Convert contenteditable div's content to plaintext via javascript - javascript

I'm trying to make custom lightweight rich text editor with just one feature - adding links. I did some research and desided iframe is the best choice. After some messing around it works with one exception - I need to run some code on keyup event. I read everything I found on the internet and nothing helped, still doesn't work...
iframe.document.designMode = 'On';
iframe.document.open();
iframe.document.write(someHTML);
iframe.document.close();
var keyupHandle = function() { /* some code */ };
var iframeDoc = document.getElementById('iframe').contentWindow.document;
if(iframeDoc.addEventListener) {
iframeDoc.addEventListener('keyup', keyupHandle(), true);
} else {
iframeDoc.attachEvent('onkeyup', keyupHandle());
}

I think I remember needing to wait for the iframe to fully load before adding event handlers to the document. If possible, add something to the iframe's HTML to call out to the parent page when it's loaded:
window.iframeLoaded = function() {
var iframeDoc = document.getElementById('iframe').contentWindow.document;
if(iframeDoc.addEventListener) {
iframeDoc.addEventListener('keyup', keyupHandle(), true);
} else {
iframeDoc.attachEvent('onkeyup', keyupHandle());
}
};
iframe.document.designMode = 'on';
iframe.document.open();
iframe.document.write('<html><body onload="parent.iframeLoaded()">Stuff</body></html>');
iframe.document.close();
Failing that, setting a brief timer using window.setTimeout() will probably work.

Related

javascript help; pausing autorefresh

trying to figure a way to keep my chat div area from refreshing and annoyingly scrolling to the bottom. after searching the only solution I could come up with, is setting a global to a certain value and changing it when onfocus and back with onblur.
javascript was never my strongest area and I think it might just be me.
var chatarea = document.getElementById('usertalk');
window.onload= function() {
chatarea.scrollTop = chatarea.scrollHeight;
}
var chatfocus = false;
chatarea.onfocus=function(){ chatfocus = true; }
chatarea.onblur=function(){ chatfocus = false; }
setInterval("updateChat()", 5000);
function updateChat(){
var ajaxRequest;
ajaxRequest = new XMLHttpRequest();
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
if(chatfocus === false){
chatarea.innerHTML = ajaxRequest.responseText;
chatarea.scrollTop = chatarea.scrollHeight;
}
}
}
ajaxRequest.open("GET", "comments.php?t=<?php echo $topicc; ?>", true);
ajaxRequest.send(null);
}
If javascript would print me errors I could probably figure it out or search enough to understand. I've tried many different variations and assigning it to window but still script doesn't wanna work. I finally gave up and moved on in php and im now able call a edit form to replace a comment inside this same div that I want to auto refresh and going to need to pause this script for that too. But once again have no idea of achieving in js without asking questions.
"usertalk" doesn't exist at the time execution so attaching your event handlers is failing. Put your event handlers in the onload function:
var chatarea = null;
window.onload= function() {
chatarea = document.getElementById('usertalk');
chatarea.scrollTop = chatarea.scrollHeight;
chatarea.onfocus=function(){ chatfocus = true; }
chatarea.onblur=function(){ chatfocus = false; }
}
Edit: Didn't realize you're also referencing chatarea in updateChat, define this outside onload's scope as null but only use getElementById after the page has loaded.
i apparently cannot have a onfocus or onblur event on a div area?
after trying every possible way to get those events to work and change a value i didnt quite know how to set as a global without guessing until success, i made a input button to enable/disable my auto updateChat function and set the value in my hidden html form.
also i found useful websites like jshint.com to diagnose possible errors. sorry for being unaware

Showing iFrame only after its source content has been completely loaded

I have a iFrame on my page thats display style is none. I have a javascript function to set the source and then set the display to block. The problem is that the iframe shows up before the content of it is loaded and thus I get a flickering effect. It goes white first and then displays the content. So I need to set the source, and when done loading all content of its source, only set its display style.
CSS & Javascript
.ShowMe{display:block;}
function(url)
{
document.getElementById('myIFrame').src = url;
document.getElementById('myIFrame').className = ShowMe;
}
It's simple as that:
<iframe onload="this.style.opacity=1;" style="opacity:0;border:none;
I would suggest you try the following:
<script type="javascript">
var iframe = document.createElement("myIFrame");
iframe.src = url;
if (navigator.userAgent.indexOf("MSIE") > -1 && !window.opera){
iframe.onreadystatechange = function(){
if (iframe.readyState == "complete"){
//not sure if your code works but it is below for reference
document.getElementById('myIFrame').class = ShowMe;
//or this which will work
//document.getElementById("myIFrame").className = "ShowMe";
}
};
}
else
{
iframe.onload = function(){
//not sure if your code works but it is below for reference
document.getElementById('myIFrame').class = ShowMe;
//or this which will work
//document.getElementById("myIFrame").className = "ShowMe";
};
}
</script>
Based on the code found here.
You could do this within the iframe:
window.onload = function () {
window.frameElement.className = 'ShowMe'; // 'ShowMe' or what ever you have in ShowMe variable.
}
Since you've tagged your question with [jquery], I assume you have executed the code within $(document).ready(). It is fired when the DOM is ready, i.e. it uses native DOMContentLoaded event (if available). window.onload is fired, when all resources on the page are ready.

