Chrome jumping caret bug with removeChild - javascript

Can someone please shed some light on this problem in Chrome? The removeChild() function makes the caret jump to the end of the div. Anyone got a workaround?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
var caretX = 0
function keypress(event){
insertAtCaret('<span id="caretpos"></span>');
var caretpos = document.getElementById('caretpos')
//caretX = getX(caretpos) //finds the X position of the element
removeNode(caretpos)
return(true)
}
//Functions used:
function insertAtCaret(text,replaceContents) {
if(!text){return(false);}
if(replaceContents==null){replaceContents=false;}
if(!replaceContents){//collapse selection:
var sel = document.getSelection()
sel.collapseToStart()
}
return(document.execCommand('insertHTML', false, text))
};
function removeNode(el){
el.parentNode.removeChild(el);
}
</script>
</head>
<body contentEditable="true" onkeypress="return(keypress(event))">
<div>Type some content somewhere here > < and watch what happens in chrome</div>
</body>
</html>
Update:
I'm actually trying to get the pixel location of the user's caret by inserting a dummy element, finding its position and then removing it. That said, the problem is a fundamental one in chrome, manipulating the DOM in this way causes the caret to jump to the end of the element

Exactly what should happen to the caret after calling document.execCommand('insertHTML') is undefined, but I agree that Chrome's behaviour is unhelpful. You could get round it by using the insertNode() method of Range to add your dummy element:
var sel = window.getSelection();
sel.collapseToStart();
var span = document.createElement("span");
var range = sel.getRangeAt(0);
range.insertNode(span);
// Get the position here...
span.parentNode.removeChild(span);
An alternative approach to the whole thing is to use Range's getBoundingClientRect() method in browsers that support it. See my answer here:
Coordinates of selected text in browser page
Finally, I've been writing a module to do this for my Rangy library. It's not quite finisihed but there's a demo here: http://rangy.googlecode.com/svn/trunk/demos/position.html

Related

After an onpaste event in a contentEditable node, how can I iterate through all the pasted nodes? (especially in older versions of IE)

I'm modifying an HTML editor. On pasting, I need to manipulate some of the pasted HTML to adjust the attributes of the pasted nodes to identify them as duplicates.
I can intercept the paste when the user enters control + V, but it doesn't seem possible to redirect the paste when the user goes through the browser's context menu. I'm using the onpaste event in this case, getting the initial range and then using timeouts, when the range changes, I want to try to get all the nodes. How can I do this?
If I keep a reference to the TextRange object, the offsetWidth changes after the paste. I can call select() on the range and it selects exactly what was pasted. However, the offsetLeft doesn't seem to be correct, which I think is because the DOM changed. I'm trying to solve this for (older) IEs first because they're definitely the trickiest and for now, I need to support them.
Here's simplified sample code (the 500ms timeout is arbitrary):
inner.htm:
<!DOCTYPE html>
<html>
<head>
</head>
<body topMargin="1" leftMargin="1" contentEditable="true" onblur="">
<div>First section PASTE</div>
<div>HERE Second section</div>
<div>This is <div>COPY</div>ME text</div>
</body>
</html>
outer.htm:
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript'>
function getIfrmDoc() {
var ifrm = document.getElementById('ifrmain');
return ifrm.contentDocument || ifrm.contentWindow.document;
}
window.onload = function () {
var doc = getIfrmDoc();
doc.body.onpaste = function (e) {
var rng = doc.selection.createRange();
setTimeout(function () {
handlePastedData(rng);
}, 500);
}
}
function handlePastedData(initRange) {
// What can I do here?
initRange.select();
//alert(initRange.offsetWidth);
}
</script>
</head>
<body>
<iframe id="ifrmain" src="inner.htm" style="width: 100%; height: 450px;"></iframe>
</body>
</html>
So if you open outer.htm, and then copy a couple characters from anywhere, pasting it before the word "PASTE", it will give an offsetLeft of 1 even there are a few words before it.
In handlePastedData, how can I iterate through all the pasted nodes? I've tried to adapt various solutions from various other questions but haven't found anything that will work for this scenario.
Thanks!

