I can use the following scriptlet to make a webpage editable
javascript:document.body.contentEditable='true'; document.designMode='on'; void 0
but after doing the edits I want to do (e.g., for a screenshot for a manual), how do I restore the state of the page to its normal uneditable state? I have tried changing true and 0 to false and 1 respectively, to no avail.
You would be able to leave edit mode by changing your command to the following
javascript:document.body.contentEditable='false'; document.designMode='off'; void 0
I have updated my answer to include a simple working example of my answer, tested in chrome, safari and firefox.
<input type="button" value="Edit" onclick="javascript:document.body.contentEditable='true'; document.designMode='on'; void 0"> <input type="button" value="Disable Edit" onclick="javascript:document.body.contentEditable='false'; document.designMode='off'; void 0">
<div><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel arcu eget risus iaculis imperdiet vel in leo. Pellentesque commodo nibh tellus. Morbi ultricies consectetur fermentum. Aenean eu vehicula libero. Nam pellentesque lobortis dui, ut rutrum neque suscipit at. In tincidunt justo sit amet faucibus bibendum. Sed viverra dignissim nulla, ac lacinia orci bibendum at.</p><p>Mauris enim ex, mattis et augue nec, maximus dignissim leo. Donec maximus interdum blandit. Phasellus porta accumsan est, ac sagittis arcu sollicitudin quis. Donec consequat velit at congue congue. Suspendisse feugiat molestie neque, id condimentum tellus. Vestibulum fringilla libero nec iaculis pellentesque. Cras mollis risus eros, eget mollis augue molestie ac. Nulla tincidunt metus at pulvinar cursus.</p></div>
You need to remove the contenteditable attribute.
var demo_editable = document.getElementById('demo-editable');
var demo_button = document.getElementById('demo-button');
demo_editable.setAttribute('contenteditable',true);
demo_button.onclick = function() {
delete demo_editable.removeAttribute('contenteditable');
}
<div id="demo-editable">This is editable</div><button id="demo-button">Make not editable</button>
Or you can set the attribute to false.
var demo_editable = document.getElementById('demo-editable');
var demo_button = document.getElementById('demo-button');
demo_editable.setAttribute('contenteditable',true);
demo_button.onclick = function() {
delete demo_editable.setAttribute('contenteditable',false);
}
<div id="demo-editable">This is editable</div><button id="demo-button">Make not editable</button>
Try this:
Hit F12 to inspect the page
Right-click on the top-most element the <html> tag
From the resulting contextmenu, select "Edit as HTML"
Focus the editable HTML and hit Ctrl+A to select all
Hit Ctrl+C to copy the page's HTML to your clipboard
Make the edits to the contenteditable section
Repeat steps 1 through 4
Ctrl+V to paste over the edited HTML with the page's original HTML
Related
I'm writing a Javascript application that utilises contentEditable. The browser's "Edit" menu contains a number of entries that change the contents of a contentEditable—I've found ways to intercept all of them apart from "Delete". So there's a cut event for the "Cut" menu item, a paste event for the "Paste" menu item, etc. What's the equivalent for the "Delete" menu item?
So you mean you want to intercept when something is deleted or you want to launch a command to delete something? You could intercept a key event:
$(document).on('keydown', 'div[contenteditable="true"]', function(event){
var parent = document.getElementById($(this).attr('id'));
if (event.which == 46) {
//if delete key is pushed do something
} else if (event.which == 8) {
//if backspace key is pushed do something
}
});
Here is a list of all key codes in Javascript: http://css-tricks.com/snippets/javascript/javascript-keycodes/
Here is a list of all the execCommand attributes available and browser compatibility: http://help.dottoro.com/larpvnhw.php
If you want to delete the current selection you could use the document range.deleteContents(); function which is compatible with most modern browser like this:
function RemoveSelection () {
if (window.getSelection) { // all browsers, except IE before version 9
var selection = window.getSelection ();
var range = selection.getRangeAt(0);
range.deleteContents();
}
}
<div>
Select some content on this page with the mouse!
</div>
<button onclick="RemoveSelection ();">Remove selected text</button>
You can also look into the deleteFromDocument method: http://help.dottoro.com/ljdslife.php
Latest edit:
Okay, now that I understand your question better, I figured out you can use the on input event on your contenteditable to detect any changes to your contenteditable. Works both when you select some text and select delete from browser's menu, or when you use delete or backspace key. You basically compare text length from before and after.
There isn't really a default on delete event. Here is a list of all the events: http://help.dottoro.com/ljfvvdnm.php
var editor = document.getElementById("editor");
var prevLength = editor.innerHTML.length;
function interceptDelete(evt) {
var newLength = evt.target.innerHTML.length;
if(newLength < prevLength) {
alert('Deleted');
}
prevLength = newLength;
}
editor.addEventListener("input", interceptDelete, false);
<div id="editor" contenteditable="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce quis mollis tellus. Nulla rhoncus venenatis malesuada. Donec mi neque, blandit nec efficitur sit amet, tincidunt vel arcu. Vivamus quis eros vitae nunc gravida hendrerit. Vivamus nibh neque, maximus at fringilla id, scelerisque vitae nulla. Aenean ut turpis ante. Sed gravida id magna nec sollicitudin. Sed quis justo eget erat elementum condimentum non sit amet mauris. Cras fringilla, justo fringilla interdum scelerisque, orci neque elementum erat, bibendum accumsan velit ipsum a ipsum. Ut sed tincidunt felis. Ut sed egestas mauris. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed dolor est, volutpat id suscipit at, faucibus et metus.
Donec non enim in nulla condimentum consequat. Praesent faucibus consectetur maximus. Maecenas quis leo lacinia, ornare enim at, iaculis magna. Donec faucibus nec est vitae lobortis. Nam fermentum tellus tempus, sollicitudin orci id, suscipit lacus. Pellentesque at tortor ultrices, cursus urna consequat, viverra sem. Vestibulum tempor enim nec est lobortis fermentum. Etiam eu accumsan ligula, eget placerat felis. Aliquam nec nunc eu ante dictum pretium. Morbi sed nulla quis libero commodo condimentum.</div>
And you could please appreciate the time I took for answering this with voting up or accepting my answer! Thanks!
The input event is supported for contenteditable in Mozilla and WebKit browsers and fires when content is deleted via the browser menu. Sadly it isn't supported in IE yet.
http://jsfiddle.net/cfz1du4h/
I simply want the contents of the HTML5 details tag to 'glide'/animate open rather than just pop open/appear instantly. Is this possible with jQuery/Javascript?
Fiddle
HTML:
<details>
<summary>Show/Hide</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum laoreet metus auctor tempor dignissim. Nunc tempor ligula malesuada, adipiscing justo quis, ultrices libero. Curabitur pretium odio sagittis lorem euismod, a ultrices sem ultrices. Integer sapien nibh, mollis id pretium id, dignissim ut dui. Nam sit amet lectus lectus. Cras scelerisque risus a dui accumsan, in dignissim dolor sodales. Nunc aliquam pharetra dui, a consectetur velit lobortis vel.</p>
<p>Mauris convallis orci in semper aliquam. Ut mollis laoreet nibh pretium tincidunt. Donec aliquam at odio sit amet dictum. Phasellus sapien leo, feugiat sit amet sagittis in, congue vel lectus. Donec elementum est vitae nulla interdum laoreet. Curabitur fringilla a tellus non laoreet. Aliquam vel lectus convallis massa pulvinar pellentesque. Mauris laoreet pharetra turpis vel tristique. Sed ligula ligula, sodales sed auctor in, aliquam sit amet lorem. Etiam vestibulum, libero vel dignissim ultrices, lacus mauris lacinia enim, quis aliquam nibh mauris eu mauris. Etiam sapien leo, dapibus et libero sed, laoreet ornare tellus.</p>
<p>Sed placerat vehicula magna et adipiscing. Nam euismod nibh ut tellus tempor, eget lobortis metus iaculis. In laoreet, enim in dignissim pellentesque, felis augue tincidunt massa, vestibulum fringilla mauris sapien in diam. Duis interdum molestie fermentum. Aenean dictum varius augue, id luctus neque viverra id. Nam eleifend tempus mauris in mattis. Sed id risus non magna semper blandit in vel arcu. Suspendisse quis nisi ligula. Fusce vestibulum at enim eu.</p>
</details>
Too bad a simple CSS transition can't be used.
I'd therefore suggest wrapping the sibling elements of the summary element and then using .slideToggle() on them. It isn't that simple though, you need to add the open attribute to details, and hide the inner wrapped elements by default.
This only works if you use e.preventDefault() to prevent the default functionality; however, you then need to rewrite the arrow indicators, (►,▼).
You would use summary::-webkit-details-marker and display:none to remove the marker that is no longer working, and add your own custom markers via the :before/:after pseudo elements.
UPDATED EXAMPLE HERE
$('details summary').each(function(){
$(this).nextAll().wrapAll('<div id="wrap"></div>');
});
$('details').attr('open','').find('#wrap').css('display','none');
$('details summary').click(function(e) {
e.preventDefault();
$(this).siblings('div#wrap').slideToggle(function(){
$(this).parent('details').toggleClass('open');
});
});
CSS:
summary::-webkit-details-marker {
display: none;
}
summary:before {
content: "►";
}
details.open summary:before {
content: "▼";
}
If you want the details element to be open by default, add class="open" as opposed to the attribute open, and then use this: $('details.open div#wrap').css('display','block');
ALTERNATIVE EXAMPLE - (open by default)
Based on #JoshCrozier's answer, I've made a solution that uses the open attribute instead of the extra open class. This way you don't have to change the css.
If you would like to use css to change the appearance of the <details> element, you can use the same style rules regardless of whether the browser supports the <details> element, and regardless of whether javascript is enabled in the browser, since you only have to consider the open attribute, and no special classes.
In addition, there is no special id on the wrapper element, making the solution slightly more robust and generic.
Also, this solutions takes <details> elements that should be open by default into account.
$('details summary').each(function() {
var $Wrapper = $(this).nextAll().wrapAll('<div></div>').parent();
// Hide elements that are not open by default
if(!$(this).parent('details').attr('open'))
$Wrapper.hide();
$(this).click(function(Event) {
Event.preventDefault();
if($(this).parent('details').attr('open')) {
$Wrapper.slideUp(function() {
// Remove the open attribute after sliding so, so the animation is visible in browsers supporting the <details> element
$(this).parent('details').removeAttr('open');
});
} else {
// Add the open attribute before sliding down, so the animation is visible in browsers supporting the <details> element
$(this).parent('details').attr('open', true);
$Wrapper.slideDown();
}
});
});
This website has a fancy effect: when a navigation link is clicked, the content fades out and when the new page (on a different URL) loads, its contents fade in.
What's interesting is, after users click on the "Back" button of their browsers, they go back to the previous page and the content still fades in. In other words, the previous page doesn't stay at the faded-out state, which is what was last seen. According to this comment, a page should be staying at its last seen state.
I tried many ways to reproduce this effect, yet on my tests, after clicking on the "Back" button the previous page still shows nothing (the content stays at the faded-out state). Sometimes it works on some browsers but not on others. Sometimes it works, but then it doesn't after reopening the browser.
How does the website implement this effect, which even works after users use the "Back" button to go to the previous page?
=== EDIT 1 ===
Here are my test pages.
=== EDIT 2 ===
The above test pages have been tested with Firefox on three different PCs, and Firefox from version 4 all the way to version 20 via an online cross-browser testing service. And the results are the same: doesn't work.
You need a very simple workaround: hook into window.unload event, and a specific condition to reload the page inside window.onpageshow!
Firefox fix
jQuery:
$(window).unload(function () { $(window).unbind('unload'); });
JavaScript:
function UnloadHandler() { window.removeEventListener('unload', UnloadHandler, false); }
window.addEventListener('unload', UnloadHandler, false);
iOS Safari fix
jQuery:
$(window).bind('pageshow', function(event) {
if (event.originalEvent.persisted) {
window.location.reload()
}
});
JavaScript:
window.addEventListener('pageshow', function (event) {
if (event.persisted) {
window.location.reload()
}
}, false);
Working sample
Since I don't have access to update your page, I've uploaded one here.
Why Firefox needs window.onunload? MDN window.unload says:
Using this event handler in your page prevents Firefox 1.5 from caching the page in the in-memory bfcache. See Using Firefox 1.5 caching for details.
Some users might not want to disable Firefox's bfcache [see section Page caching despite unload and beforeunload handlers), and it is why the Firefox fix above is unbinding the onunload event inside of the onunload event.
Why Safari needs window.onpageshow? Apparently there's no way of disabling Safari's "bfcache", and we must refresh the page when it's shown.
PS. bfcache means back/forward cache.
Full HTML/JavaScript for reference:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<div>
Page 1
Page 2
</div>
<div id="content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas laoreet imperdiet diam, in sodales velit porta eget. Ut tellus urna, vestibulum vel facilisis eu, blandit sed est. Sed tortor justo, interdum vel iaculis eu, semper ut libero. Morbi porttitor sem eget dolor eleifend fermentum. Mauris lacinia dictum lacus ut pharetra. Proin lacus felis, vestibulum sit amet malesuada id, pretium at lorem. Duis elementum sapien vitae nibh consequat tincidunt. Proin gravida rhoncus metus sed feugiat. Sed ultricies tellus et augue adipiscing dictum. In vitae tellus eget sapien fringilla tincidunt. Vestibulum gravida, velit quis mattis elementum, lacus felis vestibulum neque, et commodo quam orci quis odio. Nunc varius viverra metus, eu dictum massa venenatis vel. Cras suscipit, orci a gravida pretium, erat massa facilisis turpis, quis sodales sem metus vitae ligula. Nunc interdum augue vel arcu vulputate quis aliquet nulla vehicula. Suspendisse eros odio, ultrices hendrerit euismod nec, condimentum sed metus.</p>
<p>Donec at dolor et arcu aliquam tincidunt. Nulla eu elit sit amet leo facilisis posuere. Etiam non elit ac elit ornare elementum a vitae felis. Aenean semper nunc urna. Ut et interdum mi. Duis mollis est eu leo gravida vitae adipiscing leo commodo. Ut scelerisque cursus nulla, nec bibendum elit molestie sed. Nulla facilisi. Proin neque arcu, aliquam sed sagittis non, ultrices in enim. Fusce vitae nunc neque, ut sodales magna. Proin aliquam lobortis augue sed aliquet. Maecenas sit amet pellentesque mauris. Donec luctus purus hendrerit nisl pharetra eleifend. Mauris a lectus mi. In elit dui, porta a venenatis vel, consectetur id magna. Quisque vehicula leo vel nulla convallis quis sollicitudin sem fringilla.</p>
<p>Morbi nec mi odio, eget porttitor nisi. Duis luctus blandit lacus. Donec quis sagittis mi. Maecenas id nisl enim. Aliquam erat volutpat. Nulla facilisi. Donec ac velit diam, interdum rutrum mauris. Nullam at odio eget felis tempus elementum. Nam a augue nibh, sed bibendum massa. Vivamus eget sollicitudin mauris. Pellentesque dapibus quam nec ligula blandit scelerisque. In vulputate mauris vel dolor interdum vitae aliquet nisl convallis. In massa mi, consectetur id malesuada at, suscipit vitae libero. Sed a ligula erat.</p>
</div>
<script type="text/javascript">
$(function() {
$('body').hide().fadeIn(800);
$('a').click(function() {
var href = $(this).attr('href');
$('body').fadeOut(800, function() {
window.location = href;
});
return false;
});
});
// Firefox fix
$(window).unload(function () { $(window).unbind('unload'); });
// iOS Safari fix
$(window).bind('pageshow', function(event) {
if (event.originalEvent.persisted) {
window.location.reload()
}
});
</script>
</body>
</html>
For anybody running in problems with Rails and this -- your issue isn't bfcache -- it's the turbolinks gem. Here is how to remove it.
Maybe that's not not exactly what you are asking, but they achive the effect in this way: page content starts hidden.
That's always, even when you click back button, because content hidden is declared in a style or class in markup.
Then there's javascript code that fadeIn the content after the ready event:
$('#content').fadeIn(800);
I'm using the jquery columnizer plugin to create columns of a text in a div. The used plugin can be found here.
Below is an example of my html which should be divided into three columns:
<div class="textColumn">
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum adipiscing,
nisi tempus tincidunt tempor, lorem libero venenatis lectus, molestie congue arcu risus ut
lorem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras mauris lorem, eleifend
vitae auctor id, rhoncus eget mi. Nunc convallis condimentum pretium. Praesent vulputate
mauris sit amet nisl porttitor fringilla. Aliquam sit amet venenatis risus. Nullam
malesuada hendrerit dolor, id sagittis libero condimentum non. Sed dapibus bibendum augue,
id lobortis arcu iaculis laoreet. Maecenas lacinia mattis ipsum, ut vehicula nulla
tristique id. Quisque vehicula orci vitae nibh ultricies ac dictum metus pretium. Donec id
arcu tellus, vulputate blandit augue. Integer turpis felis, cursus et congue sit amet,
mollis at neque. Nunc pellentesque erat vel odio tempus aliquam.<br>
<br>
Quisque faucibus lectus luctus odio blandit aliquet. Phasellus blandit augue vel eros
lacinia nec hendrerit ligula sagittis. Sed sollicitudin ultricies sem sit ametpellentesque.
Fusce semper purus vel massa porttitor vestibulum. Fusce eget erat eu augue ullamcorper
mattis. Morbi adipiscing fermentum purus, ut ultrices libero tristique sed. Fusce ut augue
in ante rhoncus iaculis. Nunc auctor, est sit amet ornare dictum, dolor odio elementum
orci, vitae porta enim nisi id felis. Aenean justo mauris, fringilla id faucibus eget,
tincidunt ornare purus. Aenean dapibus sapien non justo elementum sollicitudin. In at
vehicula turpis. Sed porta rhoncus arcu a cursus. Maecenas eu purus in urna mattis ornare
et et arcu. Suspendisse auctor magna ac tortor condimentum condimentum.<br>
</div>
</div>
In a generic javascript file i've defined a document.ready function in which in executing the columnizer to create my columns. This is done with the javascript below. It works fine when defining only a width. However, I also want to set a limited height for the columns. As soon as I do this the plugin (and there with also the browser) crashes.
$(document).ready(function(){
$('#content.one .textColumn .text').columnize({
width: 169
/*,height: 162*/ /*Enabling this rule crashes the internet!*/
});
});
I've tried with the width and height both setup, but also with only the height setup. Both make the plugin crash. Also defining the height inside the plugin (and therewith modifying the plugin) make it crash. According to this jquery plugin page it should be possible to set a height and also this example shows a working version.
Does anyone have a good resolution to this?
It is a bug in the plugin, please use this one:
https://raw.github.com/cioddi/Columnizer-jQuery-Plugin/71eae2c531419274a1ec085f6a6485038e98c9f3/src/jquery.columnizer.js
I got it from a git push request. Your js code is valid. please see this jsfiddle as prove:
http://jsfiddle.net/kxMJM/
I got the patched plugin from cioddi
http://jsfiddle.net/h2vMN/1/
I have a text box text inside it already, in the actual application this will be filled dynamically, but for the sake of this question it has been pre filled.
<textarea id="textarea">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempor commodo ornare. Donec lobortis dui sed lectus egestas tristique. Vivamus vel metus turpis, faucibus varius risus. Aenean ante mauris, ultrices id facilisis vitae, dignissim eget sem. Quisque sed justo lectus, eget aliquet leo. Curabitur in mauris et diam fermentum venenatis. Proin ullamcorper, neque a vehicula euismod, odio enim aliquam ipsum, eu tristique urna sapien nec erat.
Aliquam erat volutpat. In in lacus cursus dolor pellentesque posuere. Cras eu metus urna, a rhoncus ligula. Ut hendrerit orci in arcu dignissim id fermentum orci vulputate. Sed ante ligula, volutpat eu convallis vel, auctor in metus. Mauris euismod, metus eget venenatis sodales, risus tellus volutpat elit, et aliquet massa tellus ut sapien. Mauris tempor posuere massa et consectetur. Duis dignissim enim a nulla ultricies vitae vulputate felis commodo. Phasellus mollis est eget odio porttitor consequat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus ut nibh auctor libero sagittis semper vitae quis erat.
</textarea>
When I run the above code, it shows a tiny text area with scroll bars all over it. In other words, completely useless in terms of being user friendly. How do I automatically resize the text box according to the amount of content their is and it has a set width of 600px.
#textarea{width:600px;}
I would like a javascript/jquery solution.
I have tried the .autoresize solution unsuccessfully, which can be found here:
http://james.padolsey.com/demos/plugins/jQuery/autoresize.jquery.js/view
Note, the height should be resized automatically
Thy this:
$(document).ready(function(){
tx = $('#textarea')
tx.height(tx.prop('scrollHeight'));
})
DEMO
$(document).ready(function(){
var heightFudgeFactor = 10;
var id = 'tempid' + Date.now();
$('#textarea').after( $('<div>').css('font-family','monospace').css('white-space','pre-wrap').css('word-wrap','break-word').attr('id',id).css('width',$('#textarea').width()).text( $('#textarea').text() ) );
$('#textarea').css('height',$('#'+id).outerHeight() + heightFudgeFactor).next().remove();
});
Here's one way of doing it, I'm creating a secondary div that's the height of the textarea, based on content, but you'll need to play with it a little more to get it to your actual liking
I once used this plugin: http://www.jacklmoore.com/autosize
It worked fine.