contenteditable not working in safari but works in chrome - javascript

I'm having a strange issue...
This works in chrome as expected but in safari it only gets .. glowing but doesn't react on key input..
this is the method that fires the text edition:
var namebloc = $(event.currentTarget).find('.column_filename');
var oldvalue = namebloc.html();
namebloc.attr('contentEditable', true).focus();
document.execCommand('selectAll',false,null);
namebloc.blur(function()
{
$(this).attr('contentEditable', false).unbind( "keydown" ).unbind( "blur" );
var newvalue = $(this).html().replace('"','"').replace(/(<([^>]+)>)/ig,"");
console.log(newvalue);
});
namebloc.keydown(function(e)
{
if(e.keyCode==27){ $(this).html(oldvalue);}//escape
if(e.keyCode==13){ $(this).blur(); }//enter
});
This is a screenshot in chrome when fired this works as expected...
and this is the result in safari.. no reaction to keyboard or mouse selection:
Any idea why and how to solve this in safari?
this is the HTML before the method is called :
<span field="filename" class="column_filename" style="width:763px;">eiffel (2).JPG</span>
This is when it's called (at the same time as screenshots)
<span field="filename" class="column_filename" style="width:763px;" contenteditable="true">eiffel (2).JPG</span>

Safari has the user-select CSS setting as none by default.
You can use:
[contenteditable] {
-webkit-user-select: text;
user-select: text;
}
To make it work.

In Safari, despite also being WebKit based, there is differing behavior when clicking on an element that has the user-select property set. Chrome seems to key-off that css property and prevent any focus going to the element that was clicked (thanks for continuing to develop a modern and sensible browser Google), while Safari does nothing with that css property regarding focus, and sets focus on the clicked element anyway.
One solution in Safari is to use a proper html button element, but this sucks from a styling perspective.
A better solution is to trap the mousedown event (the first to fire of the Mouse type events in a click), and preventDefault() on the event. This should work in any version of Safari.
For example
<span onclick="document.execCommand('bold', false);" onmousedown="event.preventDefault();">
<i class="material-icons">format_bold</i>
</span>

Related

Element does not take the focus on Firefox when changing its content on mouse down

Say you have a DIV with a TABINDEX so that it can receive the focus.
Now imagine that on mousedown you change the text contained in that DIV. On Chrome and Edge, the DIV will take the focus. But not on Firefox.
On Firefox, it appears that the clicked text node inside the DIV matters. Destroying/replacing it using innerHTML or textContent will not allow the DIV to receive the focus.
Here is a fiddle: https://jsfiddle.net/gq52bj7o
HTML:
<div id="test" tabIndex="0">click here (on the text, not outside)</div>
JavaScript:
var testDiv = document.getElementById("test");
testDiv.addEventListener(
"mousedown",
function ()
{
//testDiv.innerHTML = "why Firefox, why?"; // KO
testDiv.textContent = "why Firefox, why?"; // KO
//testDiv.firstChild.nodeValue = "why Firefox, why?"; // OK
});
Notice that if you preserve the existing text node (testDiv.firstChild.nodeValue = "why Firefox, why?";) all works as expected. Also, if you click outside of the text, the DIV also receives the focus.
Is this normal? How would you bypass this behaviour (imagine a bigger application that updates the textContent or innerHTML of the clicked element -- focus issues would be encountered on Firefox...)?
just change "mousedown" event to "focus". works in Firefox.
testDiv.addEventListener(
"focus",
function ()
{
testDiv.textContent = "why Firefox, why?";
});

event.relatedTarget is null on focusout on touch screen

