Dynamic script loading works first time but not thereafter - javascript

I have contact page on my website where I have various social network links (plus an e-mail form) with links at the side to select each one. Clicking a link makes an ajax request to the server, and on success replaces the html of a common div with the response.
Each one has a javascript file associated with it, and this is added as a script tag in the document head on ajax success.
These scripts should evaluate on each load and prepare the DOM in the response. However, I am finding that the first click works perfectly, the script is loaded and executes, but when I go to click on another link, it loads the new script but it never seems to execute. And none of those dynamically loaded scripts work thereafter.
The ajax call for loading each option is bound to each link's click event here:
$('.socialLink').click(function() {
var id = $(this).prop('id').toLowerCase();
var callingObj = $(this);
$.ajax({
url: "./socialMedia/" + id + ".php",
success: function(msg) {
$('.socialLink').css('opacity', '0.4');
$('.socialLink').data('active', false);
callingObj.css('opacity', '0.9');
callingObj.data('active', true);
if ($('#Feed').css('display') !== 'none') {
$('#Feed').slideToggle(400, function() {
$('#Feed').html(msg);
});
}
else
{
$('#Feed').html(msg);
}
$('#Feed').slideToggle(400);
$.getScript('./script/' + id + '.js');
}
});
});
The thing is, I dynamically load scripts for each page on the site, too... and don't seem to have any problems with that.
You can see the page I am talking about if you go here http://www.luketimoth.me/contact.me. Only two options actually load any javascript at the moment, the e-mail and twitter ones... the rest are empty js files with only a single comment inside.
EDIT: I am now using jQuery getScript()... I have changed the code above to reflect this. The scripts I am trying to load, which are not working as exepcted, are:
twitter.js (just the standard code twitter gives you for one of their widgets):
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.
js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
email.js:
$('#Send').click(function() {
var senderName = $('#YourName').val();
var senderEmail = $('#Email').val();
var emailSubject = $('#Subject').val();
var emailBody = $('#EmailBody').val();
$.ajax({
url:'./script/sendMail.php',
data: {
name: senderName,
email: senderEmail,
subject: emailSubject,
body: emailBody
},
type: "POST",
success: function(msg) {
$('#success').html(msg);
}
});
});
$('input, textarea').focus(function() {
if (this.value === this.defaultValue) {
this.value = '';
}
});
$('input, textarea').focusout(function() {
if (!this.value.length) {
this.value = this.defaultValue;
}
});

Thanks for all the comments and suggestions. I decided in the end to load everything in the background rather than make an ajax request every single time.
It's actually a much more responsive page now... admittedly at the cost of having unused DOM elements in the background. Given how much faster it is, though, I think the trade-off is acceptable.

Related

Is it possible to use jQuery on a new window?

