Injecting javascript and HTML using AJAX - javascript

First of all I would like to say that while this is the first time i post here these boards have helped me much.
With that said, I have got a strange issue regarding AJAX and scripts.
You see, in my web application i used custome JS context menus. Now each of them menus is implemented with specific features depending on the object and if the object exists.
E.x : if we got an upper menu place holder but no upper menu the context menu will have one option which is "add menu".
But say we already have the upper menu the context menu will have different options such as "edit menu" etc...
so far so good, however, say we have an upper menu place holder and no menu and then we added the menu (still no refresh on the page) i need to generate a new context menu and inject it right? so i do just that along with the new menu i just built.
all that code goes into the SAME div where the old context menu script and upper menu place holder were so basicaly they are overwriten.
Now the menu itself is in HTML so it overrides the current code the JS however acts wierd and will show now 2 context menus the old one and the new one even though i overwrite it's code.
I need to some how get rid of the old context menu script without refreshing the page.
Any ideas?
P.S
all the JS are dynamicaly generated if that makes any difference (i dont think it does.)

Well after some head breaking i figured it out..
(the problem not the solution yet) this is the ajax function right?
$.ajax({
type: "GET",
url: "../../../Tier1/EditZone/Generate.aspx?Item=contentholder&Script=true",
dataType: "html",
success: function (data) {
$('#CPH_Body_1_content_holder').html(data);
}
});
now they function uses a page with an event handler, that event handler reutnrs the data as followed response.write(answer) it just hit me that when you use response.write it sends the code after it's been compiled and ran in our case at page Generate.aspx.
so the script will run but not in the page i intended it to run and because of that i cannot overwrite it... how silly of me.
what i think ill do it return the data as an actualy string and then and only then inject the code into the container div.
ill let you folks know if that works out.
cheers and thanks for the advice these forums rock.

No matter what anyone says, do not use EVAL. It's evil and will give you memory issues if used more than a few times on a page.
See my soluition here: trying to call js code that is passed back from ajax call
Basically, create a div with the ID of "codeHolder" and voila. You'll basically want to pass your HTML and JS back to the AJAX receiver (separated by a separator), parse it on the JS side, display the HTML and put the JS Code in your javascriptCode variable.
//Somehow, get your HTML Code and JS Code into strings
var javascriptCode="function test(){.....}";
var htmlCode="<html>....</html>";
//HTML /////////////////////////////////////////
//Locate our HTML holder Div
var wndw=document.getElementById("display");
//Update visible HTML
wndw.innerHTML = htmlCode;
//Javascript ///////////////////////////////////
//Create a JSON Object to hold the new JS Code
var JSONCode=document.createElement("script");
JSONCode.setAttribute("type","text/javascript");
//Feed the JS Code string to the JSON Object
JSONCode.text=javascriptCode;
//Locate our code holder Div
var cell=document.getElementById("codeHolder");
//Remove all previous JS Code
if ( cell.hasChildNodes() )
while ( cell.childNodes.length >= 1 )
cell.removeChild( cell.firstChild );
//Add our new JS Code
cell.appendChild(JSONCode);
//Test Call///////////////////////////////////////
test();
This code will replace all previous JS code you might have put there with the new JS Code String.

Thanks for the replies.
Dutchie - that's exactly what I did. now the thing is the HTML is properly overwritten (I didn't use append I overwrote the entire div) and yes the javascript just keeps on caching...
I tried to disable browser cache and still the problem persists i get multiple context menu per item the more I ran the ajax function...
Jan,
My AJAX function builds a div tag and script tags and places them into another container div tag in the page.
What's suppose to happen is that every time the AJAX runs the code inside the container div is overwritten and you get an updated version.
the div inside the container div is overwritten yet the script tags somehow are cached into the memory and now each time the out jQuery function calls the context menu i get multiple menus...
I don't think code is needed but I will post it tomorrow.
Any ideas?

Related

How to capture the displayed link in HTML (JavaScript) and pass to another HTML page as a variable?