I want to use focusout on a textarea, stash the value of the clicked button which caused the focusout, and click it later, after some processing. My solution works well on all devices except iPhone and iPads. Can anyone explain why the event.relatedTarget is null on touch screens? Or is it the browser? What else is there to use?
I have tried e.currentTarget and document.activeElement (returns the whole HTML body) as well as trying setTimeout around my use of e.currentTarget. I can't seem to get the ID of the clicked button inside my focusout, on iPads and iPhones.
Here's a sample:
<div id="resultPage">
<textarea id="txtAnswer0" class="txtAnswer"></textarea>
<button id="goNow">
GO
</button>
</div>
$(document).ready(function() {
$("#resultPage").on("focusout", ".txtAnswer:not(input[type=radio], input[type=checkbox])", function(e) {
var targetCtrl = e.relatedTarget;
alert(targetCtrl);
});
});
Here is my fiddle:
https://jsfiddle.net/awebster28/6q6ok4re/25/
In my research I learned relatedTarget is only supposed to be on mouse events. If relatedTarget isn't null in a non-mouse event then the browser isn't following standards.
You'll probably have to temporarily store the button, and/or button value in a variable on click so it can be used later with the second click.

Chrome for iOS (iPad/iPhone) does not fire focus event for inputs

I have a simple detection if a software keyboard is opened on Android and iOS:
$(document).on({
focus: function() { keyboardOpened = true; },
blur: function() { keyboardOpened = false; }
}, 'input'); //catch all focus and blur events fired on any input element
It's used to prevent certain actions while user is writing a message (e.g. ignoring resize events).
It works on all browsers except for Chrome on iOS. I've included Firebug Lite on the site but there is no error, just the events are never fired and the web does not work correctly when opening SW keyboard.
Here is a fiddle: http://jsfiddle.net/WYULR (click the input and see an alert)
Anyone knows about a reason or workaround for this?
I get this too :( My solution is to detect if ipad + chrome using :
var isCriOS = /CriOS/.test(navigator.userAgent);
I tried https://github.com/gabceb/jquery-browser-plugin + webkit type distinguishing code found here How to detect chrome and safari browser (webkit) but I couldn't get that to work.
If ipad+chrome, apply a 'click' event for the field to do the same thing ... this is only good if the only focus you will have is from user taps, as calling .focus() will not trigger it ... but in this case you could just call the function ascribed through click event after the .focus() . This seemed a bit hackish so I decided to test vanilla js .onfocus event and proved that it wasn't firing either.

Handling text selection event in Firefox extension (preventing user from selecting text)

I was wondering if in chrome code we have some better way to detect when the user selects/highlights something in the current page than listening for keyup/mouseup and checking window.getSelection(). Any ideas?
edit: Actually, what I'm trying to do is simply preventing the user from selecting any text at all in the contentDocument. Something that accomplishes this will be fine as well. (The idea behind getting the selection event was just to preventDefault() or otherwise getSelection().removeAllRanges())
edit2: Please note that I need not just to prevent the highlighting from showing up, but rather the selection from happening.
edit3: I don't need to prevent copying but rather selecting the elements.
If you put the following scipt in you body, selection will be disabled in Firefox:
<script type="text/javascript">
document.body.style.MozUserSelect = "none";
document.body.style.cursor = "default";
</script>
It does not only disable the highlight, it also disables the selection itself. If you try to select an area via mouse or by arrow-keys (clicking an position and navigating with arrow-keys while SHIFT is pressed) and and press STRG+C, nothing happens.
The only selection that works after that change is STRG+A (no selection visible, but STRG+A & STRG+C copys all). It might be possible to avoid that by keyboard-events.
Edit: I saw you comment with link to Mozilla Doc Center and while they write it controls only the appearance, all my tests in Firefox 3.6 show that it affects also the selection, not only the appearance. But it might be changed in future Releases...
In the absence of suitable events such as select and selectstart (which are indeed absent in Firefox, which has the select event but only applies it to form controls), all you can do is use mouse and keyboard events, as you suggested in the question. Preventing the default action of all mousedown events in the document is no good because it will prevent all interactive elements such as links and form elements from working. Instead, you could do something like the following that zaps a selection as it is made using the mouse and keyboard.
It won't prevent selection via "Select All" in the context and edit menus though, since there is no way of detecting those at all in Firefox. If you need to deal with this, polling the selection is your only hope.
function killSelection() {
window.getSelection().removeAllRanges();
}
document.addEventListener("mousedown", function(evt) {
document.addEventListener("mousemove", killSelection, false);
}, false);
document.addEventListener("mouseup", function(evt) {
document.removeEventListener("mousemove", killSelection, false);
}, false);
document.addEventListener("keydown", killSelection, false);
window.addEventListener("blur", function(evt) {
document.removeEventListener("mousemove", killSelection, false);
}, false);
You can use css
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
You can use CSS to prevent the user selecting text. See my answer here: How to disable text selection highlighting using CSS?
To set this via JavaScript in Firefox, you can do the following:
document.body.style.MozUserSelect = "-moz-none";
The Copy command is enabled and disabled by an event. You can get notified of this event by creating a command updater.
<commandset commandupdater="true" events="select"
oncommandupdate="setTimeout(selectNone, 0);"/>
Add the following code to a css file, which is linked with a <link> tag in your popup html:
*,
*::before,
*::after {
user-select: inherit;
}
body {
user-select: none;
}

Jquery: change event to input file on IE

I have a form to upload files, and it should fire the submit after the file selection.
On FireFox/Chrome it goes well, and submits the form after file selection, but I can't do this on Internet Explorer.
Already tried with click/propertychange but nothing happens. Some code I already tried:
$("#attach").attr("onChange", "alert('I changed')");
$("#attach").live($.browser.msie? 'propertychange': 'change', function(e) { ... });
This input file is created on the fly; because of it I use .live() to bind the event.
Any suggestions?
I know this is several months late, but I just ran into the exact same behavior in IE7; in all other browsers, the change event for file inputs happens after file selection. In IE7, it happens only if you trigger the file select again, or on blur.
Here's how I ended up fixing it:
var $input = $('#your-file-input-element');
var someFunction = function()
{
// what you actually want to do
};
if ($.browser.msie)
{
// IE suspends timeouts until after the file dialog closes
$input.click(function(event)
{
setTimeout(function()
{
if($input.val().length > 0) {
someFunction();
}
}, 0);
});
}
else
{
// All other browsers behave
$input.change(someFunction);
}
Technically you could/should filter the hack condition to just IE7, since IE8 behaves properly on the change event, but it also has the same behavior as IE7 on suspending timeouts while browser-related chrome is visible (I guess it considers it blocking I/O), so it works as-is.
This is really late, but I was having the same problem, and I solved it by using a styled <label> tag with a slight workaround for Firefox.
http://jsfiddle.net/djibouti33/uP7A9/
The Goals:
allow user to upload a file by using standard html file input control
hide standard html file input control and apply own styling
after user selects file to upload, automatically submit the form
The Browsers:
Firefox, Chrome, IE8/9, Safari
IE7 didn't work, but it might if you add that browser to the workaround detailed at the bottom
The Initial Solution:
Hide the file input by positioning it offscreen. Important not to display:none as some browsers won't like this.
Add another styled element to the page (link, button).
Listen for a click on that element, then programmatically send a click to the file input to trigger the native 'file explorer'
Listen for the file input's onchange event (occurs after a user chooses their file)
Submit the form
The Problem:
IE: if you programmatically send a click to a file input in order to activate it (2), programmatically submitting the form (5) will throw a security error
The Workaround Solution:
Same as above
Take advantage of the accessibility features built in to the tag (clicking on a label will activate it's associated control) by styling
a tag instead of a link/button
Listen for the file input's onchange event
Submit the form
For some reason Mozilla browsers won't activate a file input by clicking on it's .
For Mozilla, listen for the click on the label and send a click event to the file input to activate it.
Hope this helps! Check out the jsfiddle for details on the html/js/css used to make it all work.
Format it like this:
$("#attach").change(function() {
alert('I Changed');
});
Update: After answering another question on this earlier, we realized this was fixed as part of the jQuery 1.4.2 event re-write, just update to the latest version to resolve the change event issue with <input type="file" /> in IE.
I used the following solution. I tried to make it as self-contained as possible.
(function($) {
if ($.browser.msie == false)
return;
$('input[type=file]').live('click', function(e) {
var self = this;
var blur = function() {
$(self).blur();
}
setTimeout(blur, 0);
});
})(jQuery);
This has always worked for me in IE6 ad IE7.
$('#id-of-input-type-file').change(function(){});
In IE onchange event works fine when it filled out in html tag directly. Like:
<input type="file" onchange="uploader.upload()" />
This is likely a problem with a race condition with input fields in IE. By using setTimeout the function that is executed will then register that a change happened. When the UI code is performed in the onChangeEvent, that event hasn't fired yet as it appears to IE.
I solved a similar situation by doing the following inside my change handler:
if (jQuery.browser.msie) { setTimeout(DoSomeUIChange, 0); } else { DoSomeUIChange(); }
The DoSomeUIChange is executed after the current code on the event queue and so removes the race condition.
I was having the same issue with IE (including IE 9). The UI logic is:
click on a div element triggers the click event on a file-input-element so that user click on a div trigger file open dialog
bind the change event handler to the file-input-element to ensure the form is submitted when file open dialog closed
The app (running inside an iframe) works like a charm on Chrome and FF. But soon I found it doesn't work on IE as when user selected a file and close the dialog the form didn't submit.
The final solution is to drop the logic #1 "click on div element trigger click event on file input element" and let user to click on the file input element directly, and then it works.
BTW, the reason we have a div element is we want to hide the browser rendered controls because we have everything in the background image. However set display to none makes the control not able to respond a user interaction event. So we move the file-input-element to outside of the view port and use a div element to replace it. Since this doesn't work on IE, we end up with move back the file-input-element and set it's opacity to 0. On IE 8 or less which doesn't support opacity, we use filter to make it transparent:
#browse {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
filter: alpha(opacity=0);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
}
I found this solution
In HTML hide file element (don't use display: none, won't work in IE), prepare onchange event of IE:
<div style="width: 0px; height: 0px; overflow: hidden;">
<input id="ifile_template" type="file" onchange="this.focus(); this.blur();"/>
</div>
In javascript for IE bind function to blur, and for FF,CH bind function change():
$(iFile).blur(
function () {
...some code...
}
);
// FF, CH
$(iFile).change(
function () {
...some code...
}
);
For IE You can use the "onfocus" event to catch the change of uploading file. Once the file browsing dialog is closed the onfocus event is triggered. You can check this by adding this line to your page:
<input type="file" onfocus="javascript:alert('test');" />
Once the dialog is closed the alert message is shown.
This solution is only for IE, not for FF or Chrome.
My solution:
setInterval(function()
{
if ($.browser.msie) $("input[type=file]").blur();
},500);
Not pretty, but it works. ;D
I can confirm, at least that it only works after a blur event takes place, similar to a radio and checkbox in IE. I am probably going to have to add some kind of visual element for the user to click and tell me when they have picked their file.
lame.
$("#attach").attr("onChange", "alert('I changed')");
It works in IE, but if you want to emulate "live" behavior, you should add "onChange" attribute to each new element when create its.
jQuery doesn't seem to recognise the propertychange event. I added it to the DOM node using IE's attachEvent().
var userChoseFile = function($input) {
// ...
}
var $input = $(/* your file input */);
$input[0].attachEvent('onpropertychange', function() {
userChoseFile($input);
});
Look at these fiddle http://jsfiddle.net/uP7A9/531/
HTML:
<input type="file" name="PicturePath" id="fileUpload" accept=".png,.jpg,.jpeg,.gif,.tif" />
jQuery:
$("input[type=file]#fileUpload").on("change", function () {
alert('hi')
});
it works for all browsers, tested.

Categories

Resources