How can I make this javascript marquee manually scrollable? - javascript

I am trying to make an automatic scrolling marquee using javascript and CSS but, I also want to be able to manually scroll the marquee with the mouse wheel. The marquee functions as expected ie. it scrolls automatically and loops well but I can't figure out how to incorporate manual scrolling. Here is the code that I am using. Any ideas?
<doctype HTML>
<body onload="init()">
<main>
<div id="marquee_replacement" class="scrollbar" onmouseout="startit();" onmouseover="stop();">
<p>some text some text some text some text some text some text some text some text</p>
<p>some text some text some text some text some text some text some text some text</p>
<p>some text some text some text some text some text some text some text some text</p>
<p>images are also present</p>
<p class="spacer"></p>
</div>
<script type="text/javascript">
//
var speed = 2; // change scroll speed with this value
/**
* Initialize the marquee, and start the marquee by calling the marquee function.
*/
function init() {
var el = document.getElementById("marquee_replacement");
el.style.overflow = 'hidden'; //issue is fixed by setting this to auto
scrollFromBottom();
}
var go = 0;
var timeout = '';
/**
* This is where the scroll action happens.
* Recursive method until stopped.
*/
function scrollFromBottom() {
clearTimeout(timeout);
var el = document.getElementById("marquee_replacement");
if (el.scrollTop >= el.scrollHeight - 150) {
el.scrollTop = 0;
};
el.scrollTop = el.scrollTop + speed;
if (go == 0) {
timeout = setTimeout(scrollFromBottom, 50);
};
}
/**
* Set the stop variable to be true (will stop the marquee at the next pass).
*/
function stop() {
go = 1;
}
/**
* Set the stop variable to be false and call the marquee function.
*/
function startit() {
go = 0;
scrollFromBottom();
}
</script>
<!--CSS for Marquee-->
<style type="text/css">
#marquee_replacement.scrollbar {
width: auto;
height: 150px;
overflow-y: scroll; /*issue is fixed by setting this to auto*/
}
.scrollbar::-webkit-scrollbar {
display: none;
}
#marquee_replacement {
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
#marquee_replacement p.spacer {
height: 150px;
}
</style>
</main>
</body>
Edit:
Sorry for the newbie mistake of not providing a minimal reproducible example. I will update the code above to provide an MREX so that the issue is easier to understand for future readers. Also, I solved the issue. If I set the overflow values in both CSS and javascript portions to auto instead of scroll and hidden respectively it works as an auto-scrolling marquee and manual scrolling text box.

setTimeout takes a function, not a string with code. Do it like this: setTimeout(scrollFromBottom, 50)

I figured it out. If anyone needs this in the future I had to set el.style.overflow = 'auto';to auto instead of hidden and set the CSS overflow to overflow-y: auto; to auto instead of scroll. Now it scrolls automatically and manually!

Related

Change text colour on text scroll

I am using the Neve Theme on WordPress for my website development and I am customizing my header block and I am having an issue. I am using a plugin to give my header a background after 100px on scroll of the page this changes the background colour to where the text in the header is difficult to read.
The plugin offers the functionality to change the text colour but Neve overrides anything this plugin or myself can do through it. This way I am wondering if there is a way I can change the text colour through code after 100px of scroll on the website. The classes for the content are as follows
a.button.button-primary & .book-now-header * header.header
header.header is for the entire header block so that is used to change the background colour and the other 2 are for the content needing to change colour.
Any help with this would be appreciated as I am unsure where to begin.
this code below is detect the element scroll postition you can put the result in equation but first change number of position to hex and then use it with color you have and that will change color in your text
let lastPostition = 0;
function myFunction() {
const element = document.getElementById("myDIV");
let x = element.scrollLeft;
let y = element.scrollTop;
document.getElementById ("demo").innerHTML = "Horizontally: " + x.toFixed() + "<br>Vertically: " + y.toFixed();
console.log(lastPostition);
if(y.toFixed() === lastPostition ){
alert("the end of document");
}
lastPostition = y.toFixed()
}
<!DOCTYPE html>
<html>
<style>
#myDIV {
height: 250px;
width: 250px;
overflow: auto;
}
#content {
height: 800px;
width: 2000px;
background-color: coral;
}
</style>
<body>
<h1>The Element Object</h1>
<h2>The scrollTop and scrollLeft Properties</h2>
<p>Scroll the content below to display the number of pixels it is scrolled.</p>
<div id="myDIV" onscroll="myFunction()">
<div id="content">Scroll me!</div>
</div>
<p id="demo"></p>
</body>
</html>
let lastPostition = 0;
function myFunction() {
const element = document.getElementById("myDIV");
let x = element.scrollLeft;
let y = element.scrollTop;
document.getElementById ("demo").innerHTML = "Horizontally: " + x.toFixed() + "<br>Vertically: " + y.toFixed();
if(y.toFixed() === lastPostition ){
alert("the end of document");
}
lastPostition = y.toFixed()
}