Jquery/Css Issue #2: Hover Elements triggering unwanted hovering action

Long time ago, I made a question with the concept: Jquery/CSS challenge, where I use Jquery to fill in for CSS place and was given the hover function (because I haven't learned that before, and is now very useful!) So I copied the code, edited it to my liking to make my homemade 'navigation' buttons made by the span attribute (i know i can use button, but was curious on how it plays here).
So when I begin to test it, I noticed an odd behavior. After I started my hovering activity on multiple 'same' attributes. My mouse acted weirder when my on hover acts like 'off hover' and when I go away it acted like I was 'on hover'. I even edited to mouse enter and mouse leave from the jQuery library and I still run into the same issue, HELP!
Here is my sample of code used for the jQuery-Css Project:
$(document)
.ready(
function() {
var $span = $("span");
$span
.css(
{
"background-color" : "#eef"
}
)
.hover(
function (){
$(this)
.css(
{
"background-color" : "#ddf"
}
)
;
},
function () {
$(this)
.css(
{
"background-color" : "#eef"
}
)
;
}
)
;
}
)
;
Then the appropriate HTML coding used for this scenario:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Jquery Test Page.</title>
<!--[if lte IE 7]>
<style>
.content {
margin-right: -1px;
} /* this 1px negative margin can be placed on any of the columns in this layout with the same corrective effect. */
ul.nav a {
zoom: 1;
} /* the zoom property gives IE the hasLayout trigger it needs to correct extra whiltespace between the links */
</style>
<![endif]-->
</head>
<body>
<div class="menu">
<span id="a">I am button A</span>
<span id="b">I am button B</span>
<span id="c">I am button C</span>
</div>
</body>
</html>
I do spread my coding out just for easy editing purposes, but I need help with this! Thank you all for making this a good community!
It is not acting weird. That is happening because you have made two functions there in the hover event. The first one is fired when you hover and the second one when you left the button. If you want only the hover event you can make only one function there
$span.css({"background-color" : "#eef"}).hover(function (){
$(this).css({"background-color" : "blue"});
});
And you can use mouseleave function in jquery to understand when the user left the button.
Read this article for better understand
http://www.w3schools.com/jquery/event_hover.asp

Getting screen size to use in CSS

<style>
<script>
var screenW = 640, screenH = 480;
if (parseInt(navigator.appVersion)>3) {
screenW = screen.width;
screenH = screen.height;
}
else if (navigator.appName == "Netscape"
&& parseInt(navigator.appVersion)==3
&& navigator.javaEnabled()
)
{
var jToolkit = java.awt.Toolkit.getDefaultToolkit();
var jScreenSize = jToolkit.getScreenSize();
screenW = jScreenSize.width;
screenH = jScreenSize.height;
}
document.write(
".wrap, html {font-family: 'PT Sans', sans-serif; width:"+screenW+"px;height:"+screenH+"px;}"
)
</script>
</style>
This script is meant to add the user's screen size into the height and width parameters of this short CSS piece, which I have included internally, lacking a method of doing it with an external style sheet.
I'll be happy to learn a new and more efficient method of doing this. My official question, however, is will this script work?
http://www.javascripter.net/faq/screensi.htm is the page location that I grabbed this from!
I did this using XHTML (if it works in XHTML it works in HTML, but 99.9% of the time not vice-versa) so you know you're getting a quality example here.
First off you don't make a script element the child of a style element.
Secondly never ever put a script element inside of the body element unless you want to accrue serious damage to getting things to work down the road.
Never use document.write as it's not XHTML compatible or innerHTML as it treats code as text strings instead of code, meaning when you try to change something dumped in to the DOM it may or may not work because you may be referring to code or you may be referring to text that simply looks like code.
Save the following as example.xhtml and then open in Firefox. I recommend using Firebug's inspector to look at the DOM so you can see that the link element referring to the style sheet with the screen_height and screen_width can be confirmed at your end. Feel free to ask me any (sane) questions.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Example</title>
<script type="application/javascript">
//<![CDATA[
function load_css()
{
var l = document.createElement('link');
l.setAttribute('href','themes/example/style.css?screen_height='+encodeURIComponent(screen.height)+'&screen_width='+encodeURIComponent(screen.width));
l.setAttribute('rel','stylesheet');
l.setAttribute('title','example');
l.setAttribute('type','text/css');
document.getElementsByTagName('head')[0].appendChild(l);
}
window.onload = function()
{
load_css();
}
//]]>
</script>
</head>

div not rendered in internet explorer 9

Hi I have a custom js autocomplete component using AJAX that uses a div containing a table to show matching values.
When using it in IE9 with DOCTYPE declaration the div does not appear.
The strange think is that if I have another instance of the component in tha page everything works fine (I have those components in a table and add new rows dinamically; if the table is empty at the beginning I have the problem, otherwise I can add new rows containing new instances of the component and everything works fine).
The code work fine in firefox and chrome.
It works fine in ie9 too if I specify
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<meta http-equiv="X-UA-Compatible" content="IE=8" />
I have debugged and the javascript setting the div visible is executed to no avil:
this.resultTable.innerHTML=responseText;
this.resultTable.style.top=getY(this.editField)+22;
this.resultTable.style.left=getX(this.editField);
this.resultTable.style.zIndex="1";
this.resultTable.style.visibility='visible';
If I resize the windows the div magically appears.
Thanks in advance for you reply.
EDIT:
I have found a solution (thank to epascarello hint).
I have added
window.resizeBy(1,1);
window.resizeBy(-1,-1);
this solved almost because my page is in an iframe 100% w/h; the only remaining issue was that maximizing and restoring browser windows resulted in unecessary srollbars appearing in the iframe; I solved it adding
getFrameForDocument(document).style.width='100%';
getFrameForDocument(document).style.height='100%';
where getFrameForDocument was found at Getting a reference to the parent IFRAME and is
function getFrameForDocument(document) {
var w= document.defaultView || document.parentWindow;
var frames= w.parent.document.getElementsByTagName('iframe');
for (var i= frames.length; i-->0;) {
var frame= frames[i];
try {
var d= frame.contentDocument || frame.contentWindow.document;
if (d===document)
return frame;
} catch(e) {}
}
}

Ajax+Jquery Javascript running very slowly in Internet Explorer

On a website I'm designing a user searches for hotels in a city, and results are returned as xml then formatted through ajax/javascript/jquery.
The results are displayed almost immediately in Chrome or FF, but in Internet Explorer (I've tried ie6 and ie9) the results take almost a minute to be displayed.
Running the developer tools in IE states that 99% of execution time is spent in function "getElementsByTagName" which is called almost 200,000 times, however I'm unaware of how to fix this if it is the issue.
The page in question is beta.hotelsweep.com and the function being called on search is:
//summarized version of the function
$.get(url, function (xmlResponse) {
$('#results').empty();
var exception = $("Exception", xmlResponse);
if (exception.size() > 0) {
var error = "<h2>We were unable to complete your request</h2>";
$('#results').html(error);
} else {
$('#numResults').html($("resultsNumber", xmlResponse).text() + " hotels found <br>");
var resultsHtml = "<div id='results_list'>";
//set googlem map to center
map.setCenter(new GLatLng($("avgLat", xmlResponse).text(), $("avgLong", xmlResponse).text()), 9);
// Loop through response, creating <li> for each hotel
$("Hotel", xmlResponse).each(function () {
var bookLink = $('affiliateLink', this).text();
var address = $('fulladdress', this).text();
var stars = $('stars', this).text();
resultsHtml += 'Hotel Stars: ' + stars;
});
//put html into results div
$('#results').html(resultsHtml);
}
});
You can't really fix this issue. getElementsByTagName isn't indexed in older versions of IE. You can use element id lookups instead (avoid $("Exception"), $("avgLat"), etc).
If that's not feasible, you can add a script on the server to render the results to HTML.
It turns out the issue was something to do with the document mode. In quirk mode, the javascrit wasn't even fully executing.
Adding this to the top:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
or
<meta http-equiv="X-UA-Compatible" content="IE=9" />
Made Internet Explorer execute as expected. I don't fully understand what is happening, but if you find your javascript executing incorrectly only in IE it could be to do with the document mode.

Categories