Replace the surround of an html element with another document - javascript

I have an html page with (among other things) a Unity3D window. I would like to replace everything on the page without causing the Unity window to reload. I have tried the following jquery-tastic
function replaceSurround(keepElem, newElem)
{
keepElem.siblings().remove();
keepElem.prepend(newElem.prevAll());
keepElem.append(newElem.nextAll());
var keepParent = keepElem.parent();
var newParent = newElem.parent();
if (keepParent && newParent)
{
replaceSurround(keepParent, newParent);
}
}
where keepElem is an element in the original document and newElem is the corresponding element in the new document, but it did not work very well.

Here is what I've got, it seems to work...
jQuery.fn.rewrap = function(newWrap){
var $parent = jQuery(this).parent();
var $clone = jQuery(this).siblings().clone()
var $newParent = $clone.wrap(newWrap).parent().clone();
$parent.replaceWith($newParent);
}
$('#header').rewrap('<div class="container" style="background-color:blue;" />');
I tested it on the Stackoverflow website. One small problem though, it seems to be refiring some onX events...?
[edit]
On second thought, that is not what you meant at all....
Can't you just do something like:
$('#result').load('ajax/test.html #result');
?

Related

jQuery.attr('data-*') not work on IE8 (work on IE7) [duplicate]

This has gotten so far,that I will sum up what we found out:
Inside the event handler the attribute src cannot be read in IE8 (FF works fine), neither with jQuery nor with usual javascript
The only way to get the data was to get it outside the handler, write it to an array and read it afterwards from the inside of the handler
But there was still no possibility to write to src (neither jQuery nor javascript worked - only for IE 8)
I've got it working by writing the img elemts themselves to the document, but the reason behind this problem is no solved
The snippet we have is used twice.
The old code
<script type="text/javascript">
jQuery(document).ready(function() {
//...
//view entry
jQuery('.blogentry').live('click',function(){
// Get contents
blogtext = jQuery(this).children('.blogtext').html();
blogauthor = jQuery(this).children('.onlyblogauthor').html();
blogtitle = jQuery(this).children('.blogtitle').html();
profileimage = jQuery(this).children('.profileimage').html();
imgleft = jQuery(this).children('.Image_left').attr('src');
imgcenter = jQuery(this).children('.Image_center').attr('src');
imgright = jQuery(this).children('.Image_right').attr('src');
// Write contents
jQuery('#bild_left').attr('src', imgleft);
jQuery('#bild_center').attr('src', imgcenter);
jQuery('#bild_right').attr('src', imgright);
jQuery('.person').attr('src', profileimage);
jQuery('#g_fb_name').html(blogauthor);
jQuery('#g_titel').html(blogtitle);
jQuery('#g_text').html(blogtext);
//...
});
//...
// Change entry
jQuery('.blogentry').each(function(){
entryindex = jQuery(this).attr('rel');
if (entry == entryindex)
{
// The following works fine (so 'children' works fine):
blogtext = jQuery(this).children('.blogtext').html();
blogauthor = jQuery(this).children('.onlyblogauthor').html();
blogtitle = jQuery(this).children('.blogtitle').html();
profileimage = jQuery(this).children('.profileimage').html();
// This does not work - only in IE 8, works in Firefox
imgleft = jQuery(this).children('.Image_left').attr('src');
imgcenter = jQuery(this).children('.Image_center').attr('src');
imgright = jQuery(this).children('.Image_right').attr('src');
//alert: 'undefined'
alert(jQuery(this).children('.Image_center').attr('src'));
//...
}
}
//...
});
</script>
The new code
Please see my own posted answer for the new code.
UPDATE:
This does not work if called inside of the click event!!!
jQuery('.Image_left').each(function(){
alert(jQuery(this).attr('src'));
});
SOLUTION TO GET THE IMAGE DATA:
relcounter = 1;
imgleft_array = new Array();
jQuery('.Image_left').each(function(){
imgleft_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
relcounter = 1;
imgcenter_array = new Array();
jQuery('.Image_center').each(function(){
imgcenter_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
relcounter = 1;
imgright_array = new Array();
jQuery('.Image_right').each(function(){
imgright_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
//... inside the eventhandler (entryindex = 'rel' of blogentry):
imgleft = imgleft_array[entryindex];
imgcenter = imgcenter_array[entryindex];
imgright = imgright_array[entryindex];
This works because it is not called inside the event handler and the sources are saved beforehand
BUT! I still cannot write the data, which is my aim:
jQuery('#bild_left').attr('src', imgleft);
jQuery('#bild_center').attr('src', imgcenter);
jQuery('#bild_right').attr('src', imgright);
UPDATE!!!
This is just crazy, I tried to write the data via usual javascript. This also works in FF, but no in IE8. Here really is some serious problem witt the attribute src:
document.getElementById('bild_left').src = imgleft;
document.getElementById('bild_center').src = imgcenter;
document.getElementById('bild_right').src = imgright;
alert(document.getElementById('bild_left').src);
This works in FF, but not in IE8, the attribute src remains undefined after writing! This seems to be not a jQuery problem at all!
children looks for immediate child elements only where as find looks for all the elements within it until its last child element down the dom tree. If you are saying find is working that means the element you are looking is not its immediate children.
Try to alert this jQuery(this).children('#Image_center').length see what you get.
FYI. Even when any element is not found jQuery will return an emtpy object it will never be null. So alert an emtpy object will always give you [object Object]. You should alwasy check for the length property of the jQuery object.
Try this
alert(jQuery(this).find('#Image_center').length);//To check whether element is found or not.
Bing Bang Boom,
imgright = jQuery(".Image_right",this).attr('src');
And why don't you easily use one working?
alert(jQuery(this).children('#Image_center').attr('src'));
change children to find
alert(jQuery(this).find('#Image_center').attr('src'));
It is probably the easiest solution, and when it work, why wouldn't you use it?
the problem is not in the attr('src') but in something else. The following snippet works in IE8:
<img id="xxx" src="yrdd">
<script type="text/javascript">
alert($('#xxx').attr('src'));
</script>
But if you for example change the the text/javascript to application/javascript - this code will work in FF but will not work in IE8
This has gotten so far,that I will sum up what we found out:
Inside the event handler the attribute src cannot be read in IE8 (FF works fine), neither with jQuery nor with usual javascript
The only way to get the data was to get it outside the handler, write it to an array and read it afterwards from the inside of the handler
But there was still no possibility to write to src (neither jQuery nor javascript worked - only for IE 8)
I've got it working by writing the img elemts themselves to the document, but the reason behind this problem is no solved
The new code
relcounter = 1;
imgleft_array = new Array();
jQuery('.Image_left').each(function(){
imgleft_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
relcounter = 1;
imgcenter_array = new Array();
jQuery('.Image_center').each(function(){
imgcenter_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
relcounter = 1;
imgright_array = new Array();
jQuery('.Image_right').each(function(){
imgright_array[relcounter] = jQuery(this).attr('src');
relcounter++;
});
//view entry
jQuery('.blogentry').live('click',function(){
// Get contents
entryindex = jQuery(this).attr('rel');
blogtext = jQuery(this).children('.blogtext').html();
blogauthor = jQuery(this).children('.onlyblogauthor').html();
blogtitle = jQuery(this).children('.blogtitle').html();
profileimage = jQuery(this).children('.profileimage').html();
imgleft = imgleft_array[entryindex];
imgcenter = imgcenter_array[entryindex];
imgright = imgright_array[entryindex];
// Write contents
jQuery('#entryimages').html('');
jQuery('#entryimages').html('<img class="rotate" width="132" height="138" id="bild_left" src="'+imgleft+'" /><img class="rotateright" width="154" height="162" id="bild_center" src="'+imgcenter+'" /><img class="rotate" width="132" height="138" id="bild_right" src="'+imgright+'" />');
jQuery('.person').attr('src', profileimage);
jQuery('#g_fb_name').html(blogauthor);
jQuery('#g_titel').html(blogtitle);
jQuery('#g_text').html(blogtext);
});
So I am just not using .attr('src') in the event handler....
Try to make a delay:
jQuery(document).ready(function() {
setTimeout(function () {
jQuery('.blogentry').each(function(){
// your code...
});
}, 100); // if doesn't work, try to set a higher value
});
UPDATE
Hope, this code will work.
$('.blogentry img').each(function(){
alert( $(this).attr('src') );
});
UPDATE
I'm not sure, but maybe IE can't read classes with uppercase first letter...
Try to change ".Image_center" to ".image_center"
UPDATE
Check your code again. You definitely have some error. Try this jsfiddle in IE8, attr('src') is showed correctly. http://jsfiddle.net/qzFU8/
$(document).ready(function () {
$("#imgReload").click(function () {
$('#<%=imgCaptcha.ClientID %>').removeAttr("src");
$('#<%=imgCaptcha.ClientID %>').attr("src", "Captcha.ashx");
});
});

Javascript hiding and showing dynamic content of a div

Currently I hide and show the content of a div like this:
var header = null;
var content = null;
var mainHolder = null;
var expandCollapseBtn = null;
var heightValue = 0;
header = document.getElementById("header");
content = document.getElementById("content");
mainHolder = document.getElementById("mainHolder");
expandCollapseBtn = header.getElementsByTagName('img')[0];
heightValue = mainHolder.offsetHeight;
header.addEventListener('click', handleClick, false);
mainHolder.addEventListener('webkitTransitionEnd',transitionEndHandler,false);
function handleClick() {
if(expandCollapseBtn.src.search('collapse') !=-1)
{
mainHolder.style.height = "26px";
content.style.display = "none";
}
else
{
mainHolder.style.height = heightValue + "px";
}
}
function transitionEndHandler() {
if(expandCollapseBtn.src.search('collapse') !=-1)
{
expandCollapseBtn.src = "expand1.png";
}
else{
expandCollapseBtn.src = "collapse1.png";
content.style.display = "block";
}
}
This is fine if the content is static, but I'm trying to populate my div dynamically like so.
This is called from an iphone application and populates the div with a string.
var method;
function myFunc(str)
{
method = str;
alert(method);
document.getElementById('method').innerHTML = method;
}
I store the string globally in the variable method. The problem I am having is now when I try expand the div I have just collapsed there is nothing there. Is there some way that I could use the information stored in var to repopulate the div before expanding it again? I've tried inserting it like I do in the function but it doesn't work.
Does anyone have any ideas?
to replicate:
Here is the jsfiddle. jsfiddle.net/6a9B3 If you type in text between
here it will work fine. I'm not sure
how I can call myfunc with a string only once in this jsfiddle, but if
you can work out how to do that you will see it loads ok the first
time, but when you collapse the section and attempt to re open it, it
wont work.
If the only way to fix this is using jquery I dont mind going down that route.
is it working in other browsers?
can you jsfiddle.net for present functionality because it is hard to understand context of problem in such code-shoot...
there are tonns of suggestions :) but I have strong feeling that
document.getElementById('method')
returns wrong element or this element not placed inside mainHolder
update: after review sample in jsfiddle
feeling about wrong element was correct :) change 'method' to 'info'
document.getElementById('method') -> document.getElementById('info')
I think you want to use document.getElementById('content') instead of document.getElementById('method') in myFunc.
I really see nothing wrong with this code. However, a guess you could explore is altering the line
content.style.display = "none";
It might be the case that whatever is displaying your html ( a webview or the browser itself) might be wiping the content of the elemtns, as the display is set to none

jQuery working in Firefox, Safari but not in Chrome

I have written some code with jquery works in firefox, safari and ie9. But chrome does not like it. No obvious msgs in chrome console coming up. I am hitting a wall hopefully someone can shed some light. Script just show/hides some tooltips. Any ideas?
fiddle here, changed code still no change to behaviour.
http://jsfiddle.net/qAfwJ/
$(document).ready(function(){
//custom toolTip Written by CASherwood but not working in ie9/chrome
var ShowId;
var id;
var contentholder = $(".contentBox");
var toolTip = $(".info");
var idHashString = '#info';
var idString = 'id';
function showToolTip(name, id){
id = name + id;
$(id).fadeIn(1000);
}
function hideToolTip(name, id){
id = name + id;
$(id).fadeOut(1000);
}
$(toolTip).mouseover(function(){
ShowId = $(this).attr(idString);
showToolTip(idHashString, ShowId);
});
$(contentholder).mouseleave(function(){
ShowId = $(this).find('.info').attr(idString);
hideToolTip(idHashString, ShowId);
});
});
There are a few things here,
You are setting a variable var toolTip = $(".info");
And then using this same variable to add a function to it.
What you are doing here is actually
$($(".info")).mouseover(
Instead of
var toolTip = $(".info");
toolTip.mouseover(
Also you might consider using
jquery.hover(handlerIn(eventObject) , handlerOut(eventObject) );
http://api.jquery.com/hover/
Ok one thing I'm noticing here is that you are wrapping some elements twice with the jQuery selector.
var contentholder = $(".contentBox");
$(contentholder).mouseleave(function(){
...
});
Basically what evaluates to is this -
$($(".contentBox"))
That doesn't look too good and I'm not too sure if it would work as expected. Even if it does, the issues of cross browser compatibility might come into play and I believe this is what you are experiencing. If you have already captured the element and are not just storing the selectors as strings, then there is no need to wrap the element again with the $ syntax.
var contentholder = $(".contentBox");
contentholder.mouseleave(function(){
...
});
When you are constructing selectors from strings and variables, you should do so in a similar way to this -
var elementId = 'the_elements_id';
$('#'+elementId).on('click',handler);
I'd start by changing
$(toolTip).mouseover(function(){
ShowId = $(this).attr(idString);
showToolTip(idHashString, ShowId);
});
$(contentholder).mouseleave(function(){
ShowId = $(this).find('.info').attr(idString);
hideToolTip(idHashString, ShowId);
});
to
toolTip.mouseover(function(){
ShowId = $(this).attr(idString);
showToolTip(idHashString, ShowId);
});
contentholder.mouseleave(function(){
ShowId = $(this).find('.info').attr(idString);
hideToolTip(idHashString, ShowId);
});
since your toolTip and contentholder variables are already jquery objects.
I'm not sure and haven't tested it, but what if you try to move the two functions (showToolTip() and hideToolTip()) before or after the $(function(){});
The might get seen as inner functions of some sort instead of global functions and that might be a thing.

Duplicate iframe: Copy head and body from 1 iframe to another

Simple question which I can't seem to find an answer of:
I have two iframes on a page and I'd like to copy the content of the first one to the second.
But I can't do it by just copying the url of the first iframe to the second since the containing page is a dynamic one.
This code does do it, but a lot of the page-formatting seems to get lost. And I don't know if it's cross-browser either.
iframe2.contentWindow.document.write(iframe1.contentWindow.document.body.innerHTML);
Can this be done?
Native JavaScript Solution As Asked For:
First, to make things simple I created 2 object literals:
var iframe1 = {
doc : undefined,
head : undefined,
body : undefined
};
var iframe2 = {
doc : undefined,
head : undefined,
body : undefined
};
Next, I put everything under iframe1's window.onload handler to make sure it was loaded fully:
document.getElementById("iframe1").contentWindow.onload = function() {
Then I assigned all of the object literal properties:
iframe1.doc = document.getElementById("iframe1").contentWindow.document;
iframe1.head = iframe1.doc.getElementsByTagName("head")[0];
iframe1.body = iframe1.doc.getElementsByTagName("body")[0];
iframe2.doc = document.getElementById("iframe2").contentWindow.document;
iframe2.head = iframe2.doc.getElementsByTagName("head")[0];
iframe2.body = iframe2.doc.getElementsByTagName("body")[0];
Next, I needed to create a couple functions removeNodes() and appendNodes() so that I could re-factor some code that is used for both <head> and <body> routines.
function removeNodes(node) {
while (node.firstChild) {
console.log("removing: " + node.firstChild.nodeName);
node.removeChild(node.firstChild);
}
}
and:
function appendNodes(iframe1Node, iframe2Node) {
var child = iframe1Node.firstChild;
while (child) {
if (child.nodeType === Node.ELEMENT_NODE) {
console.log("appending: " + child.nodeName);
if (child.nodeName === "SCRIPT") {
// We need to create the script element the old-fashioned way
// and append it to the DOM for IE to recognize it.
var script = iframe2.doc.createElement("script");
script.type = child.type;
script.src = child.src;
iframe2Node.appendChild(script);
} else {
// Otherwise, we append it the regular way. Note that we are
// using importNode() here. This is the proper way to create
// a copy of a node from an external document that can be
// inserted into the current document. For more, visit MDN:
// https://developer.mozilla.org/en/DOM/document.importNode
iframe2Node.appendChild(iframe2.doc.importNode(child, true));
}
}
child = child.nextSibling;
}
With those functions created, now all we have to do is make our calls:
console.log("begin removing <head> nodes of iframe2");
removeNodes(iframe2.head);
console.log("begin removing <body> nodes of iframe2");
removeNodes(iframe2.body);
console.log("begin appending <head> nodes of iframe1 to iframe2");
appendNodes(iframe1.head, iframe2.head);
console.log("begin appending <body> nodes of iframe1 to iframe2");
appendNodes(iframe1.body, iframe2.body);
... and finally, we close off the window.onload function:
};

Javascript error: Object Required in ie6 & ie7

I have a javascript function (epoch calendar) which displays a calendar when focus is set on certain text boxes. this works fine in ie8, ff (all versions as far as I can test), opera etc but doesn't work in ie7 or previous.
If i have it set up in a blank html test page it will work so I'm fairly sure it's a conflict with my css (provided to me by a designer).
I've traced the error to these lines of code -
Epoch.prototype.getTop = function (element) //PRIVATE: returns the absolute Top value of element, in pixels
{
var oNode = element;
var iTop = 0;
while(oNode.tagName != 'BODY') {
iTop += oNode.offsetTop;
oNode = oNode.offsetParent;
}
return iTop;
};
Epoch.prototype.getLeft = function (element) //PRIVATE: returns the absolute Left value of element, in pixels
{
var oNode = element;
var iLeft = 0;
while(oNode.tagName != 'BODY') {
iLeft += oNode.offsetLeft;
oNode = oNode.offsetParent;
}
return iLeft;
};
More specifically, if i remove the actual while loops then the calendar will display OK, just that its positioning on the page is wrong?
EDIT
Code below which sets 'element'
<script type="text/javascript">
window.onload = function() {
var bas_cal, dp_cal, ms_cal;
dp_cal = new Epoch('epoch_popup', 'popup', document.getElementById('<%=txtDateOfDiag.ClientID%>'));
dp_cal = new Epoch('epoch_popup', 'popup', document.getElementById('<%=txtDOB.ClientID%>'));
};
</script>
Note: I am using asp.net Master pages which is why there is a need for the .ClientID
EDIT
A further update - I have recreated this without applying css (but including the .js file provided by the designer) the code still works fine which, there must be some sort of conflict between the CSS and my JavaScript?
That would lead me to believe that the tagName does not match, possibly because you have it in upper case. You might try while(!oNode.tagName.match(/body/i)) {
what happens if you add a line of debug code like this:
var oNode = element;
var iLeft = 0;
alert(oNode);
This might give different results in different browsers; I think it may be NULL for IE.
You may want to have a look at the code that provides the value of the 'element' parameter to see if there's a browser-dependant issue there.

Categories