I am building a website (and I am a novice) and the site has 2 frames. On the left side (frame 1), I have a list of links that when you click on a link it will load a page in frame 2 (right side). But the links are on the left side are actually the result of a query and will change.
Rather than hard coding a site for each link, I want to use one target page to display data. I want to use the link on the left side as a variable value to pass to the right side so I can use the link name in a query on the target page.
MyUniqueLink
Any help would be very appreciated.
In your first <iframe>, you can access the parent document like so:
// window.parent will be undefined if you are not in an iframe.
window.parent.document
Then, as spencer said, it would be easier for you to use document.getElementById("secondFrameId") to get to your second iframe.
Also, the onclick event might be a bit more suited to your needs.
So together the code would look like:
<a onclick="window.parent.document.getElementById('secondFrameId').src='http://example.com'">MyUniqueLink</a>
If you want to access the data in your <a>'s, you should start by giving them an id:
<a id = "myId" href="JavaScript:void(top.frames[2].location.href='Recap.html');" >MyUniqueLink</a>
Then you can grab their data using standard js:
document.getElementById("myId").innerHTML; // grabs MyUniqueLink
document.getElementById("myId").getAttribute("href"); // resolves to href value
Or accomplish the same using jQuery:
$("#myId").html();
$("#myId").attr("href");
If you are dynamically creating the <a>'s in the first place, you can also assign them an id at this point using newElement.setAttribute("id", "someNewId");.

Javascript: Text in arrays and multiple textareas