Javascript - JQuery - clearInterval/setInterval - iframe cycle won't stop on click

I'm fairly new to Javascript in general, and I cobbled together a small script from things found mostly on this site to try to get a small iframe to cycle through a bunch of links, which it does brilliantly. However, I also want it to stop cycling when the user clicks on the iframe or any of its contents.
Here is the code I have so far. There is only one iframe on the HTML page.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
<!--
var sites = [
"side/html5.html",
"side/silverlight.html",
"side/wordpress.html",
"side/mysql.html",
"side/php.html",
"side/css3.html"
];
var currentSite = sites.length;
var timerId;
var iframeDoc = $("iframe").contents().get(0);
$(document).ready(function ()
{
var $iframe = $("iframe").attr("src","side/html5.html");
timerId = setInterval(function()
{
(currentSite == 0) ? currentSite = sites.length - 1 : currentSite = currentSite -1;
$iframe.attr("src",sites[currentSite]);
}, 4000);
$(iframeDoc).bind('click', function()
{
clearInterval(timerId);
});
});
//-->
</script>
</head>
<body>
<sidebar>
<iframe name="sideframe" src="side/html5.html"></iframe>
</sidebar> ..etc..
Please help, I am trying to learn Javascript as fast as I can but as far as I can see, it should work, but it really doesn't.
Thanks for any help you can give me, it's really appreciated.
EDIT:
Okay, I've got a new script now, mostly based off of Elias' work, but it doesn't work either. I've pinned it down in Firebug and it's saying that the timerCallback.currentSite value IS updating properly, though I can't find the $iframe's src value to check for it explicitly. As far as I can tell, it is updating the variables properly, it's just not updating the iframe properly. Am I calling/setting the iframe correctly in this code? Also, is the linked in jquery library sufficient for my purposes? I'm a little lost of all these libraries to link to...
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript" charset="utf-8">
<!--
var sites =
[
"side/html5.html",
"side/silverlight.html",
"side/wordpress.html",
"side/mysql.html",
"side/php.html",
"side/css3.html"
];
var $iframe = $("iframe").attr("src","side/html5.html");
function timerCallback()
{
timerCallback.currentSite = (timerCallback.currentSite ? timerCallback.currentSite : sites.length) -1;
$iframe.attr("src",sites[timerCallback.currentSite]);
$($('iframe').contents().get('body')).ready(function()
{
$(this).unbind('click').bind('click',function()
{
var theWindow = (window.location !== window.parent.location ? window.parent : window);
theWindow.clearInterval(theWindow.timerId);
});
});
}
var timerId = setInterval(timerCallback, 4000);
//-->
</script>
If I were you, I'd play it safe. Since you say you're fairly new to JS, it might prove very informative.
function timerCallback()
{
timerCallback.currentSite = (timerCallback.currentSite ? timerCallback.currentSite : sites.length) -1;
$iframe.attr("src",sites[timerCallback.currentSite]);
}
var timerId = setInterval(timerCallback, 4000);
$($('iframe').contents().get('body')).unbind('click').bind('click', function()
{
var theWindow = (window.location !== window.parent.location ? window.parent : window);
theWindow.clearInterval(theWindow.timerId);
});
Now I must admit that this code is not tested, at all. Though I think it provides a couple of things to get you on your way:
1) the interval is set using a callback function, because it's just better for tons of reasons
1b) in that Callback, I took advantage of the fact that functions are objects, and created a static var, that is set to either the length of your sites array (when undefined or 0), in both cases 1 is substracted
2) jQuery's ,get() method returns a DOM element, not a jquery object, that's why I wrapped it in $(), a new jQ obj, giving you the methods you need.
3) since you're manipulating the dom inside the iFrame, it's best to unbind events you want to bind
4) inside the iFrame, you don't have direct access to the parent window, where your interval is.
You might want to read up on how to deal with iFrames, because they can be a bit of a faff from time to time
EDIT:
David Diez is right, easiest way around this is to incorporate the binding in the timeout function:
function timerCallback()
{
timerCallback.currentSide = ...//uncanged
//add this:
$($('iframe').contents().get('body')).ready(function()
{
$(this).unbind('click').bind('click',function()
{
//this needn't change
});
});
}
In theory, this should bind the click event to the body after it has been loaded
Edit2
I've been messing around a bit, you could keep your code, as is. just add a function:
function unsetInterval()
{
window.clearInterval(window.timerId);
}
and add this to your setInterval function:
$('#idOfIframe').load(function()
{
var parentWindow = window.parent;
$('body').on('click',function()
{
parentWindow.clearInterval();
});
});
this will get triggered as soon as the iFrame content is loaded, and bind the click event and unset the timer, like you wanted to
I think your code is not working because of this
var iframeDoc = $("iframe").contents().get(0);
This could be getting the header of the iFrame because you are saving the iframeDoc value to the first child of the iframe, the head tag, actually if you have more than 1 iframe in your window iframeDoc would be undefined because $("iframe") gets all the iframes of your document.
BTW your currentSite value condition is wrong, you asign the same value for both conditions
Now I give you an example:
<iframe id="myFrame" src="http://www.google.com/"></iframe>
and the script:
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
var sites = [
"site1",
"site2"
];
var myFrame = document.getElementsByTagName('iframe')[0];
var currentSite = myFrame.getAttribute('src');
var timerId;
var myFrameDoc = window.frames[0].document;
$(document).ready(function()
{
myFrame.setAttribute('src', 'side/html5.html');
timerId = setInterval(function()
{
//WRONGG
(currentSite == 0) ? currentSite = sites.length - 1 : currentSite = currentSite -1;
myFrame.setAttribute('src', sites[currentSite]);
$(myFrame).off("click").on("click", clearInterval(timerId));
}, 4000);
//Won't work because you are trying to get events from an inside of a iframe
//$(myFrameDoc).on("click", clearInterval(timerId));
//This may work
$(myFrameDoc).off("click").on("click", clearInterval(timerId));
});
</script>
When you try to track the events of an iframe you have to be carefull because an iframe contains a totally different document for javascript purprouses so basically you have to get inside the new document, unbind the events you need to use, and bind them again against your functionality, as #Elias points out. but be aware that you are changing constantly the src of your iframe, so if yu really need to do that you will have to separate the code that unbinds and binds again your clearInterval, and for that matter maybe $.on() could work for you.
EDIT: Calling to the iframe should work this way IF the src of the iframe is inside the same domain, with the same port and with the same protocol:
var myFrameDoc = window.frames[0].document;
I Added a new variable because we want to bind and unbind the click event to the iframe's document, not to the iframe, we use for that the window.frames collection property, but modern browsers throw an exception and denies acces if you try to access to a frame and you are not on the same domain with using the same port and the same protocol...
Additionaly the use of $.on() and $.off() instead of $.bind and $.unbind() is because the first ones are the new ones and despite we are not using it here, they are capable of watch constantly the DOM for new elements to bind if added; that could be useful to this case if this code still doesn't work. If that is the case you can still change this:
var myFrameDoc = window.frames[0].window;
and this:
$(myFrameDoc).off("click", "document").on("click", "document", clearInterval(timerId));
This will re-bind the event handler to new documents additions. Not tested but could work.

