Code snippet not loading properly - javascript

I'm trying to add a review snippet to a webpage after retrieving the corresponding data-id from the database. Unfortunatly the snippet doesn't work properly if I add the snippet like shown below. The snippet works fine if it is hardcoded in html but not if I add it in javascript or if I put the snippet without a data-id and then try to append the data-id attribute with the correct id.
I've tried loading my ajax call to the database in a script next to the div's location to then simply use document.write() but without success. The snippet in use is a review snippet from Mobials.
Help is greatly appreciated.
<div id="mobials"> </div>
<script type="text/javascript" src="//api.mobials.com/assets/js/api/v1.js"></script>
<script type="text/javascript" src="https://mobials.com/assets/js/api/review.min.js"></script>
function Submit() {
if (validateInputs()) {
$.ajax({
type: "GET",
url: "#ViewBag.urlApi" +"LocationDetails?zipcode=" + $("#ZipCodeLoc").val() + "&format=JSON&authoriazation={"+"#ViewBag.ApiKey"+"}",
dataType: "jsonp",
traditional: true,
success: function (data) {
$("#events").empty();
$("#logos").empty();
$("#openingHours").empty();
locationDetails = JSON.parse(data);
//Customer Reviews
var isMobial = false;
$.each(locationDetails.Reviews, function (key, value) {
if(key == "Type" && value == 1){
isMobial = true;
$("#consumerAffairs").hide();
}
if(key == "ReviewCode" && isMobial){
var mob = document.getElementById("mobials");
mob.innerHTML += '<div class="mobials-root" data-id="'+value.reviewcode+'" data-language="en" data-type="badge" data-size="200"></div>';
}
});
}};
}
}
EDIT: This line in my .html:
<div class="mobials-root" data-id="someId" data-language="en" data-type="badge" data-size="200"></div>
Looks like this when loaded:
<div class="mobials-root" data-id="someId" data-language="en" data-type="badge" data-size="200" data-tracker="1" id="mobial-root-1"><img src="https://s3.amazonaws.com/mobials.com/api/badges/read_reviews/en/174_174_4.7_70.png"></div>

You can't use document.write() with ajax calls.
document.write() will work "as expected" only as long as the document is open. As soon as the browser recognizes that the document is loaded completely, the document is closed.
Subsequent calls to document.write() will replace the document rather than append to it.
Edit: but looking at your code, I don't see document.write() at all.

Related

AJAX success not render properly since second request

I use ajax to render output to below HTML element.
<p class="result-box" id="result-box">The result is : <br><strong id="result"></strong></p>
Everything works fine when rendering result for the 1st input request.
When I update my input, the console changes and prints desired data but the webpage including the text does not change.
I get Cannot read property 'setAttribute' of null at canvas_and_ploton the 2nd+ time refresh below, If I remove setAttribute, I get Cannot read property 'getAttribute' of null at canvas_and_plot.
$(document).on('submit','#cat_select',function(e){
e.preventDefault();
$.ajax({
type:'POST',
url:'/cat_select',
data:{
l2:$('#l2').val(),
l3:$('#l3').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
success: function server_response(response) {
const r = JSON.parse(response);
console.log(r); //updated
var cat_result = r.cat_result;
console.log(cat_result[0]) //updated
var text=$('<i></i>');
$.each(cat_result, function(idx, value) {
text.append('<id="result'+idx+'">' + cat_result[idx][0]+ '<br>'); //even the text output are not updated
text.append('<canvas id="canv_'+idx+'" width="200" height="200"></canvas><br>');
});
$('#result').replaceWith(text);
$.each(cat_result, function(idx, value) {
canvas_and_plot(idx,cat_result[idx][9],cat_result[idx][10],cat_result[idx][11])});
}
function canvas_and_plot(idx,a,b,c) {
var canv = document.getElementById('canv_'+idx);
canv.setAttribute('id', 'canv_'+idx);
var C = document.getElementById(canv.getAttribute('id'));
//plot...
}
I tried adding cache: false and adding random number to the url but neither of them works.
Why only error after the first request? How can I fix this? Thanks
The reason for it not changing is that you are replacing your block #result with received data.
$('#result').replaceWith(text);
After which you'll a dom tree that looks something like this:
<p class="result-box" id="result-box">
The result is : <br>
<i>
<id="result123">...<br>
<canvas id="canv123" width="200" height="200"></canvas><br>
<id="result321">...<br>
<canvas id="canv321" width="200" height="200"></canvas><br>
</i>
</p>
So the second time you click there is no element with #result id.
I suggest (as a rough and quick solution):
On every request remove all children of your #result element and fill it again with new data. So add this line before making the request - $('#result').empty(); and replace $('#result').replaceWith(text); with $('#result').append(text);
The main idea is to keep the place you put and add your server data. Hope this helps!

jQuery Remove part of the HTML and append new HTML

We have approval with our client, just a heads up to cover me in any way.
We are needing to modify some of the code in a clients site if a cookie is seen on their computer, the client's site is in ASPX format. I have the first part of the code created, but where I am getting stuck is this:
I need to remove the last 2000 characters (or so) of the body of the page, then append the new HTML to it.
I tried:
$('body').html().substring(0, 10050)
but that doesn't work, I also tried copying that HTML (which did work) and put it back with the new code, but it created a loop of the script running.
Any suggestions on what I should do? It has to be javascript/jQuery sadly.
//////// EDIT ////////////
My script is brought in by Google Tag Manager, and added to the page at the bottom, then my script runs, this is what was causing the loop in the script. Basically, here is the setup:
My Script on my server is loaded into the client site using Google Tag Manager, added to the bottom of the page. From there it is able to execute, but when doing this, it creates a loop of adding the Google Tag Manager script, causing my code to re-add, causing it to re-execute again.
The client is not willing to do anything, he has pretty much told us to just figure it out, and to not involve his web guy.
This is the code straight from their site I am trying to edit.
<script language="JavaScript">
jQuery(function($){
$('#txtPhone').mask('(999) 999-9999? x99999');
$('#submit').click(function(){CheckForm();});
});
function CheckForm(theForm){
if (!validRequired($('#txtfirst_name'),'First Name')){ return false; }
if (!validRequired($('#txtlast_name'),'Last Name')){ return false; }
if (!validRequired($('#txtEmail'),'E-Mail Address')){ return false; }
if (!validEmail($('#txtEmail'),'E-Mail Address',true)){ return false; }
if (!validPhone($('#txtPhone'),'Phone Number')){ return false; }
var dataList='fa=create_lead';
dataList += '&name=' + $('#txtfirst_name').val();
dataList += '&lastname=' +$('#txtlast_name').val();
dataList += '&email=' + $('#txtEmail').val();
dataList += '&phone=' + $('#txtPhone').val();
dataList += '&vid=' + dealerOnPoiVisitId;
dataList += '&cid=' + dealerOnPoiClientId;
dataList += '&leadType=9';
dataList += '&leadSrc=32'; ////////////////////// THIS IS WHAT I AM ATTEMPTING TO CHANGE /////////////////////////
dataList += '&contactname=' + $('#contactname').val();
dataList += '&comment=' + encodeURIComponent($('#txtComments').val());
dataList += '&dvc=' +encodeURIComponent(DealerOn_Base64.encode($('#txtfirst_name').val() + $('#txtEmail').val()));
var lid=1;
$('#submit').prop('disabled', true);
$.ajax({
url:'/lead.aspx',
data: dataList,
dataType: 'json',
success: function(data){
$('#submit').prop('disabled', false);
lid=data.leadid;
if (lid > 1){
$('#submit').prop('disabled', false);
var jqxhr = $.post('/lead.aspx?fa=complete_lead&leadid=' + lid , function() {
window.location.href='/thankyou.aspx?name=' + $('#txtfirst_name').val() + '&lid=' + data.leadid;
});
}
},
error: function(request,error) {
$('#submit').prop('disabled', false);
}
});
}
</script>
This is the page on the site: www.moremazda.com/contactus.aspx
You have to add the HTML back:
var html = $('body').html().substring(0, 10050);
$('body').html(html);
Note that doing this, and just randomly removing chunks of HTML is not good practice, and could lead to a number of problems.
Technically you should be able to do this:
var bodyHTML = $('body');
bodyHTML.html(bodyHTML.html().substring(2000));
But as I pointed out in my comment above, that is a REALLY BAD idea.
If you have access to the HTML to the page, wrap the code you want to replace in a identifiable tag and remove that. I.e.:
<div id="tobeRemoved">Lorem Ipsum</div>
<script>
$('#toBeRemoved').empty();
</script>
If you can't edit the HTML, but you know that it is always the last script tag, you could do something like this:
var scripts = $('script');
scripts.get(-1).remove;

jquery load content into script tag in firefox

I have an html page using jquery 1.7.2. Within the page I have a scrip tag like so.
<script id="navigation-template" type="text/x-handlebars-template"></script>
Further down the page I'm using javascript to load my handlebars template into the script tag using the following function:
loadTemplate: function( templateId, elementId ) {
if ( !elementId ) {
elementId = templateId;
}
$('#'+elementId).load('/my/path/templates.html #'+templateId);
}
This is working fine in chrome, the eclipse browser, and even IE 9 but seems to go south in Firefox.
I have debugged and the load call successfully completes and the content is returned, but a call to $('#navigation-template').html() gives an empty String.
I also had content in the script tag and called the load and saw that it was replaced by the empty string after the .load call.
Finally, if I manually perform $('#navigation-template').html( "hello" ); I see that the .html() for the script tag is changed.
If I go to a simple ajax get then I will have to parse it and get the given element rather than relying on load to get the element for me.
How do I get around this issue in firefox?
Here is the function I use for such purposes:
Util.loadTemplates = function(ExternalTemplates) {
$.each(ExternalTemplates, function(index, value){
var scriptUrl = value;
$.ajax({
url: scriptUrl,
dataType: 'text',
success: function(res){
var templateName = value.slice(value.lastIndexOf('/') + 1, value.lastIndexOf('.'));
TEMPLATES[templateName] = Handlebars.compile(res);
}
});
});
}
var ExternalTemplates = [
'templates/application.hbs',
'templates/people.hbs'
];
But it is better to look into doing the compiling, which turns the template into a function, before the page is sent to the client.
You are using the type as this
<script id="navigation-template" type="text/x-handlebars-template"></script>
Try changing the type to
<script id="navigation-template" type="text/javascript"></script>
One thing I liked about load() was that I could store all my templates in a single file and use load to select the div for the template I was interested in. I wrote a method that will load the template file and store the templates into a map of template name to template source and compiled template. I compile the template on the first access so that I don't needlessly compile all the templates every time, but only compile the ones I need when needed. It looks something like this:
var myTemplateHelperThingy = {
loadTemplates: function() {
$.get( '/my/path/templates.html' )
.done(function(data) {
var elements = $(data);
$( 'div.template-marker-class', elements).each( function( index, element ) {
// need to use element instead of 'this' because IE is st00pid.
var content = $(element)[0].outerHTML; // trick from StackOverflow
myAppObject.pageTemplates[this.id] = {
source: content,
template: null
};
});
});
},
getTemplate: function( name ) {
// get a compiled template, compiling it if necessary.
var result = myAppObject.pageTemplates[name].template;
if (!result) {
myAppObject.pageTemplates[name].template = Handlebars.compile(myAppObject.pageTemplates[name].source);
}
return myAppObject.pageTemplates[name].template;
},
evalTemplate: function( data, templateName ) {
var template = myAppObject.getTemplate(templateName);
if (template) {
return template(data);
}
else {
// message to user here that something went wrong.
}
},
showTemplate: function( targetElement, data, templateName ) {
$(targetElement).html(bi.evalTemplate( data, templateName ));
}
}
And templates.html looks like:
<html>
<body>
<div id="templates-wrapper-do-not-remove-or-jquery-will-not-find-the-templates">
<div id="my-first-template" class="template-marker-class other-class">
<!-- a bunch of content -->
</div>
<div id="my-second-template" class="template-marker-class another-class">
<!-- more content -->
</div>
</div>
</body>
</html>

Change javascript onclick event to jquery click and still pass parameters

I think I may be missing something or haven't grasped a fundamental of jQuery. I have searched for hours but yet to find an answer to my question.
I've got an old website that I'm upgrading to use jQuery and many of the links call a JavaScript onClick call that passes multiple parameters, as per the example below:
View Details
The problem is that I've updated the old displayData function with various jQuery code and the displayData function is within the
$(document).ready(function() {
});
code, and this seems to prevent the function displayData being called using the onClick as it says object expected. I've moved the displayData function out from the $(document).ready() but by doing so, this has prevented references to other functions within the $(document).ready() code being referenced.
A cut down example of what I have is below:
<script>
$(document).ready(function() {
function displayData(title, isbn, dt, price) {
// there's a call to jQuery AJAX here
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "WebServices/BookService.asmx/GetBookReviews",
data: "{isbn: '" + isbn + "'}",
dataType: "json",
success: function(msg) {
DisplayReviews(msg.d);
}
});
return false;
}
function DisplayReviews(data) {
// data normally formatted here and passed to formattedData variable
var formattedData = FormatData(data);
$('#reviewScreen').html(formattedData);
}
function FormatData(data) {
// function reformats data... code removed for space..
return data;
}
});
</script>
<table>
<tr><td>View Reviews</td><td>Book Title</td></tr>
<tr><td>View Reviews</td><td>Book Title 2</td></tr>
</table>
What I'd like to do is to be able to remove the onclick="displayData();" within the link and instead us a jQuery click reference, something like
$('a.reviewLink').click(function() {
displayData(parameters go here....);
});
I just don't know how I'd pass the parameters to the function from the link as they would not longer be in the HTML onclick attribute.
If I continue to use the onclick attribute in the link, and move the displayData(params) out of the $(document).ready() code block, it works fine, but the moment I try and reference any of the other functions within the $(document).ready() code block I get the dreaded object expected error with the other functions such as DisplayReviews(param).
I don't know if this makes any sense.... sorry if it's confusing, I'm not the worlds best programmer and don't know all the terminology necessarily, so have tried as best I can to explain. I hope you can help.
Many thanks
The init code should go into the .ready(), not your library functions, those can be defined in a seperate .js file.
<script src="yourFunctions.js"></script>
<script>
$(document).ready(function(){
$('a.reviewLink').click(function() {
displayData(parameters go here....); // in yourFunctions.js
});
});
</script>
An alternative to passing inline parameters without using inline javascript, is to use HTML5's 'data-' attribute on tags. You can use it in xhtml, html etc as well and it just works.
html:
<div data-name="Jack" data-lastname="black">My name is</div>
jquery:
$('div').click(function(){
alert($(this).attr('data-name') + ' ' + $(this).attr('data-lastname'));
});
Note: You HAVE to use either jQuery's .attr() or native .getAttribute() method to retreive 'data-' values.
I use 'data-' myself all the time.
As pointed out by Skilldrick, displayData doesn't need to be defined inside your document ready wrapper (and probably shouldn't be).
You are correct in wanting to use the jQuery click event assignment rather than onClick - it makes your code easier to read, and is required by the principle of Unobtrusive Javascript.
As for those parameters that you want to pass, there are a few ways to go about the task. If you are not concerned with XHTML compliance, you could simply put some custom attributes on your link and then access them from your script. For example:
View Details
And then in your click event:
$('a.reviewLink').click(function() {
var booktitle = $(this).attr('booktitle');
var isbn = $(this).attr('isbn');
var pubdate = $(this).attr('pubdate');
var price = $(this).attr('price');
displayData(booktitle, isbn, pubdate, price);
});
I'm sure someone on here will decry that method as the darkest evil, but it has worked well for me in the past. Alternatively, you could follow each link with a hidden set of data, like so:
View Details
<ul class="book-data">
<li class="book-title">Book Title</li>
<li class="book-isbn">ISBN</li>
<li class="book-pubdate">Publish Date</li>
<li class="book-price">Price</li>
</ul>
Create a CSS rule to hide the data list: .book-data { display: none; }, and then in your click event:
$('a.reviewLink').click(function() {
var $bookData = $(this).next('.book-data');
var booktitle = $bookData.children('.book-title').text();
var isbn = $bookData.children('.book-isbn').text();
var pubdate = $bookData.children('.book-pubdate').text();
var price = $bookData.children('.book-price').text();
displayData(booktitle, isbn, pubdate, price);
});
There are lots of ways to accomplish your task, but those are the two that spring most quickly to mind.
I worked this up, so even though the question is answered, someone else might find it helpful.
http://jsbin.com/axidu3
HTML
<table border="0" cellspacing="5" cellpadding="5">
<tr>
<td>
View Reviews
<div class="displayData">
<span class="title">Book Title 2</span>
<span class="isbn">516AHGN1515</span>
<span class="pubdata">1999-05-08</span>
<span class="price">$25.00</span>
</div>
</td>
<td>Book Title 2</td>
</tr>
</table>
JavaScript
<script type="text/javascript" charset="utf-8">
jQuery(".reviewLink").click(function() {
var title = jQuery(".title", this.parent).text();
var isbn = jQuery(".isbn", this.parent).text();
var pubdata = jQuery(".pubdata", this.parent).text();
var price = jQuery(".price", this.parent).text();
displayData(title, isbn, pubdata, price);
});
function displayData(title, isbn, pubdata, price) {
alert(title +" "+ isbn +" "+ pubdata +" "+ price);
}
</script>
CSS
<style type="text/css" media="screen">
.displayData {
display: none;
}
</style>

jQuery / javascript and nested if statements

I have a multi-lingual page where I want to display form validation error in the user's language. I use a hidden input to determine which language version the user is browsing like this: <input type="hidden" name="lang" id="lang" value="<?php echo $lang; ?>" />
The PHP side of the script works, but jQuery doesn't seem to realize which language is passed on. It displays the English error message no matter on which language site I am.
Here's the code (I removed the other form fields for length):
$(document).ready(function(){
$('#contact').submit(function() {
$(".form_message").hide();
var emailReg = /^([\w-\.]+#([\w-]+\.)+[\w-]{2,4})?$/;
var lang = $("#lang").val();
var name = $("#name").val();
var dataString = {
'lang': lang,
'name': name
}
if (name == '') {
if (lang == 'de') {
$("#posted").after('<div class="form_message"><p><span class="error">Fehler:</span> Bitte gib deinen Namen an!</p></div>');
} else {
$("#posted").after('<div class="form_message"><p><span class="error">Error:</span> Please enter your name!</p></div>');
}
$("#name").focus();
$("#name").addClass('req');
} else {
$("#loading").show();
$("#loading").fadeIn(400).html('<img src="/img/loading.gif" />Loading...');
$.ajax({
type: "POST",
url: "/contact-post.php",
data: dataString,
cache: false,
success: function(html){
$("#loading").hide();
$("#posted").after('<div class="form_message"><p>Thank you! Your contact request has been sent.</p></div>');
$("#contact input:submit").attr("disabled", "disabled").val("Success!");
}
});
}return false;
}); });
The problem seems to be somewhere in the nested if statement. Does jQuery / javascript even recognize nested ifs? And if yes, why is it not working?
Does jQuery / javascript even recnogize nested ifs?
Yes they do
One thing worth checking that would cause this behaviour is that you don't have any other elements on your page with id = lang. If there are, your $("#lang") selector will only find the first one, and if that's not your hidden input it won't work as you expect.
Javascript is case-sensitive, and perhaps the value of your #lang element is in a different case. You can force it to be lowered like this...
var lang = $("#lang").val().toLowerCase();
Why wouldn't it recognize nested if's?
Can you include the HTML for the page? There doesn't appear to be anything wrong with this javascript at all - so I have a feeling the issue is with the rest of the page.
Barring that, put an alert(lang) in right before your if statement to see what it is set to. My guess is that it will not be set to the value that you think it should be set to.
Check the value
alert("'" + lang + "' :" + lang.length);

Categories