I'm currently working on a project using jQuery and Ajax to load in content from local html files to my single page site. I've also got a JSON file that I'm trying to incorporate into the files being loaded in with jQuery and Ajax.
I'm using hash urls to keep the pages separate. This is the code I'm using:
//other cached links
var pageLinks = $(".pageLink");
if(window.location.hash) {
var hash = window.location.hash.replace("#", "");
loadPage(hash + ".html");
} else {
loadPage("index.html");
}
pageLinks
.click(function(){
var iid = $(this).attr("id");
loadPage(iid + ".html");
});
function loadPage(resource) {
window.location.hash = resource.replace(".html", "");
$.get("pages/" + resource, function (data) {
content.html(data);
});
}
//this makes sure the contents of hash in the url is loaded in the page
if(window.location.hash) {
var hash = window.location.hash.replace("#", "");
loadPage(hash + ".html");
} else {
loadPage("index.html");
}
This is how I'm putting my JSON data into the page:
function FooBar() {
this.foo;
this.barLinkTemplate;
}
var fooBar = new FooBar();
$(document).ready(function (){
fooBar.contentDiv = $("#fooContent");
fooBar.barDiv = $("#bars");
$.when(
$.getJSON('data/music.json'),
$.ajax('components/components.html')
).done( function(data, templateData) {
var templateHTML = $(templateData[0]);
fooBar.barLinkTemplate = Handlebars.compile( templateHTML.find("#barLinks").html() );
fooBar.data = data[0].foo;
fooBar.barDiv.html( fooBar.barLinkTemplate( data[0].bars ));
));
});
The Ajax loads just fine, hashes and all. However, nothing from my JSON file is loaded into the page. I think I've narrowed my problem down (at least I hope) to one bit of code. If I comment out the last if/else statement (above), the JSON is loaded in the first page (only the first page). If I click on any link, and I navigate back to that page, the JSON data is gone. I have to actually reload the page for the data to reappear.
Without that if/else statement, I lose the ability to load the page content from the hash in the url--though the links still work fine.
I've been googling, but I haven't seen anything similar to the problems I'm having. Any help is appreciated. Thanks!
Related
I'm trying to create a markdown editor.
So far: I have loaded the index page. I'm using fs.readdir to get the titles of all the markdown files and display them in the sidebar. Then, on clicking on of these title #content get's the content.
module.exports = (win) => {
fs.readdir( './data', (err, data) =>{
data.map(title => {
if(title.split('.md').length==2){
el = document.createElement("li"); // get gave it the title ..
el.addEventListener('click', function(e){
fs.readFile(`./data/${title}`, (err, data) => {
document.getElementById('content').innerHTML = data;
});
})
document.getElementById('titles').appendChild(el) // title are on the page
The problem is when I introduce another page
I have a preferences page
win.loadURL(path.join('file://', __dirname, '../static/preferences.html'))
It has the same sidebar, hence I import the same code to get the titles. But now when I click one of the links, I don't want document.getElementById('content').innerHTML = data; but I want to load the index page and then inject the content
So far I tried this
const checkPageState = (pageName, callback) => {
if(pageName === "preferences"){
ipcRenderer.send(GO_TO_PAGE, 'index')
}
setTimeout(callback(), 1000);
}
...
el.addEventListener('click', function(e){
checkPageState(win, ()=>{
fs.readFile(`./data/${title}`, (err, data) => {
if (err) throw err;
fileDir = `./data/${title}`;
document.getElementById('content').innerHTML = data;
});
})
})
My thinking was ipcRenderer.send(GO_TO_PAGE, 'index') would load the index page (which it does) when wait for a bit and then inject the data into the index page. It doesn't!
How can I do this?
I recently tried to do this as well and it was kinda tricky but I found something that worked:
In electron when it tries to go to another page I stop it from going to it with:
win.webContents.on('will-navigate', function (evt, url) {
evt.preventDefault();
win.webContents.executeJavaScript('makeHiddenPageIframe("' + url + '");');
});
Then it calls the makeHiddenPageIframe function defined on the page.
Then in the page I define the makeHiddenPageIframe function:
function makeHiddenPageIframe (url) {
var hiddenPage = document.createElement("iframe");
hiddenPage.setAttribute("src", url);
hiddenPage.style.display = 'none';
document.body.appendChild(hiddenPage);
hiddenPage.onload = function () {
var frameDocument = hiddenPage.document;
if (hiddenPage.contentDocument) {
frameDocument = hiddenPage.contentDocument;
} else if (hiddenPage.contentWindow) {
frameDocument = hiddenPage.contentWindow.document;
}
document.open();
document.write(frameDocument.documentElement.innerHTML);
document.close();
window.history.pushState("", document.title, url.replace('https://' + window.location.hostname, ''));
}
}
This then makes a iframe and loads the page in there then once it has loaded copy all the html from the iframe to the parent window so it seems like the switch happened instantly.
Also the window.history.pushState thing at the bottom was when you overwrite the html the url stays the same so when you reload it goes back to the original page but the window.history.pushState changes the url without reloading the page.
Any form of navigation will do the iframe load so you would keep your win.loadURL( to go to another markdown page.
The 'will-navigate' event docs.
window.history.pushState ref.
I hope this helps :)
I have two server side php scripts:
1: /addit.php - which creates a pdf file on server based on current ID given
2: /viewit.php - which downloads the pdf file to the browser window.
Both these scripts work fine btw.
However I want to combine a single onclick function to run "addit.php" and then view the file by opening the file "view.php".
So I am using the original code that was creating the file ok and then adding in a window.location but they won't work together. If I remove the window.location the first part of code works fine, If I include it, the first part stops working and only the window.location works.
Sorry for being stupid, thanks.
function download_invoice() {
$(document).on('click','.downloadit',function(id){
var current_element = $(this);
var id = $(this).attr('id');
var ida = $(this).attr('id')+"A";
var idicon = $(this).attr('id')+"icon";
$.post('myaddress/addit.php',
{ list_entry_id: id },
$("#infobox_data_button2").fadeTo(1001,.33)
);
});
window.location="myaddress/viewit.php";
};
You should move window.location="myaddress/viewit.php"; to ajax callback as below. Otherwise it fires before you get response from server.
$.post('myaddress/addit.php',
{ list_entry_id: id },
function() {
$("#infobox_data_button2").fadeTo(1001,.33);
window.location="myaddress/viewit.php";
}
);
The window.location is out of the event. While you run the ajax (asynchronous) to 'myaddress/addit.php' the redirect will occur killing the process.
You need to put the window.location in a success callback, therefore in the event.
function download_invoice() {
$(document).on('click','.downloadit',function(id){
var current_element = $(this);
var id = $(this).attr('id');
var ida = $(this).attr('id')+"A";
var idicon = $(this).attr('id')+"icon";
$.post('myaddress/addit.php', { list_entry_id: id }, function(data){
$("#infobox_data_button2").fadeTo(1001,.33);
// Here!
window.location="myaddress/viewit.php";
});
});
// Abandoned
//window.location="myaddress/viewit.php";
};
I am new to working with AJAX and have some experience with Java/Jquery. I have been looking around for an solution to my problem but i cant seem to find any.
I am trying to build a function in a webshop where the product will appear in a popup window instead of loading a new page.
I got it working by using this code:
$(".product-slot a").live('click', function() {
var myUrl = $(this).attr("href") + " #product-content";
$("#product-overlay-inner").load(myUrl, function() {
});
$("#product-overlay").fadeIn();
return false;
});
product-slot a = Link to the product in the category page.
product-content = the div i want to insert in the popup from the product page.
product-overlay-inner = The popup window.
product-overlay = The popup wrapper.
The problem that i now have is that my Javascript/Jquery isnt working in the productpopup. For example the lightbox for the product image or the button to add product to shoppingcart doesnt work. Is there anyway to make the javascript work inside the loaded content or to load javascript into the popup?
I hope you can understand what my problem is!
Thank you in advance!
EDIT: The platform im using has jquery-ui-1.7.2
I know this is an old thread but I've been working on a similar process with the same script loading problem and thought I'd share my version as another option.
I have a basic route handler for when a user clicks an anchor/button etc that I use to swap out the main content area of the site, in this example it's the ".page" class.
I then use a function to make an ajax call to get the html content as a partial, at the moment they are php files and they do some preliminary rendering server side to build the html but this isn't necessary.
The callback handles placing the new html and as I know what script I need I just append it to the bottom in a script tag created on the fly. If I have an error at the server I pass this back as content which may be just a key word that I can use to trigger a custom js method to print something more meaningful to the page.
here's a basic implementation based on the register route handler:
var register = function(){
$(".page").html("");
// use the getText ajax function to get the page content:
getText('partials/register.php', function(content) {
$(".page").html(content);
var script = document.createElement('script');
script.src = "js/register.js";
$(".page").append(script);
});
};
/******************************************
* Ajax helpers
******************************************/
// Issue a Http GET request for the contents of the specified Url.
// when the response arrives successfully, verify it's plain text
// and if so, pass it to the specified callback function
function getText(url, callback) {
var request = new XMLHttpRequest();
request.open("GET", url);
request.onreadystatechange = function() {
// if the request is complete and was successful -
if (request.readyState === 4 && request.status === 200) {
// check the content type:
var type = request.getResponseHeader("Content-Type");
if (type.match(/^text/)) {
callback(request.responseText);
}
}
};
// send it:
request.send(null); // nothing to send on GET requests.
}
I find this a good way to 'module-ize' my code into partial views and separated JavaScript files that can be swapped in/out of the page easily.
I will be working on a way to make this more dynamic and even cache these 'modules' for repeated use in an SPA scenario.
I'm relatively new to web dev so if you can see any problems with this or a safer/better way to do it I'm all ears :)
Yes you can load Javascript from a dynamic page, but not with load() as load strips any Javascript and inserts the raw HTML.
Solution: pull down raw page with a get and reattach any Javascript blocks.
Apologies that this is in Typescript, but you should get the idea (if anything, strongly-typed TypeScript is easier to read than plain Javascript):
_loadIntoPanel(panel: JQuery, url: string, callback?: { (): void; })
{
// Regular expression to match <script>...</script> block
var re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
var scripts: string = "";
var match;
// Do an async AJAX get
$.ajax({
url: url,
type: "get",
success: function (data: string, status: string, xhr)
{
while (match = re.exec(data))
{
if (match[1] != "")
{
// TODO: Any extra work here to eliminate existing scripts from being inserted
scripts += match[0];
}
}
// Replace the contents of the panel
//panel.html(data);
// If you only want part of the loaded view (assuming it is not a partial view)
// using something like
panel.html($(data).find('#product-content'));
// Add the scripts - will evaluate immediately - beware of any onload code
panel.append(scripts);
if (callback) { callback(); }
},
error: function (xhr, status, error)
{
alert(error);
}
});
}
Plain JQuery/Javascript version with hooks:
It will go something like:
var _loadFormIntoPanel = function (panel, url, callback) {
var that = this;
var re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
var scripts = "";
var match;
$.ajax({
url: url,
type: "get",
success: function (data, status, xhr) {
while(match = re.exec(data)) {
if(match[1] != "") {
// TODO: Any extra work here to eliminate existing scripts from being inserted
scripts += match[0];
}
}
panel.html(data);
panel.append(scripts);
if(callback) {
callback();
}
},
error: function (xhr, status, error) {
alert(error);
}
});
};
$(".product-slot a").live('click', function() {
var myUrl = $(this).attr("href") + " #product-content";
_loadFormIntoPanel($("#product-overlay-inner"), myUrl, function() {
// Now do extra stuff to loaded panel here
});
$("#product-overlay").fadeIn();
return false;
});
I have a dynamic page which uses an AJAX request kicked off by jQuery to pull in HTML elements from the server and insert them into the DOM.
The problem is that when I have elements within the response, they are stripped out.
For instance, if I request the following from the server:
<!-- content.html -->
<div>
There is some content here!
<script>
manipulateContent();
</script>
</div>
What actually gets injected into my dynamic page is the following:
<!-- content.html -->
<div>
There is some content here!
</div>
I have tested in Chrome, Firefox, and Safari with identical results.
The relevant Javascript which creates the AJAX request is here:
function loadContent(url){
var a = document.createElement('a');
a.href = url;
if (a.search == ""){
url = url + "?trim=true";
} else {
url = url + "&trim=true";
}
var ch = $('#content-container').height();
// var wh = $(window).height();
$("#content").animate({top: '-='+ch+'px'}, 500, function(){
$.get(url, function(data){
$("body").scrollTop(0);
$("#content").html(data);
$("#content").css({top: ch+'px'});
$("#content").animate({top: '0px'}, 500);
});
});
}
$(document).ready(function(){
// get the current path and save it for later
var currentPage = location.pathname+location.search;
$(".content-link").live("click", function(){
// using the HTML5 history API, add the requested path
// to the browser history, then load the new content
history.pushState({ path: this.path }, '', this.href);
// because the page is not reloaded, $(document).ready()
// is not called, so the currentPath must be updated manually
currentPage = this.href;
loadContent(currentPage);
return false;
});
window.addEventListener('popstate', function() {
// compare the current path to the one being loaded
// if they are different, then load the content
// else, nothing happens
if (currentPage != location.pathname+location.search){
// because the page is not reloaded, $(document).ready()
// is not called, so the currentPath must be updated manually
currentPage = location.pathname+location.search;
loadContent(currentPage);
}
});
});
How can I tell jQuery to include the tags in the response? I've tried browsing through the jQuery docs without much luck, or even mention of the fact that the tags are stripped out. Perhaps I'm just not looking in the right places.
You need to use load, since the whole purpose here is to load hml content to a element.
function loadContent(url) {
var a = document.createElement('a');
a.href = url;
if (a.search == "") {
url = url + "?trim=true";
} else {
url = url + "&trim=true";
}
var ch = $('#content-container').height();
// var wh = $(window).height();
$("#content").animate({
top : '-=' + ch + 'px'
}, 500, function() {
$("#content").load(url, function() {
$("body").scrollTop(0);
$("#content").css({
top : ch + 'px'
});
$("#content").animate({
top : '0px'
}, 500);
});
});
}
According to jQuery documentation (http://api.jquery.com/jQuery.ajax/) if dataType option is html:
Returns HTML as plain text; included script tags are evaluated when
inserted in the DOM.
By default this option is set to Intelligent Guess, so you may want to check the type of response from the server.
Im trying to run a function when I load a ajax page.
In index.html Im loading page1.html, and in page1.html I have a function that I want to run when the page is loaded.
I have tryed many things but no luck.
Lets say I just want to run a function with an alert in it, how would that look?
Thanks!
Im using jquery to get the page1.html.
In page1.html I have the following code to get some albums from facebook, and I simply want to run the code when the page is loading?
alert('onload');
//get album name
FB.api('/1424613333333/albums', function(response) {
if (response && response.data && response.data.length){
var ul = document.getElementById('fb-albumslist');
for (var i=0, l=response.data.length; i<l; i++) {
if (response.data !== "undefined"){
var
album = response.data[i],
li = document.createElement('li'),
a = document.createElement('a');
if(!album.link) continue;
a.innerHTML = album.name;
a.href = album.link;
li.appendChild(a);
ul.appendChild(li);
}
}
}
});
FB.XFBML.parse( document.getElementById('fb-albumslist') );
}
And Im using this to load the ajax pages:
function loadPage(url) {
$('#guiden_menyn').load('manmade/guiden/guiden_menyn.html #content', hijackLinks);
$('#container').load(url + ' #content', hijackLinks);
}
function hijackLinks() {
$('#guiden_menyn a').click(function(e){
e.preventDefault();
loadPage(e.target.href);
});
}
I think it's impossible. But you can call function manually after ajax
Try using jquery load (http://api.jquery.com/load/). It gives a callback to after the load has completed
This is one way - parse the response, extract the scripts, and then eval them
Execute JavaScript within responseHTML