Writing a custom javascript event

I'm writing some code that will get executed before the DOM loads, basically, using Modernizr to get scripts. Now my issue is that I want to show a loading animation if the DOM loads and the scripts are still loading.
Modernizr is executed in the head. If I put the code to use document.getElementById in the head also, error is thrown because the DOM hasn't loaded. Now I have no idea how to solve this.
Here is the code I have so far:
<head>
<script>
var FileManager = {
IsLoading = false;
LoadRequiredFiles: function (config) {
config = config || {};
this.OnLoading = config.onLoadingCallback;
this.OnComplete = config.onCompleteCallback;
this.IsLoading = true;
if (this.OnLoading) {
this.OnLoading();
}
var self = this;
Modernizr.load([{
load: '/jquery.min.js',
complete: function () {
if (self.OnComplete) {
self.OnComplete();
}
self.IsLoading = true;
}
},
]);
}
};
var globalLoadingId = 'globalLoader';
FileManager.LoadRequiredFiles({
onLoadingCallback: function () {
document.getElementById(globalLoadingId).style.display = 'block';
},
onCompleteCallback: function () {
document.getElementById(globalLoadingId).style.display = 'none';
}
});
</script>
I used to execute this code below the <body> tag, and it worked. Now I moved it into the <head>. So I used to pass 2 callbacks to it. Now I'd rather attach events to it and handle them in the body (assuming thats where the DOM is loaded).
What I'd like to do:
<head>
<script>
FileManager.LoadRequiredFiles();
</script>
</head>
<body>
<script>
//Bind the event, not sure if this is even possible in javascript.
FileManager.OnCompleted += fileManagerCompleted;
fileManagerCompleted()
{
document.getElementById(globalLoadingId).style.display = 'none';
}
if(FileManager.IsLoading)
{
document.getElementById(globalLoadingId).style.display = 'block';
}
</script>
</body>
The page is your canvas for display. You can't show anything before it loads. It sounds more like you want a very small page to load (quickly) where you could display your progress and then your code could dynamically load/display the rest of the page with ajax calls and javascript showing progress as it goes. That's the only way to get out in front of the rest of the page load that I know of.
The only entirely reliable way to run a script that manipulates the DOM is to use the body onload event. (window.onload is popular, but not quite 100% reliable.)
There are some browsers that implement a onDocumentReady event that can be kind-of-sort-of faked in IE, but I don't recommend its use.
Using getElementById will not, by itself, throw an error if used in the head. You might be causing an error because you aren't checking the returned value, which will be null if an element with the specified id wasn't found, e.g.
var el = document.getElementById('foo');
if (el) {
// do somethig with el
} else {
// el wasn't found
}
Your problem is how to display the image only if the scripts are still loading and the page is visible. The simple answer is don't use client-side script loading, do it at the server. :-)
If you want to persist with script loading, add a class to the loading image, say "hideOnLoad". Have a callback from the last script load that sets the rule to "display: none" (just create and add style sheet with that one rule using script).
Now you just include the loading image as the first element in the body with a class of "hideOnLoad", knowing that when scripts have finished loading they will hide the image regardless of whether it (or any other element with the same class) existed at the time or not.