Animate text using intervals (and timeouts?) Javascript, JQuery

I would like to make a Text run from left to right in a loop. Here is the fiddle with my attempt:
https://jsfiddle.net/9Lruxym8/33/
I started with css #keyframes but I think I need the width of the text itself if I want the text to run seamlessly. My idea was to write down the text two times and once the div with the texts has run exactly halfway, the animation starts again.
After #keyframes didn't work, I tried jQuery animation. It did work somewhat but didn't run smoothly. Now I'd like to do it via transition. I thought a combination of intervals and timeouts could do the trick but I still don't get it to work - and now, I don't know why. Does anyone have a hit for me?
function runText() {
var text_width = $('#runningP').width()/2;
console.log(text_width)
setInterval(function(){
console.log("interval");
$('.text').css({'transition':'margin-left 5s'});
$('.text').css({'margin-left':'-' + text_width + 'px'});
moveBack();
}, 3000);
function moveBack() {
console.log("timeout")
setTimeout(function(){
$('.text').css({'transition':'none'});
$('.text').css({'margin-left': 0});
}, 3000);
}
}
runText();
I've recently made a bit of custom code for this functionality.
Looking at my code, it seems a bit much having essentially 3 "levels" (.scrollTextWrap > .scrollingText > .scrollContent) but this was the structure I ended up using to get a clean and consistent effect.
I've added in an initialiser too so that you could simply add the scrollMe class and have them setup the html for you
In the snippet I've added a .parentContainer purely to show how it works when constrained
$(document)
.ready(function(){
// check that scrollingText has 2 scrollContent element
$('.scrollMe')
.each(function(){
initScrollingText($(this));
});
});
function initScrollingText($this){
// store text
var text = $this.text();
// empty element
$this.html(null);
var $wrap = $('<div class="scrollTextWrap" />'),
$text = $('<div class="scrollingText" />'),
$content = $('<div class="scrollContent" />');
// set content value
$content.text(text);
// duplicate content
$text
.append($content)
.append($content.clone());
// append text to wrap
$wrap.append($text)
// add $wrap to DOM
$wrap.insertAfter($this);
// remove old element
$this.remove();
}
/* to simulate width constraints */
.parentContainer {
width: 140px;
position:relative;
overflow:hidden;
}
.scrollTextWrap {
position:relative;
width:auto;
display:inline-block;
}
.scrollingText {
display: flex;
position:relative;
transition:left 0.1s;
animation: scrollText 5s infinite linear;
}
.scrollContent {
white-space: nowrap;
padding-right:5px;
}
#keyframes scrollText {
0% { left:0 }
100% { left:-50% }
}
<div class="parentContainer">
<div class="scrollMe">Content you want to scroll goes here</div>
<!-- alternatively you can just structure the html -->
<div class="scrollTextWrap">
<div class="scrollingText">
<div class="scrollContent">Content you want to scroll goes here</div>
<div class="scrollContent">Content you want to scroll goes here</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Finding where element meets top of scrollable div