I'm trying to load a parent page into an object tag, and whilst I can get an alert to show I've got the code, I cannot get it into the <object> Any clues?
var page=parent.document.documentElement.innerHTML;
alert(page);
document.getElementById('close_skin').style.visibility="visible";
document.getElementById('show_skin').style.visibility="visible";
document.getElementById('show_skin').setAttribute("data",page);
Assuming I can get the code to appear, how can I "toggle" to a different set of styles? The parent uses ".xxx_fixed" classes, but the code in the object needs to use the ".xxx_float" classes that are also in the template CSS at top of page. (When I did it in another PERL program, it was easy just to rename the tags in the <body> from "class='xxx_fixed' " to "class='xxx_float' " (Can't do that so easily with global javascript replace as that would also rename the classes at top of code as well!)
I have just tried adding some script to the top of the var page object - which MAY work if I can get the code to appear ...
+'document.getElementById(\'icon_outer\').setAttribute(\'class\', \'icon_outer_float\')'
If you're interested as to the "why", the "fixed" keep menu / top bar fixed in one place when viewed in full screen browser, but the 'float' makes everything move in unison within the <object> "window" allowing viewer to pan around the template page like a static magnifying glass;
.menu_back_float{position:relative;top:0px;background-color:#f5eca4;min-height:520px;height:auto}
.menu_back_fixed{position:relative;top:35px;background-color:#f5eca4;min-height:550px;height:auto}
To load the parent page into an <object> element, you have to specify the URL of the page. To get the code and place it in a alert box, you can use jQuery's $.get() method (as long as you load it via a proxy domain), like this:
HTML:
// I'm just using W3Schools just to save time
<object data="http://www.w3schools.com/" width="1500" height="1200">
<embed src="http://www.w3schools.com/" width="1500" height="1200"></embed>
Your browser does not support the object tag.
</object>
JavaScript:
window.jQuery.get("http://www.yourdomain.com/?url=www.w3schools.com", function(response) {
window.alert(response);
}
For the second part of your question, you can use jQuery to change the name of the class from .xxx_fixed to .xxx_float:
function main() {
$('object').removeClass('xxx_fixed').addClass('xxx_float');
}
$(document).ready(main);
Hopefully I have answered your question correctly and thouroughly, and if I haven't, feel free to let me know so I can edit this.

jQuery refer to files in folders

$(function () {
$(".links2lvl a").click(function () {
var page = this.hash.substr(1); /*in case of first link - works*/
/* var page = this.hash.substr(7); in case of second link - nope.jpg*/
$.get(page + ".php", function (gotHTML) {
$("#content").html(gotHTML);
});
});
});
<section class="tabs">
<ul class="links1lvl">
<li><a>About</a>
<ul class="links2lvl">
<li>Us</li>
<li>Personal</li>
So here I have two two sets of code. First is jQuery function, which extracts given PHP file and it's contents are shown in div with id="content".
The other is my 2 level list. In the second level you can see pages I'm trying refer to. The first link works just fine, jQuery successfully extracts the content and shows it given plave, but the second link in the folder about/ thats another story, the function doesn't seem to find it. The question is, how do I refer to .whatever from another file?
Most of the problems I see in code are based on attempts to solve challenges by adding more challenges to the code. :)
I would give a suggestion and I hope you don't mind: I would solve it by adding a "data-*" to each a tag to hold the reference you need to find using this.hash (or, maybe, use .each or .map) to loop through the elements and extract the proper URL to be used).
What happen is, this.hash will return "#who", but it is also a valid ID selector in jQuery (see more here). Hence this.hash will find "#who", but won't find "about/#personal" (because the hash element is not the first character of the string).
You could use string.split('#') to capture the string straight after the "#", then save it in - for instance -, the data-hash parameter at each a tag while constructing the HTML. Then it should be fairly easy to obtain the content needed for your application (once again, it is always about how to minimize challenges, instead of add them). ;)
Sadly I am no able to build a code sample now, but if you have difficulties following this idea, contact me and I will write a quick sample code for you.

How to manipulate the DOM with Onsen UI

I'm a total newbie to Onsen UI and I managed to make my first little app (static that is) with a few pages, popovers, lists, etc.
But when I try to add dynamic stuff in there, it does not want to cooperate.
When I click my side menu, it calls menu.setMainPage and in the callback I want to modify the content of the list (lets say iterate a JSON request and add a ons-list-item for each of them). However, they do not look styled with Onsen UI icing.
I guess it's because the menu.setMainPage has already parsed the ons-page and showed it in the browser.
Is there a way to do a load page, update the dom, and then pass it to be displayed?
I have a simila problem with an popover that contains a list. I want to add items in that list, but my jQuery append never work. Same reason I suppose.
Thanks!
Sounds like you're not running ons.compile() on the dynamic elements. The custom elements must be compiled after they've been added to the DOM to get the correct style and behavior.
I made a short example to illustrate it:
ons.bootstrap();
var addItem = function() {
var $myList = $("#my-list"),
$item = $("<ons-list-item>").text(Math.random());
$myList.append($item[0]);
ons.compile($item[0]);
};
If you attach the addItem function to a click handler you can add items dynamically to an <ons-list>.
This is a running example on codepen:
http://codepen.io/argelius/pen/gbxNEg

Executing function on a click event in a mustache template

I have a page that is driven by a mustache template (along with javascript and jquery), and I can't figure out how to insert a function into this template. Essentially what I want is to add a link or button to the page that executes a function, "onTaskSelected(taskId)", when the user clicks on it. I've been searching for a way to accomplish this for several days now, and extensive mustache documentation/support/examples are woefully hard to find. Does anyone know how this could be accomplished?
Edit - Here is some of the code that I've tried:
data["B" + task.taskId] = {
changeTask : function(taskId) {
var self = this;
self.onTaskSelected(taskId);
},
taskId : task.taskId
};
Data gets loaded into the mustache template, which has the following within it:
<button onClick="{{#B8.changeTask}}B8.taskId{{/B8.changeTask}}">Change to task 8</button>
I've debugged the code to the point where data gets sent to the template to be converted to html, and B8 has set both changeTask and taskId correctly. However, by the time the html is displayed, the button looks like this:
<button onclick>Change to task 8</button>
Why is the onclick getting zapped, and how can I fix it? It doesn't need to be a button, but I do need a clickable element on the page with that text.
Update: I have since updated my template as follows:
<button onClick="{{#B8}}{{#changeTask}}8{{/changeTask}}{{/B8}}">Change to task 8</button>
Apparently I needed to nest my data templating in order to access the variables inside the "B8" object. However, now the problem I have is that it's trying to execute the "changeTask" function when it creates the html from the template. How can I get it to wait to execute until I click the button?
Finally got it working, but I ended up going a completely different route. Wanted to post it here in case anyone else had the same problem. I formatted the mustache to give the button a name rather than try to insert the onClick method, then I cycled through every button in that section of the DOM using jquery and add an onClick method to the buttons that had the right names.
Edit: Technically I also changed my buttons to links, which I'll show in the code below, but it should also work for buttons as well.
template:
<a name="{{{B8}}}">Change to task 8</a>
jquery (partial example):
$('a[name="' + buttonData[B8].name + '"]').click(function() {
self.onTaskSelected(buttonData[B8].taskId);
});
Hope that is helpful for others.
While your own answer is correct in essence, there is an easier option to select with jQuery:
$(link+'[name|="'+buttonData[B8].name+'"]')
Hope this helps u in the future.
Btw - I am myself still searching for a solution to the original problem...

Categories