How to clear the contents of the openwysiwyg editor?

I am using the openwysiwyg editor in my webpage. I want to clear the contents of it. I have used
$('#report').val('');
but that doesn't clear it.
The editor creates an iframe and updates the contents there, syncing as it goes.
How would I go about clearing it?
You probably need to supply a bit more information - the html itself would be very useful, but I'm going to assume that report is the id of the textarea you need cleared.
If it's a normal textarea, your code should really work.
If (as Paulo mentions in the comments) it's being modified by an openwysiwyg editor, it's probably being turned into an iFrame with it's own HTML page in it. It's a lot more difficult to manipulate the iFrame.
Looks like that's the case.
Have a look at this example to see if it helps you reference the iFrame itself: http://www.bennadel.com/index.cfm?dax=blog:1592.view
This is a hacked excerpt of the example.html that comes with openwysiwyg:
<script type="text/javascript">
// Use it to attach the editor to all textareas with full featured setup
//WYSIWYG.attach('all', full);
// Use it to attach the editor directly to a defined textarea
WYSIWYG.attach('textarea1'); // default setup
WYSIWYG.attach('textarea2', full); // full featured setup
WYSIWYG.attach('textarea3', small); // small setup
// Use it to display an iframes instead of a textareas
//WYSIWYG.display('all', full);
function getIFrameDocument( id )
{
var iframe = document.getElementById(id);
if (iframe.contentDocument) {
// For NS6
return iframe.contentDocument;
} else if (iframe.contentWindow) {
// For IE5.5 and IE6
return iframe.contentWindow.document;
} else if (iframe.document) {
// For IE5
return iframe.document;
} else {
return null;
}
}
function clearcontents()
{
getIFrameDocument('wysiwygtextarea1').body.innerHTML = '';
}
</script>
Then somewhere in the page, I've got a clear button (actually div):
<div style="width:120px;height:20px;background:#ff0000;text-align:center;display:block;" onclick="clearcontents();">Clear!</div>
Note that the id of your textarea is prefixed with wysiwyg. That's the name of the iFrame.
I've tested this in Firefox but nothing else at the moment. The code for getting the iFrame I found on the Net somewhere, so hopefully it works for other browsers :)
This works, but is butt ugly:
var frame = WYSIWYG.getEditor('--ENTER EDITOR NAME HERE--');
var doc = frame.contentWindow.document;
var $body = $('html',doc);
$body.html('');
Replace --ENTER EDITOR NAME HERE-- by whatever you pass to the editor when you call attach.
I believe this works
$('#report').text('');

Categories