I have a scrollable div container fits multiple "pages" (or div's) inside of it's container.
My goal is to, at any given moment, figure out where inside my red container does it reach the top of my scrollable container. So it can be a constant on scroll event, or a button that triggers this task.
So for example. If I have a absolute div element inside one of my red boxes at top:50px. And if I scroll to where that div element reaches the top of my scrollable container. The trigger should say that I am at 50px of my red container.
I'm having a hard time grasping how to accomplish this but I've tried things like:
$("#pageContent").scroll(function(e) {
console.log($(this).scrollTop());
});
But it doesn't take into account the separate pages and I don't believe it it completely accurate depending on the scale. Any guidance or help would be greatly appreciated.
Here is my code and a jsfiddle to better support my question.
Note: If necessary, I use scrollspy in my project so I could target which red container needs to be checked.
HTML
<div id="pageContent" class="slide" style="background-color: rgb(241, 242, 247); height: 465px;">
<div id="formBox" style="height: 9248.627450980393px;">
<div class="trimSpace" style="width: 1408px; height: 9248.627450980393px;">
<div id="formScale" style="width: 816px; -webkit-transform: scale(1.7254901960784315); display: block;">
<form action="#" id="XaoQjmc0L51z_form" autocomplete="off">
<div class="formContainer" style="width:816px;height:1056px" id="xzOwqphM4GGR_1">
<div class="formContent">
<div class="formBackground">
<div style="position:absolute;top:50px;left:100px;width:450px;height:25px;background-color:#fff;color:#000;">When this reaches the top, the "trigger" should say 50px"</div>
</div>
</div>
</div>
<div class="formContainer" style="width:816px;height:1056px" id="xzOwqphM4GGR_2">
<div class="formContent">
<div class="formBackground"><div style="position:absolute;top:50px;left:100px;width:450px;height:25px;background-color:#fff;color:#000;">This should still say 50px</div></div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
CSS
#pageContent {
position:relative;
padding-bottom:20px;
background-color:#fff;
z-index:2;
overflow:auto;
-webkit-overflow-scrolling: touch;
-webkit-transform: translate(0, 0);
-moz-transform: translate(0, 0);
-ms-transform: translate(0, 0);
transform: translate(0, 0);
}
#formBox {
display: block;
position: relative;
height: 100%;
padding: 15px;
}
.trimSpace {
display: block;
position: relative;
margin: 0 auto;
padding: 0;
height: 100%;
overflow: hidden;
}
#formScale::after {
display: block;
content:'';
padding-bottom:5px;
}
#formScale {
position:relative;
width:816px;
margin:0;
-webkit-transform-origin: 0 0;
-moz-transform-origin: 0 0;
transform-origin: 0 0;
-ms-transform-origin: 0 0;
}
.formContainer {
position:relative;
margin : 0 auto 15px auto;
padding:0;
}
.formContent {
position:absolute;
width:100%;
height:100%;
}
.formBackground {
width:100%;
height:100%;
background-color:red;
}
JS
var PAGEWIDTH = 816;
$(window).resize(function (e) {
zoomProject();
resize();
});
function resize() {
$("#pageContent").css('height', window.innerHeight - 45 + 'px');
}
function zoomProject() {
var maxWidth = $("#formBox").width(),
percent = maxWidth / PAGEWIDTH;
$("#formScale").css({
'transform': 'scale(' + percent + ')',
'-moz-transform': 'scale(' + percent + ')',
'-webkit-transform': 'scale(' + percent + ')',
'-ms-transform': 'scale(' + percent + ')'
});
$(".trimSpace").css('width', (PAGEWIDTH * percent) + 'px');
$("#formBox, .trimSpace").css('height', ($("#formScale").height() * percent) + 'px');
}
zoomProject();
resize();
EDIT:
I don't think I am conveying a good job at relaying what I want to accomplish.
At the moment there are two .formContainer's. When I scroll #pageContainer, the .formContainer divs move up through #pageContainer.
So what I want to accomplish is, when a user clicks the "ME" button or #click (as shown in the fiddle below), I'd like to know where in that particular .formContainer, is it touching the top of #pageContainer.
I do use scroll spy in my real world application so I know which .formContainer is closest to the top. So if you just want to target one .formContainer, that is fine.
I used these white div elements as an example. If I am scrolling #pageContainer, and that white div element is at the top of screen as I am scrolling and I click on "ME", the on click trigger should alert to me that .formContainer is touching the top of #pageContainer at 50px from the top. If, the the red container is just touching the top of #pageContainer, it should say it is 0px from the top.
I hope that helps clear up some misconception.
Here is an updated jsfiddle that shows the kind of action that I want to happen.
I am giving this a stab because I find these things interesting. It might just be a starting point since I have a headache today and am not thinking straight. I'd be willing to bet it can be cleaned up and simplified some.
I also might be over-complicating the approach I took, getting the first visible form, and the positioning. I didn't use the getBoundingClientRect function either.
Instead, I approached it trying to account for padding and margin, using a loop through parent objects up to the pageContent to get the offset relative to that element. Because the form is nested a couple levels deep inside the pageContent element you can't use position(). You also can't use offset() since that changes with scroll. The loop approach allowed me to factor the top margin/padding in. I haven't looked at the other solutions proposed fully so there might be a shorter way to accomplish this.
Keeping in mind that the scale will affect the ACTUAL location of the child elements, you have to divide by your scale percentage when getting the actual location. To do that I moved the scalePercentage to a global var so it was usable by the zoom function and the click.
Here's the core of what I did. The actual fiddle has more logging and junk:
var visForm = getVisibleForm();
var formTop = visForm.position().top;
var parents = visForm.parentsUntil('#pageContent');
var truOffset = 0;
parents.each(function() {
truOffset -= $(this).position().top;
});
// actual location of form relative to pageContent visible pane
var formLoc = truOffset - formTop;
var scaledLoc = formLoc / scalePercent;
Updated Fiddle (forgot to account for scale in get func): http://jsfiddle.net/e6vpq9c8/5/
If I understand your question correctly, what you want is to catch when certain descendant elements reach the top of the outer container, and then determine the position of the visible "page" (div with class formContainer) relative to the top.
If so, the first task is to mark the specific elements that could trigger this:
<div class='triggerElement' style="position:absolute;top:50px;left:100px;width:450px;height:25px;background-color:#fff;color:#000;">When this reaches the top, the "trigger" should say 50px"</div>
Then the code:
// arbitrary horizontal offset - customize for where your trigger elements are placed horizontally
var X_OFFSET = 100;
// determine once, at page load, where outer container is on the page
var outerContainerRect;
$(document).ready(function() {
outerContainerRect = $("#pageContent").get(0).getBoundingClientRect();
});
// when outer container is scrolled
$("#pageContent").scroll(function(e) {
// determine which element is at the top
var topElement = $(document.elementFromPoint(outerContainerRect.left+X_OFFSET, outerContainerRect.top));
/*
// if a trigger element
if (topElement.hasClass("triggerElement")) {
// get trigger element's position relative to page
console.log(topElement.position().top);
}
*/
var page = topElement.closest(".formContainer");
if (page.length > 0) {
console.log(-page.get(0).getBoundingClientRect().top);
}
});
EDIT: Changed code to check formContainer elements rather than descendant elements, as per your comment.
http://jsfiddle.net/j6ybgf58/23/
EDIT #2: A simpler approach, given that you know which formContainer to target:
$("#pageContent").scroll(function(e) {
console.log($(this).scrollTop() - $("#xzOwqphM4GGR_1").position().top);
});
http://jsfiddle.net/rL4Ly3yy/5/
However, it still gives different results based on the size of the window. This seems unavoidable - the zoomProject and resize functions are explicitly resizing the content, so you would have to apply the inverse transforms to the number you get from this code if you want it in the original coordinate system.
I do not fully understand what it is that you are needing, but if i am correct this should do the trick
$("#pageContent").scroll(function(e) {
// If more then 50 pixels from the top has been scrolled
// * if you want it to only happen at 50px, just execute this once by removing the scroll listener on pageContent
if((this.scrollHeight - this.scrollTop) < (this.scrollHeight - 50)) {
alert('it is');
}
});
ScrollHeight is the full height of the object including scrollable pixels.
ScrollTop is the amount of pixels scrolled from the top.
You can use waypoints to detect the position of divs based on where you're scrolling.
Here is a link to their official website's example: http://imakewebthings.com/waypoints/shortcuts/inview/