I've been trying to solve this problem for hours now maybe anyone of you could help me.
Right now my Code looks like this:
$('.clickable').on('click', function() {
var id = $(this).attr('data-packages');
id = "'" + id + "'";
$.ajax({
url: "show.php",
data: {
type: "showSFM",
data: id,
user: username
},
type: "POST",
success: function(data) {
$('#main').html(data);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Everything is working fine but I was asking myself If it is possible to use $('#main').html(data) on a new Window. Right now if I click an Element the current window is showing the result but I want a new tab to pop up with the result.
I was trying things like this:
success: function(data) {
var url = location.href;
var window = window.open(url);
window.document.getElementById('main').innerHTML = data;
}
The result I'm getting is that the window opens on the main page. Looks like window.open(url) works just fine but the line below does nothing.
The reason this likely doesn't work is due to the fact that you use:
window.document.getElementById('main')
The window might already be opened by the line before, but is most likely not loaded and doesn't contain an element with id main yet (since making a HTTP(S) request takes time). This could be solved by moving the filling of main element into a callback.
window.addEventListener('load', function () {
window.document.getElementById('main').innerHTML = data;
}, { once: true });
You can send the data you need for the request in the URL and then on the new page, you can send the AJAX request again, and getting the data you need for it from the URL.

Javascript does not run after aspx page has been loaded

I created a site in Visual Studio 2015 Community Edition starting with the ASP.NET Empty Web Site template. Recently, I needed to add authentication features, so I created a new ASP.NET Web Forms site, and moved all of my pages/files/entire site created in the empty web site to this new Web Forms site template.
Everything works perfectly--except that none of the javascript that used to update my pages dynamically continue to work. All of the javascript functions that previously worked seem to be completely ignored. (I haven't changed anything in the HTML or Javascript code -- the only thing that changed was the ASP.NET template I began with). Even something as simple as tagging the navigation menu to be active will not work, for example:
<script type="text/javascript">
$(function() {
// this will get the full URL at the address bar
var url = window.location.href;
// passes on every "a" tag
$(".Navigation a").each(function() {
// checks if its the same on the address bar
if (url == (this.href)) {
$(this).closest("li").addClass("active");
}
});
});
</script>
This worked perfectly to highlight the active menu previously, but no longer works in the new Web Forms site template. I've also tried moving it from the file header, to the content, and even to a separately referenced file with no avail.
Is there an assembly I need to add to my new project, or is there a global setting in this ASP.NET Web Forms template that could be blocking my javascript from working? Any help would be greatly appreciated. I've been stuck on this problem for over a week now.
Edit: here's a better example to see if I'm missing something more obvious:
This worked previously to dynamically load more information from a database after a page was loaded and the user scrolled to the bottom. The javascript still works to display a message box when the user hits the bottom of the page, but the Web Method in the c# code behind never gets called...
var pageIndex = 1;
var pageCount;
$(window).scroll(function () {
// Everytime that the user scroll reaches the bottom of the page, execute function GetRecords
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
GetRecords();
}
});
function GetRecords() {
// Local variable page index begins at 1, and each time the user scrolls to the bottom of the page
// this number is increased to mark how many times the user has hit the bottom of the page.
// This later marks how many elements have been loaded from the database.
pageIndex++;
// On first scroll, pageCount is null so pageIndex is 2, and function still needs to be executed.
if (pageIndex == 2 || pageIndex <= pageCount) {
// Display a loading bar
$("#loader").show();
window.alert("loading");
$.ajax({
// POST signals a data request
type: "POST",
// This directs which function in the c# code behind to use
url: "databaseLoadDynamic.aspx/GetCustomers",
// The paramater pageIndex, page number we need to load, to pass to GetCustomers(int pageIndex)
data: '{pageIndex: ' + pageIndex + '}',
// Type of data we are sending to the server (i.e. the pageIndex paramater)
contentType: "application/json; charset=utf-8",
// Type of data we expect back from the server (to fill into the html ultimately)
dataType: "json",
// If all goes smoothly to here, run the function that fills our html table
success: OnSuccess,
// On failure, error alert user (aka me so that I know something isn't working)
failure: function (response) {
alert(response.d);
},
error: function (response) {
alert(response.d);
}
});
}
}
Thank you so much for all of your help!

AJAX Post HTML Code

I'm having an issue with sending some HTML code using AJAX please see my code below
<iframe src="http://www.w3schools.com" width="10" height="10" id="awc_frame"></iframe>
<script>var iframe = document.getElementById("awc_frame");</script>
Here is the AJAX code below
<script>
$.ajax({
type: "POST",
url: "mobileView.php",
data: { val : iframe },
success: function(data){
console.log(data);
}
})
</script>
The code isn't sending the variable to the PHP file. Looking into the Network side of things it sends text ie if I put "" around iframe it sends this code
"val = iframe" but not the actual code within the iframe. The "var iframe"does work and pulls back the HTML code of the iframe
Please tell me what I'm doing wrongly.
Thanks in advance.
EDIT: I'm sorry. It's not the HTML code within the iFrame I need to send, It's the entire iFrame code I need to send.
Another Edit: What I'm trying to accomplish when a visitor from my company goes to my website I would like Javascript or Jquery to load an internal website from the visitors computer and then have all of the code from that website that's on the client's end to be sent to a Server which will store the entire iFrame code in a database.
This would send the entire html inside the iframe.
var iframe = $('#awc_frame').html();
First of all, var iframe does not contain HTML of the iframe element - it contains a DOM Node, which is kind of a wrapper around the iframe element (it contains various properties of that element, including the HTML).
Next thing, you probably want to wait for the iframe to completely load all the contents, so you'll have to bind to the load event of it.
Something like this should work:
var $iframe = $("#awc_frame");
$iframe.on("load", function () {
var iframeHTML = $iframe[0].contentWindow.document.body.innerHTML;
// jQuery alternative
var iframeHTML = $iframe.contents().find("body").html();
$.ajax({
type: "POST",
url: "mobileView.php",
data: {
val: iframeHTML
},
success: function(data){
console.log(data);
}
});
});
Super important thing in this example
Just one more thing - please note that for websites outside of your own domain, this code won't work (due to Same Origin Policy). Any other code won't work too.
Since javascript has problems with getting the HTML from a cross-domain iframe, you can't do this across domains. However, why not just send the iframe's src attribute to the PHP page, and then just use file_get_contents to get the HTML, and then store that? Problem solved:
Javascript:
var iframe = $('#awc_frame').prop('src');
$.ajax({
type: "POST",
url: "posttest.php",
data: { val : iframe },
success: function(data){
console.log(data);
}
});
PHP:
$html = file_get_contents($_POST['val']);
what are you trying to do?
var iframe = document.getElementById("awc_frame");
above code is an javascript object of your iframe which contains a lot of properties.. since you are using jQuery, you could get that with:
var iframe = $('#awc_frame');
keep in mind that above code is the element it self in jquery object format you could get element object like this:
var iframe = $('#awc_frame')[0];
** you're doing something wrong.
if you're trying to get iframe HTML content:
var iframe_contents = $("#awc_frame").contents();
if you explain more about what you are trying to do, i can update my answer to suit you.
* UPDATE *
considering what you are trying to do..
Method #1: (Easy Way)
you could use php to fetch content of the website you need:
<?php
$contents = file_get_contents('http://www.w3schools.com');
// Saving $contents to database...
?>
Method #2: (Hard Way)
as #mdziekon said, you first should wait until your iframe gets loaded then:
var iframe = $("#awc_frame");
iframe.on("load", function () {
var contents = $(this)[0].innerHTML;
$.ajax({
type: "POST",
url: "mobileView.php",
data: {
val: contents
},
success: function(data){
console.log(data);
}
});
});
hope it solves your problem

jQuery rebind click event after ajax call

I'm trying to prevent defaults on a click, call a page with ajax and trigger the click on complete, using this answer.
<a id="mylink" href="file.csv" download >Dowload</a>
<script>
var flag = false;
$('#mylink').on('click',function(e) {
// Result is the same with :
//$(document).on("click","#mylink",function(e){
if (flag === true) {
flag = false;
return;
}
e.preventDefault();
$.ajax({
url: "index.php?controller=admin&action=refreshFile",
complete: function() {
console.log('control'); // This is called
flag = true;
$('#mylink').trigger('click'); // This is not called
}
});
});
</script>
The call works but the link is not triggered after. The result is the same when the ajax call is set inside a separate function.
use window.location to call the link href
$('#mylink').on('click',function(e) {
e.preventDefault();
$.ajax({
url: "index.php?controller=admin&action=refreshFile",
complete: function() {
console.log('control'); // This is called
window.location = $('#mylink').attr("href");
}
});
});
or with one event listeners
var eventListener = function(e) {
e.preventDefault();
$.ajax({
url: "index.php?controller=admin&action=refreshFile",
complete: function() {
console.log('control'); // This is called
$('#mylink')[0].click();
$('#mylink').one('click', eventListener);
}
});
};
$('#mylink').one('click', eventListener);
I'm not sure what your flag is supposed to do. In your example it would mean the link only works every 2nd click.
P.s. Using the complete callback means it also works even when the ajax fails. You might want to change it to success.
Update
#Racil Hilan has a point: this solution is a little overkill when you could just call the link directly and return the correct file after the refreshFile action has been called.
TRy
var flag = false;
$('#mylink').on('click',function(e) {
// Result is the same with :
//$(document).on("click","#mylink",function(e){
if (flag === true) {
flag = false;
windows.location="file.csv";
}
e.preventDefault();
$.ajax({
url: "index.php?controller=admin&action=fileDownload",
complete: function() {
console.log('control'); // This is called
flag = true;
$('#mylink').trigger('click'); // This is not called
}
});
});
In my humble opinion, this is not the right design. Your Ajax is calling the index.php on the server before triggering the download. If the index.php is doing some security or critical stuff that MUST be done before allowing the user to download the file, then this design is absolutely insecure. You don't even need to be a hacker, simply copy the link file.csv and paste it in your browser's address bar, and you'll get the file without the Ajax.
You need to place the file.csv file outside your website folder (or maybe it is generated on the fly by the server code, so that' good too) and then the PHP page must run all the checks and if all run OK, it reads the file (or generate it) and returns the download to the browser (or an error message if the checks failed). This is how to secure file downloads on the server.
After doing all of that, it is a matter of preference whether you call the PHP directly from your link, or the link calls the Ajax function which in turn calls the PHP page and parse the download (this is a bit more complex, but doable). The only difference between the two methods is whether you want the page refreshed when the download (or error message) come back from the server.
If you want to take this advice, rephrase your question and select which way you want to go (i.e. direct link, or through Ajax), so we can help you.

Removing broken links in offline HTML

I have an html file with many <a> tags with href links.
I would like to have the page do nothing when these links point to an outside url (http://....) or an internal link that is broken.
The final goal is to have the html page used offline without having any broken links. Any thoughts?
I have tried using a Python script to change all links but it got very messy.
Currently I am trying to use JavaScript and calls such as $("a").click(function(event) {} to handle these clicks, but these have not been working offline.
Also, caching the pages will not be an option because they will never be opened online. In the long run, this may also need to be adapted to src attributes, and will be used in thousands of html files.
Lastly, it would be preferable to use only standard and built in libraries, as external libraries may not be accessible in the final solution.
UPDATE: This is what I have tried so far:
//Register link clicks
$("a").click(function(event) {
checkLink(this, event);
});
//Checks to see if the clicked link is available
function checkLink(link, event){
//Is this an outside link?
var outside = (link.href).indexOf("http") >= 0 || (link.href).indexOf("https") >= 0;
//Is this an internal link?
if (!outside) {
if (isInside(link.href)){
console.log("GOOD INSIDE LINK CLICKED: " + link.href);
return true;
}
else{
console.log("BROKEN INSIDE LINK CLICKED: " + link.href);
event.preventDefault();
return false;
}
}
else {
//This is outside, so stop the event
console.log("OUTSIDE LINK CLICKED: " + link.href);
event.preventDefault();
return false;
}
}
//DOESNT WORK
function isInside(link){
$.ajax({
url: link, //or your url
success: function(data){
return true;
},
error: function(data){
return false;
},
})
}
Also an example:
Outside Link : Do Nothing ('#')
Outside Link : Do Nothing ('#')
Existing Inside Link : Follow Link
Inexistent Inside Link : Do Nothing ('#')
Javascript based solution:
If you want to use javascript, you can fix your isInside() function by setting the $.ajax() to be non asynchronous. That is will cause it to wait for a response before returning. See jQuery.ajax. Pay attention to the warning that synchronous requests may temporarily lock the browser, disabling any actions while the request is active (This may be good in your case)
Also instead of doing a 'GET' which is what $.ajax() does by default, your request should be 'HEAD' (assuming your internal webserver hasn't disabled responding to this HTTP verb). 'HEAD' is like 'GET' except it doesn't return the body of the response. So it's a good way to find out if a resource exists on a web server without having to download the entire resource
// Formerly isInside. Renamed it to reflect its function.
function isWorking(link){
$.ajax({
url: link,
type: 'HEAD',
async: false,
success: function(){ return true; },
error: function(){ return false; },
})
// If we get here, it obviously did not succeed.
return false;
}
Python based solution:
If you don't mind preprocessing the html page (and even caching the result), I would go with parsing the HTML in Python using a library like BeautifulSoup.
Essentially I would find all the links on the page, and replace the href attribute of those starting with http or https with #. You can then use a library like requests to check the internal urls and update the appropriate urls as suggested.
Here is some javascript that will prevent you from going to external site:
var anchors = document.getElementsByTagName('a');
for(var i=0, ii=anchors.length; i < ii; i++){
anchors[i].addEventListener('click',function(evt){
if(this.href.slice(0,4) === "http"){
evt.preventDefault();
}
});
}
EDIT:
As far as checking if a local path is good on the client side, you would have to send and ajax call and then check the status code of the call (infamous 404). However, you can't do ajax from a static html file (e.g. file://index.html). It would need to be running on some kind of local server.
Here is another stackoverflow that talks about that issue.

Categories