problems with execCommand justification in Firefox? - html

I am building a very simple WYSWIG editor for a div with contenteditable = "true". I am using execCommand to do simple formatting such as bold, italicize, and underline along with text justification.
PROBLEM: Bold, italic, underline all work but using justifyCenter (or any justify) doesn't work in Firefox but works in Chrome and Safari. Chrome and Safari don't seem to like my justifyRight but works just fine with justifyLeft and justifyCenter. In Firefox I get the following:
uncaught exception: [Exception... "Component returned failure code:
0x80004005 (NS_ERROR_FAILURE) [nsIDOMNSHTMLDocument.execCommand]"
nsresult: "0x80004005 (NS_ERROR_FAILURE)"
I can't figure out what is wrong but wonder it if might have something to do with designMode needing to be set to on in Firefox? However, bold, italic, and underline are working just fine without me explicitly turning on designMode.
Any ideas? Thanks in advance.

I know it's sort of a late answer, and you probably figured it out already, but for anyone who hasn't, try setting contenteditable to true for the body. I'm trying to find a way around this because every browser justifies the text just fine without it on, and I don't want the whole page editable.

The bug is referenced here : https://bugzilla.mozilla.org/show_bug.cgi?id=442186
Someone proposed this workaround :
try
{
document.execCommand('justifyright', false, null);
}
catch (e)
{
//special case for Mozilla Bug #442186
if(e && e.result == 2147500037)
{
//probably firefox bug 442186 - workaround
var range = window.getSelection().getRangeAt(0);
var dummy = document.createElement('br');
//find node with contentEditable
var ceNode = range.startContainer.parentNode;
while(ceNode && ceNode.contentEditable != 'true')
ceNode = ceNode.parentNode;
if(!ceNode)
throw 'Selected node is not editable!';
ceNode.insertBefore(dummy, ceNode.childNodes[0]);
document.execCommand('justifyright', false, null);
dummy.parentNode.removeChild(dummy);
}
else if(console && console.log)
console.log(e);
}
It consists in creating a dummy element (a <br />) and remove it after the execution of the justify* command.

Related

Is there a way to have a bookmark be created upon clicking a button/link?

I'm trying to figure out if it's possible to make it so that if you click a link or button, a bookmark will be created. Anything that comes up on Google has to do with ebooks, and I can't seem to find anything. If anyone has the answer, it would be a huge help!
function addFavorites(a) {
pageTitle = document.title;
pageURL = document.location;
try {
// Internet Explorer solution
eval("window.external.AddFa-vorite(pageURL, pageTitle)".replace(/-/g, ''));
} catch (e) {
try {
// Mozilla Firefox solution
window.sidebar.addPanel(pageTitle, pageURL, "");
} catch (e) {
// Opera solution
if (typeof(opera) == "object") {
a.rel = "sidebar";
a.title = pageTitle;
a.url = pageURL;
return true;
} else {
// The rest browsers (i.e Chrome, Safari)
alert('Press ' + (navigator.userAgent.toLowerCase().indexOf('mac') != -1 ? 'Cmd' : 'Ctrl') + '+D to bookmark this page.');
}
}
}
return false;
}
Add to Favorites
Source: https://rudrastyh.com/javascript/favorite-button.html
Be aware of eval()
eval() may be a dangerous function under certain circumstances, which executes the code it's passed with the privileges of the caller.
Get advised by Mozilla.org and use with caution
No, there's no stright forward way for that.
Opera, Google Chrome and Safari do not provide a way to add new elements to the Favorites (Bookmarks) from JavaScript.
There was an API for that however, which is the Window.external API, and I believe it used to work as window.external.AddFavorite() in Internet Explorer, and window.sidebar.addPanel() in Firefox (obsolete, deprecated, i.e. dead, see for the API).
Not sure this info would help, but you might have to create a browser extension for that, then connect your button with your extension, this way you can ensure its stability.
My suggestion is to simply ask the users to bookmark the webpage they're in if that would help to solve the problem you're trying to solve (not sure what you're trying to create).

Copying text with a new line to <input type="text"/> not working in IE

My problem is the following:
I have an input, simple as that:
<input type="text"/>
And when I try to paste some text that contains a new line in it, all the text after the new line does not appear.
Now I know this type of input shouldn't support such behavior, and the best scenario is to use a textarea but that would be hardly achievable in the current project I am working on.
However, other browsers convert the new line to a space character and append the text after the new line so you eventually get the whole text in a single line. IE doesn't do that.
I have found the following solution to intercept paste event and I thought maybe I can use it to transform the string into a single-lined but it doesn't work in firefox. I can try a browser detection but I am afraid it can fail in many other scenarios as well.
Is there something else that I can do to make IE behave like other browsers and what are my best options?
I found this answer that might be the solution to your problem:
JavaScript get clipboard data on paste event (Cross browser)
It should work in IE6+, FF 22+, Chrome & Safari.
HTML
<input id='editableDiv' contenteditable='true' type="text"/>
JavaScript
function handlePaste (e) {
var clipboardData, pastedData;
// Stop data actually being pasted into input field
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
// Remove new line characters
alert(pastedData);
var res = pastedData.replace(/\r?\n|\r/g, );
}
document.getElementById('editableDiv').addEventListener('paste', handlePaste);
Hope this helps mate.
Thanks for your answer George K - yours was the base for my solution. I had a few remaining problems to get past:
addEventListener was giving me 'element not found'
concatenated value wasn't populating the field
So I ended up with these slight modifications to your javascript:
function handlePaste(e) {
var clipboardData, pastedData;
// Stop data actually being pasted into input field
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
// Remove new line characters
var res = pastedData.replace(/\r?\n|\r/g, ' ');
document.getElementById(e.target.id).value = res; // <- added this to populate value
}
// added this also - this fixed my 'element not found' error
window.addEventListener('load', function () {
document.getElementById('editableDiv').addEventListener('paste', handlePaste);
})
BTW, I am using an <asp:textbox> instead of an <input> element.
This works for me in both IE (11) and Chrome (83.x).

After Input goes Invalid in HTML5 set error message and prevent default error message from kendo in a grid

I stuck with the inline validation in the kendo grid.
I don't want to validate after losing focus. I want to validate immediately after typing. So I start using the HTML validator. It works pretty well but the problem is I cant answer these two questions:
which event set the input from valid to invalid.
which event displays the error message.
My Current work: https://dojo.telerik.com/OSONo/56
which event set the input from valid to invalid.
...
which event displays the error message.
Just run your kendoValidator with validator.validate();
The error messages are also set with validate().
Something like this should work:
$(document).on('input propertychange', function() {
validator.validate();
});
The warning seems to be hidden behind some elements, so you can also add the folowing errorTemplate to your kendoValidator:
errorTemplate: '<div class="k-widget k-tooltip k-tooltip-validation" style="margin: 0.5em; display: block;"><span class="k-icon k-i-warning"></span>#=message#<div class="k-callout k-callout-n"></div></div>'
And the whole solution:
https://dojo.telerik.com/OSONo/66
Solved my Problem on my Own. I will edit the post so you can see what i mean but first i just give the dojo projcet.
https://dojo.telerik.com/OSONo/64
my edit:
I am sorry for my previous anwser, i just want to give him my solution i mention in my comment.
In my solution i created an event listener, how listen to all input elements. When something has changed it, saves the current cursor position (its import for ie support) and after this it trigger my "change" event. The "change" event check if it is valid or invalid. If it is invalid the kendo validator shows imidently the error-message (not as default by a blur event).
var ValidierungCheckClass = (function () {
return {
AllDOMElements: function () {
$('body').on('input', function () {
var myActiveElement = $(':focus');
if ((myActiveElement) && (myActiveElement.context.activeElement.nodeName.toLowerCase() !== "body")) {
var myActiveDOMElement = myActiveElement[0],
start = myActiveDOMElement.selectionStart, //just for IE Support
end = myActiveDOMElement.selectionEnd; //just for IE Support
myActiveElement.trigger("change");
myActiveDOMElement.setSelectionRange(start, end); //just for IE Support
}
})
}
}
});
The change event is allready created from kendo so you dont have to write your own.
At least you have to call the method when creating the website.
<script>
ValidierungCheckClass().AllDOMElements();
</script>
This is my Solution to my problem.
best regards.

If buttonImage in .datePicker starts with a forward slash (/), Chrome does not find the image

I have datepickers whose images are being set in a .js file with jquery.
Is it ok to remove the leading / as I have done in buttonImage? The jsFiddle below suggests that Chrome should be able to handle this so I'm wondering if I'm doing something else wrong.
When setting buttonImage in .datePicker(), if the location starts with "/", Chrome doesn't find the image (404 behind the scenes in Chrome DevTools). These are the lines from the .datePicker() below in question:
buttonImage: "content/images/cal.png", //WORKING IN ALL BROWSERS
buttonImage: "/content/images/cal_editor.jpg", //NOT WORKING IN
CHROME but works in IE, Firefox
However, when I try to replicate this in a simple jsFiddle, it doesn't work in Chrome without the forward slash: http://jsfiddle.net/tonyleif/3z865d2r/2/.
From the jsFiddle above:
buttonImage: "/img/initializing.png" //WORKING IN ALL BROWSERS
buttonImage: "img/initializing.png" //NOT WORKING IN ALL BROWSERS
Here is the full .datePicker function that is being called in my app:
var $calendarButton = $(me).datepicker({
dateFormat: "dd-M-yy",
showOn: "button",
buttonImage: "content/images/cal.png", //WORKING IN ALL BROWSERS
//buttonImage: "/content/images/cal.png", //NOT WORKING IN CHROME but works in IE, Firefox
buttonImageOnly: true,
beforeShowDay: oneDayOnlyMethod,
altField: alternateField,
onSelect: function() {
if ($(me).hasClass('searchItem')) {
APP.SearchTable.AddDateFilter($(me));
}
var pairedName = $(me).attr('paired-date-picker');
if (pairedName !== undefined && pairedName.length > 0) {
var d = $(this).val();
if (isValidDate(d.valueOf())) {
var pairedControl = $('#' + pairedName);
if (pairedControl.val() == "" || pairedControl.val() == "DD-MMM-YY") {
pairedControl.val(d);
}
}
}
$(me).change();
}
}).next(".ui-datepicker-trigger").addClass("calendar-button");
Let me know if you need more code that this. I'm trying not to include too much text initially.
One more thing I should note is that when I'm running the site locally with Visual Studio 2013, I don't have this issue. It only happens when I publish to the server.
The idea behind the leading slash is that it makes the whole URL relative to the root of the site (http://sitename.blah/). Without the slash, you get the relative path of where the lookup originated.
My guess is that you're attempting to get the image from a directory other than the root, which is why it works without the slash on all browsers.
Comparing your code to the jsFiddle is fine, but you need to also compare the file paths and where they are relative to the site root. In jsFiddle, the img folder is at the root of the site.
So to answer your question, no, it's not ok to leave off the slash unless you mean to get the file from the relative directory.

Contenteditable paragraph tag on enter

I was wondering if there is an acceptable way to force all major browsers to insert paragraph tag instead of the default tag that they insert on pressing enter key when contentEditable is true.
As far as I know IE inserts p automatically. But Google Chrome inserts div tag and Firefox inserts br (WTF?!).
Thanks in advance!
you can use document.execCommand('formatBlock', false, 'p'); in event like keypress or keydown, etc. to use paragraphs after enter press. For example:
element.addEventListener('keypress', function(ev){
if(ev.keyCode == '13')
document.execCommand('formatBlock', false, 'p');
}, false);
As its build in the browser you can't change that behaviour. You could work around by detecting browser and replacing elements correspondingly. Very ugly, I know.
Also check WhatWG for background: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/031577.html
I had this same problem and found the solution (CHROME, MSIE, FIREFOX), follow my code in the link.
$(document).on('click','#myButton',function() {
if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1)
var str = $('#myDiv').html().replace(/<br>/gi,'').replace(/<div>/gi,'<br>').replace(/<\/div>/gi,'');
else if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1)
var str = $('#myDiv').html().replace(/<\/br>/gi,'').replace(/<br>/gi,'<br>').replace(/<\/br>/gi,'');
else if (navigator.userAgent.toLowerCase().indexOf("msie") == -1)
var str = $('#myDiv').html().replace(/<br>/gi,'').replace(/<p>/gi,'<br>').replace(/<\/p>/gi,'');
$('#myDiv2').removeClass('invisible').addClass('visible').text(str);
$('#myDiv3').removeClass('invisible').addClass('visible').html(str);
});
https://jsfiddle.net/kzkxo70L/1/