Bring an element to top of the page even if the page does not scroll

Background:
Let's say you have a simple page which has a logo and a heading only and one paragraph
<img src="http://blog.stackoverflow.com/wp-content/uploads/StackExchangeLogo1.png">
<h1>Foo Bar</h1>
<p>ABC12345</p>
This is how that looks like
That page, obviously would not have vertical overflow / scroll bar for almost even tiny scale mobile devices, let alone computers.
Question
How can you bring that heading to the top left of the screen and move the logo out of focus unless someone scrolls up? Open to using any JavaScript library and any CSS framework
Attempts:
Tried using anchors but they only work if the page already had a scroll bar and anchor was out of focus.
Tried window.scrollTo but that also requires the page to have scroll already
Tried $("html, body").animate({ scrollTop: 90}, 100); but that also doesn't work when the page doesn't have overflow
Notes:
Please note that adding some extra <br/> to induce an overflow is not the way to go, it can be done that way but that's a very ordinary workaround
Why is it needed?
Its for a form for mobile devices, simple requirement is to take the first field of the form to top of the page and hide the logo (one can scroll up if they wish to see it) so it doesn't take attention away. Not using jQueryMobile for this particular task.
If you want the user to be able to scroll up and see the logo, then the logo must be within the top boundary of the body tag, because anything outside of that tag will not be viewable. This means you cannot use negative margins or offsetting like that. The only way to achieve this is to have the page scroll to the desired location that is within the top boundary of the body tag. You can set the time for this event to one millisecond, but there will still be a 'jump' in the page when it is loaded. So, the logic is: first make sure the page is long enough to scroll to the right place, then scroll there.
//Change the jQuery selectors accordingly
//The minimum height of the page must be 100% plus the height of the image
$('body').css('min-height',$(document).height() + $('img').height());
//Then scroll to that location with a one millisecond interval
$('html, body').animate({scrollTop: $('img').height() + 'px'}, 1);
View it here.
Alternatively, you can load the page without the image in the first place. Then your form field will be flush with the top of the document. Then you could create the element at the top and similarly scroll the page again. This is a round-a-bout way of doing the same thing though. And the page will still 'jump,' there is no way around that.
Only CSS and anchor link solution
With a pseudo element :
--- DEMO ---
First :
set : html,body{height:100%;}
Second :
Choose one of your existing tags. This tag mustn't have a relatively positioned parent (except if it is the body tag). Preferably the first element in the markup displayed after the logo. For your example it would be the h1 tag. And give it this CSS :
h1:before {
content:"";
position:absolute;
height:100%;
width:1px;
}
This creates an element as heigh as the viewport area. As it is displayed under the logo, the vertical scroll lenght is the same as the logo height.
Third :
Give the first element after logo an id (for this example I gave id="anchor").
Then you can use a link like this your_page_link#anchor and you will automaticaly scroll to the anchor (logo outside/above the viewport).
This works whatever height the logo is.
link to editable fiddle
Full code :
HTML
<img src="http://blog.stackoverflow.com/wp-content/uploads/StackExchangeLogo1.png">
<h1 id="anchor">Foo Bar</h1>
<p>ABC12345</p> Anchor link
CSS
html, body {
height:100%;
margin:0;
padding:0;
}
h1:before {
content:"";
position:absolute;
width:1px;
left:0;
height:100%;
}
You might need to add js functionality to hide the logo if user scrolls down but I guess following code will fullfill the first requirement.
Please see
<script src="js/jquery.js"></script>
<img id='logo' src="http://blog.stackoverflow.com/wp-content/uploads/StackExchangeLogo1.png" style="display:none">
<h1>Foo Bar</h1>
<p>ABC12345</p>
<script type="text/javascript">
var p = $( "p:first" );
var isScrolled=false;
/* For Firfox*/
$('html').on ('DOMMouseScroll', function (e) {
isScrolled = true;
if(p.scrollTop()==0 && isScrolled==true){
$('#logo').css('display','block');
}
});
/* For Chrome, IE, Opera and Safari: */
$('html').on ('mousewheel', function (e) {
isScrolled = true;
if(p.scrollTop()==0 && isScrolled==true){
$('#logo').css('display','block');
}
});
</script>
I have referred this question to find solution.
You could use touchmove event to detect swipe up or down. This is my example. You can try it on mobile device.
<style>
#logo {
position: absolute;
top: -100%;
-webkit-transition: top 0.5s;
-moz-transition: top 0.5s;
-ms-transition: top 0.5s;
-o-transition: top 0.5s;
transition: top 0.5s;
}
#logo.show {
top: 0;
}
</style>
<script>
var perY;
var y;
$(window).on('touchmove', function(e) {
e.preventDefault();
y = window.event.touches[0].pageY;
if(!perY)
perY = y;
else
{
if(y > perY)
$('#logo').addClass('show');
else
$('#logo').removeClass('show');
perY = null;
}
});
</script>
<img id="logo" src="http://blog.stackoverflow.com/wp-content/uploads/StackExchangeLogo1.png">
<h1>Foo Bar</h1>
<p>ABC12345</p>
This is the same problem i've encountered hiding the addressbar without the page overflowing. The only solution that fitted my needs was the following:
Set the min-height of the body to the viewportheight + your logo.
$('body').css('min-height', $(window).height() + 200);
This is a simple solution of getting the height of the contents to see if we can scroll to the part of the header, if not, we add height to the paragraph.
<img id="img" src="http://blog.stackoverflow.com/wp-content/uploads/StackExchangeLogo1.png" />
<h1 id="h" >Foo Bar</h1>
<p id="par" style="background:yellow;">
hello world
</p>
script:
function hola(){
var imgH = $("#img").outerHeight(true);
var titleH = $("#h").outerHeight(true);
var winH = $(window).height();
var parH = $('#par').outerHeight(true);
var contH = (imgH + titleH + parH);
var wishH = (imgH + winH);
console.log("wished height: " + wishH);
console.log("window height: " + winH);
console.log("content height: " + contH);
if(contH < wishH){
console.log("window is smaller than desired :(");
var newH = wishH - contH;
$("#par").height(parH + newH);
$(window).scrollTop(imgH);
}
}
Here is the working example:
http://jsfiddle.net/Uup62/1/
You may like this solution: http://jsfiddle.net/jy8pT/1/
HTML:
<div class="addScroll"></div>
<h1 class="logo"><img src="https://drupal.org/files/images/OQAAAI1PPrJY0nBALB7mkvju3mkQXqLmzMhxEjeb4gp8aujEUQcLfLyy-Sn4gZdkAas6-k8eYbQlGDE-GCjKfF5gIrUA15jOjFfLRv77VBd5t-WfZURdP9V3PdmT.png" height="100" alt="company logo"/></h1>
<h2>This is a sample page heading.</h2>
<p>This is a sample page text.</p>
JS:
function addScroll()
{
$(".addScroll").css({
"height": ($(window).height()+1) + "px",
"width": "100%"
});
}
$(document).ready(function(){
addScroll();
$(window).resize(function(){
addScroll();
});
$(window).scroll(function(){
if($(window).scrollTop() > 0)
{
$(".logo").animate({
marginTop: "-110px"
}, 500);
}
if($(window).scrollTop() == 0)
{
$(".logo").animate({
marginTop: "0"
}, 500);
}
});
});
CSS:
body
{
padding:0;
margin:0;
}
h1.logo
{
display:block;
margin:0 0 10px 0;
padding:0;
outline:0;
}
.addScroll
{
position:absolute;
display:block;
top:0;
left:0;
z-index:-1;
}

Setting cursor position in a contentEditable div - cross browser

I am facing a problem with setting cursor position in a contentEditable div and seek some assistance.
I have already looked at several SO and other online solutions without success, including:
jquery Setting cursor position in contenteditable div, and
Set cursor position on contentEditable <div> and many other online resources.
Basically, we are using a Telerik Editor with the contentAreaMode set to DIV which forces it to use a contentEditable div instead of an iFrame. When a user clicks in the editor, we wish to be able to move the cursor to the click point so the user may enter/edit content wherever they wish in the editor. Using the example code below, I am able to set the cursor position in FF, Chrome, and IE9 to AFTER the inner div. However, in IE8 (which falls into the else if (document.selection) block), I am unable to get the cursor position to move after the div, so any typed text ends up either before or inside the div - never after. I would be GREATLY appreciative of any help.
ADDITIONAL INFO: Need this to work in IE8 standards document mode - NOT in Quirks mode (which does work).
UPDATE: Here is a jsfiddle of the issue to play with: http://jsfiddle.net/kidmeke/NcAjm/7/
<html>
<head>
<style type="text/css">
#divContent
{
border: solid 2px green;
height: 1000px;
width: 1000px;
}
</style>
<script type="text/javascript">
$(document).ready(function()
{
$("#divContent").bind('click', function()
{
GetCursorPosition();
});
$("#divContent").bind('keydown', function()
{
GetCursorPosition();
});
});
function GetCursorPosition()
{
if (window.getSelection)
{
var selObj = window.getSelection();
var selRange = selObj.getRangeAt(0);
cursorPos = findNode(selObj.anchorNode.parentNode.childNodes, selObj.anchorNode) + selObj.anchorOffset;
$('#htmlRadEdit_contentDiv').focus();
selObj.addRange(selRange);
}
else if (document.selection)
{
var range = document.selection.createRange();
var bookmark = range.getBookmark();
// FIXME the following works wrong when the document is longer than 65535 chars
cursorPos = bookmark.charCodeAt(2) - 11; // Undocumented function [3]
$('#htmlRadEdit_contentDiv').focus();
range.moveStart('textedit');
}
}
function findNode(list, node)
{
for (var i = 0; i < list.length; i++)
{
if (list[i] == node)
{
return i;
}
}
return -1;
}
</script>
</head>
<body>
<div id="divContent" contentEditable="true">
<br>
<div style="background-color:orange; width: 50%;">
testing!
</div>
</div>
</body>
</html>
Using Rangy (disclosure: I'm the author) works for me in IE 7 and 8 in the window load event. Trying to move the caret when the user clicks on an editable element is a bad idea: it conflicts with default browser behaviour hence may not work, and does not do what he user expects (which is to place the caret at or near where they clicked).
<html>
<head>
<style type="text/css">
#divContent
{
width: 1000px;
height: 1000px;
border: solid 2px green;
padding: 5px
}
</style>
<script src="http://rangy.googlecode.com/svn/trunk/currentrelease/rangy-core.js"></script>
<script type="text/javascript">
window.onload = function() {
rangy.init();
var el = document.getElementById("divContent");
el.focus();
var range = rangy.createRange();
range.setStartAfter(el.getElementsByTagName("div")[0]);
range.collapse(true);
rangy.getSelection().setSingleRange(range);
};
</script>
</head>
<body>
<div id="divContent" contentEditable="true">
<br>
<div style="background-color:orange; width: 50%;">
testing!
</div>
</div>
</body>
</html>

Categories

Resources