I have an UIWebView and loaded the editable div on it. As soon as the app launch's div is loaded on UIWebViewand on tap (implemented the tap gesture), it allows to write anything on it. Now i need to select the font initially after div load's(as soon as app launches), from picker which i have already done than i tap on UIWebView to write with selected font but i am unable to achieve this. But once div / UIWebView is active i.e ready to type than below code works
[webViewForEditing stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"document.execCommand('fontName', true, '%#')",fontName]];
here is my script
<html>
<script type="text/javascript">
document.addEventListener('touchend', function(e){
// Listen for touch end on the document
// Get the touch and coordinates
var touch = e.changedTouches.item(0);
var touchX = touch.clientX;
var touchY = touch.clientY;
// Get the rect for the content
var contentDIVRect = document.getElementById('content').getClientRects()[0];
// Make sure we don't block touches to the content div
if (touchX > contentDIVRect.left && touchY < contentDIVRect.bottom) {
return;
}
// If the touch is out of the content div then simply give the div focus
document.getElementById('content').focus();
document.execCommand('fontName', true, fontName);
}, false);
function moveImageAtTo(x, y, newX, newY) {
// Get our required variables
var element = document.elementFromPoint(x, y);
if (element.toString().indexOf('Image') == -1)
{
// Attempt to move an image which doesn't exist at the point
return;
}
var caretRange = document.caretRangeFromPoint(newX, newY);
var selection = window.getSelection();
// Save the image source so we know this later when we need to re-insert it
var imageSrc = element.src;
// Set the selection to the range of the image, so we can delete it
var nodeRange = document.createRange();
nodeRange.selectNode(element);
selection.removeAllRanges();
selection.addRange(nodeRange);
// Delete the image
document.execCommand('delete');
document.execCommand('insertText', false, ' ');
// Set the selection to the caret range, so we can then add the image
var selection = window.getSelection();
var range = document.createRange();
selection.removeAllRanges();
selection.addRange(caretRange);
// Re-insert the image
document.execCommand('insertImage', false, imageSrc);
}
</script>
<style>
#content img{
height:25px;
width:25px;
}
</style>
<body>
<div id="content" contenteditable="true" style="font-family: Frank the Architect ; font-size:18px">TAP HERE TO BEGIN WRITING...</div>
</body>
Related
I am using simulation for mouse click operation using element.click() in js file, but mouse cursor is some where else and action is performing on correct element, i want to have mouse cursor on element while performing the simulate mouse click.Does anyone know using javascript code, how can i get this?
You cannot move the mousepointer with javascript, because of the security implications that it incurs.
As already pointed out in other answers, you can't change the real mouse position with JavaScript... but... do you need to do that? No!
You can add a image of a mouse cursor and place that on any position you want on top of your content, relative to the browser window top-left.
You can hide the real cursor by applying css 'cursor: none;' class to the zone of the screen you want the cursor to disappear.
So to simulate what you want you can get the position of the element you want to click, hide real mouse cursor, show fake mouse cursor and move that one to the position of the element you want to click, then click it.
To make it user friendly: please notify the user to not move his mouse anymore when you start the simulation, simulate mouse move and click, when user moves his mouse hide the fake mouse and show real mouse and notify user that simulation is over.
You can't change mouse cursor postion in browser. see this.
But you can use javascript click() method to simulate click event. To do this work you must use elementFromPoint() to select click position. In my bottom example when you click on first button, javascript simulate second button click.
var first = document.getElementById("first");
var second = document.getElementById("second");
first.addEventListener("click", function(){
var xPos = second.offsetLeft;
var yPos = second.offsetHeight;
document.elementFromPoint(xPos, yPos).click();
});
second.addEventListener("click", function(){
alert("Second button clicked!");
});
<button id="first">First</button>
<button id="second">Second</button>
I found a git-repository that simulates a mouse-drag event:
link to git-repository
SEE CODEPEN EXAMPLE HERE
useful article
HTML
<!--
author: kemokid
github: https://github.com/kemokid/scripting-sortable/blob/master/script_sortable_dnd_more_general.js
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="main.css">
</head>
<body>
<!-- https://ghostinspector.com/blog/simulate-drag-and-drop-javascript-casperjs/ -->
<p>Drag the W3Schools image into the rectangle:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<img id="drag1" src="https://www.w3schools.com/html/img_logo.gif" ondragstart="drag(event)" >
<br/>
<button onClick="autodrag();">Auto-drag</button>
<br/>
<br/>
Reload the page to reset the image.
<script src="app.js"></script>
</body>
</html>
CSS
/*
author: kemokid
github: https://github.com/kemokid/scripting-sortable/blob/master/script_sortable_dnd_more_general.js
*/
#div1 {
width: 350px;
height: 70px;
padding: 10px;
border: 1px solid #aaaaaa;
}
#drag1 {
width: 336px;
height: 69px;
}
JS
/*
author: kemokid
github: https://github.com/kemokid/scripting-sortable/blob/master/script_sortable_dnd_more_general.js
*/
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var id = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(id));
}
function autodrag() {
return triggerDragAndDrop('#drag1', '#div1');
}
// Originally from https://ghostinspector.com/blog/simulate-drag-and-drop-javascript-casperjs/
// trimmed down and modified by #kemokid (Martin Baker) to work with Sortable.js
///
// Probably not going to work with dragging from one list to another
// This has been made more general, to work with other drag-and-drop elements besides a
// Sortable list, but is not as complete as the Casper example above.
// Call with DOM selectors, eg `triggerDragAndDrop('#drag', '#drop');`
// Returns false if unable to start.
// callback, if present, will be called with true if able to finish, false if not.
// If you receive "false" on the callback, the list is likely not in the beginning state.
var triggerDragAndDrop = function (selectorDrag, selectorDrop, callback) {
var DELAY_INTERVAL_MS = 10;
var MAX_TRIES = 10;
var dragStartEvent;
// fetch target elements
var elemDrag = document.querySelector(selectorDrag);
var elemDrop = document.querySelector(selectorDrop);
if (!elemDrag || !elemDrop) {
console.log("can't get elements");
return false;
}
var startingDropRect = elemDrop.getBoundingClientRect();
function rectsEqual(r1, r2) {
return r1.top === r2.top && r1.right === r2.right && r1.bottom === r2.bottom && r1.left === r2.left;
}
// function for triggering mouse events
function fireMouseEvent(type, elem, dataTransfer) {
var evt = document.createEvent('MouseEvents');
evt.initMouseEvent(type, true, true, window, 1, 1, 1, 0, 0, false, false, false, false, 0, elem);
if (/^dr/i.test(type)) {
evt.dataTransfer = dataTransfer || createNewDataTransfer();
}
elem.dispatchEvent(evt);
return evt;
};
function createNewDataTransfer() {
var data = {};
return {
clearData: function(key) {
if (key === undefined) {
data = {};
} else {
delete data[key];
}
},
getData: function(key) {
return data[key];
},
setData: function(key, value) {
data[key] = value;
},
setDragImage: function() {},
dropEffect: 'none',
files: [],
items: [],
types: [],
// also effectAllowed
}
};
// trigger dragging process on top of drop target
// We sometimes need to do this multiple times due to the vagaries of
// how Sortable manages the list re-arrangement
var counter = 0;
function dragover() {
counter++;
console.log('DRAGOVER #' + counter);
var currentDropRect = elemDrop.getBoundingClientRect();
if (rectsEqual(startingDropRect, currentDropRect) && counter < MAX_TRIES) {
if (counter != 1) console.log("drop target rect hasn't changed, trying again");
// mouseover / mouseout etc events not necessary
// dragenter / dragleave events not necessary either
fireMouseEvent('dragover', elemDrop, dragStartEvent.dataTransfer);
setTimeout(dragover, DELAY_INTERVAL_MS);
} else {
if (rectsEqual(startingDropRect, currentDropRect)) {
console.log("wasn't able to budge drop target after " + MAX_TRIES + " tries, aborting");
fireMouseEvent('drop', elemDrop, dragStartEvent.dataTransfer);
if (callback) callback(false);
} else {
setTimeout(drop, DELAY_INTERVAL_MS);
}
}
}
function drop() {
console.log('DROP');
// release dragged element on top of drop target
fireMouseEvent('drop', elemDrop, dragStartEvent.dataTransfer);
fireMouseEvent('mouseup', elemDrop); // not strictly necessary but I like the symmetry
if (callback) callback(true);
}
// start dragging process
console.log('DRAGSTART');
fireMouseEvent('mousedown', elemDrag);
dragStartEvent = fireMouseEvent('dragstart', elemDrag);
// after a delay, do the first dragover; this will run up to MAX_TRIES times
// (with a delay between each run) and finally run drop() with a delay:
setTimeout(dragover, DELAY_INTERVAL_MS);
return true;
};
I am in a fix. I am not able to identify a way to capture the keyboard show/hide status on a mobile device browser.
Problem :
I have a popup on a form in which a Text Field is present. When the user taps on the text field the keyboard shows up pushing the popup on the form and eventually making the text field invisible.
Is there a way to identify the key board show/hide status???
No, there is no way to reliably know when a keyboard is showing. The one level of control you do have is you can set your app to pan or resize when the keyboard shows up. If you set it to resize, it will recalculate your layout and shrink things so if fits the remaining screen. If you choose pan, it will keep the same size and just slide up the entire app.
you can find out keyboard show/hide inside your application,Try following code inside oncreate method,and pass your parent layout to view.
final View activityRootView = rellayLoginParent;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
Rect r = new Rect();
// r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
//MyLog.w("height difference is", "" + heightDiff);
if (heightDiff > 100)
{ // if more than 100 pixels, its probably a keyboard...
if(lytAppHeader.getVisibility() == View.VISIBLE)
{
lytAppHeader.setVisibility(View.GONE);
}
}
else
{
if(lytAppHeader.getVisibility() == View.GONE)
{
lytAppHeader.setVisibility(View.VISIBLE);
}
}
}
});
It seems there is no reliable way to do this in the browser. The closest I have come is to listen for focus events and then temporarily listen for resize events. If a resize occurs in the next < 1 second, it's very likely that the keyboard is up.
Apologies for the jQuery...
onDocumentReady = function() {
var $document = $(document);
var $window = $(window);
var initialHeight = window.outerHeight;
var currentHeight = initialHeight;
// Listen to all future text inputs
// If it's a focus, listen for a resize.
$document.on("focus.keyboard", "input[type='text'],textarea", function(event) {
// If there is a resize immediately after, we assume the keyboard is in.
$window.on("resize.keyboard", function() {
$window.off("resize.keyboard");
currentHeight = window.outerHeight;
if (currentHeight < initialHeight) {
window.isKeyboardIn = true;
}
});
// Only listen for half a second.
setTimeout($window.off.bind($window, "resize.keyboard"), 500);
});
// On blur, check whether the screen has returned to normal
$document.on("blur.keyboard", "input[type="text"],textarea", function() {
if (window.isKeyboardIn) {
setTimeout(function() {
currentHeight = window.outerHeight;
if (currentHeight === initialHeight) {
window.isKeyboardIn = false;
}, 500);
}
});
};
I am working on some jQuery/JavaScript that makes it possible to drag a div around and simultaneously be able to manipulate other divs (specifically images) on the page. The movable div is basically a transparent rectangle that is meant to simulate a lens. The problem I am having is that I cannot figure out how to pass clicks through to the images below the movable div. I have read up on the pointer-events CSS property and tried setting that to none for the movable div, but that makes the movable div no longer movable. Is there a way for me to pass clicks through this movable div while keeping it movable?
EDIT: To all those asking for my current code, here is the JavaScript that I have so far:
<script>
$(document).ready(function(){
$('img').click(function(e) {
$(document).unbind('keypress');
$(document).keypress(function(event) {
if ( event.which == 115) {
$(e.target).css('width', '+=25').css('height', '+=25');
};
if ( event.which == 97) {
$(e.target).css('width', '-=25').css('height', '-=25');
};
});
});
//code to drag the lens around with the mouse
$("#draggableLens").mousemove(function(e){
var lensPositionX = e.pageX - 75;
var lensPositionY = e.pageY - 75;
$('.lens').css({top: lensPositionY, left: lensPositionX});
});
});
</script>
I created a demo that is proof of concept using document.elementFromPoint to locate the nearest image the moveable element is over. I used jQueryUI draggable to simplify event handling.
The trick with using document.elementFromPoint is you must hide the element you are dragging just long enough to look for other elements, or the draggging element is itself the closest element.
Adding an active class to the closest element allows clicking on the viewer to access the active element
Demo code uses LI tags instead of IMG
var $images = $('#list li');
timer = false;
$('#viewer').draggable({
drag: function(event, ui) {
if (!timer) {
timer = true;
var $self = $(this);
/* use a timeout to throttle checking for the closest*/
setTimeout(function() {
/* must hide the viewer so it isn't returned as "elementFromPoint"*/
$self.hide()
var el = $(document.elementFromPoint(event.pageX, event.pageY));
$('.active').removeClass('active');
if ($el.is('li')) {
$el.addClass('active')
}
$self.show()
timer = false;
}, 100);
}
}
}).click(function() {
if ($('.active').length) {
msg = 'Clicked on: ' + $('.active').text();
} else {
msg = 'Click - No active image';
}
$('#log').html(msg + '<br>');
})
DEMO: http://jsfiddle.net/nfjjV/4/
document.elementFromPoint is not be supported in older browsers. You could also use jQuery position or offset methods to compare coordinates of elements with the current position of the viewer for full browser compatibility
I have a contentEditable Div and I want remove any formatting especially for copy and paste text.
You can add a listener to the "paste" event and reformat the clipboard contents. Like so:
let editableDiv = document.querySelector('div[contenteditable="true"]');
editableDiv.addEventListener("paste", function(e) {
e.preventDefault();
var text = e.clipboardData.getData("text/plain");
document.execCommand("insertHTML", false, text);
});
Here another example for all containers in the body:
let allEditableDivs = document.querySelectorAll('div[contenteditable="true"]');
[].forEach.call(allEditableDivs, function (el) {
el.addEventListener('paste', function(e) {
e.preventDefault();
var text = e.clipboardData.getData("text/plain");
document.execCommand("insertHTML", false, text);
}, false);
}
Saludos.
Have you tried using innerText?
ADDED:
If you want to strip markup from content pasted into the editable div, try the old hack of creating a temporary div -- see example below.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Strip editable div markup</title>
<script type="text/javascript">
function strip(html) {
var tempDiv = document.createElement("DIV");
tempDiv.innerHTML = html;
return tempDiv.innerText;
}
</script>
</head>
<body>
<div id="editableDiv" contentEditable="true"></div>
<input type="button" value="press" onclick="alert(strip(document.getElementById('editableDiv').innerText));" />
</body>
</html>
Was looking for answer to this for ages and ended up writing my own.
I hope this helps others. At the time of writing this it appears to work in ie9, latest chrome and firefox.
<div contenteditable="true" onpaste="OnPaste_StripFormatting(this, event);" />
<script type="text/javascript">
var _onPaste_StripFormatting_IEPaste = false;
function OnPaste_StripFormatting(elem, e) {
if (e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.getData) {
e.preventDefault();
var text = e.originalEvent.clipboardData.getData('text/plain');
window.document.execCommand('insertText', false, text);
}
else if (e.clipboardData && e.clipboardData.getData) {
e.preventDefault();
var text = e.clipboardData.getData('text/plain');
window.document.execCommand('insertText', false, text);
}
else if (window.clipboardData && window.clipboardData.getData) {
// Stop stack overflow
if (!_onPaste_StripFormatting_IEPaste) {
_onPaste_StripFormatting_IEPaste = true;
e.preventDefault();
window.document.execCommand('ms-pasteTextOnly', false);
}
_onPaste_StripFormatting_IEPaste = false;
}
}
</script>
Try <div id="editableDiv" contentEditable="plaintext-only"></div>
I know it's been a while, but I had the same problem. On my case, it's a GWT application to make it even worse.
Anyway, resolved the problem with:
var clearText = event.clipboardData.getData('text/plain');
document.execCommand('inserttext', false, clearText);
See: https://jsfiddle.net/erikwoods/Ee3yC/
I preferred "inserttext" command instead of "insertHTML", because the documentation says it's exactly to insert plain text, so seems more suitable.
See https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
With Jquery you can use .text() method, so, when blur for example you can replace the content with the text content
$("#element").blur(function(e) {
$(this).html($(this).text());
});
You can't access the system clipboard so you'll need a hack. See this question: JavaScript get clipboard data on paste event (Cross browser)
I'd like to add my solution to this issue:
ContentEditableElement.addEventListener('input', function(ev) {
if(ev.target.innerHTML != ev.target.textContent) {
// determine position of the text caret
var caretPos = 0,
sel, range;
sel = window.getSelection();
if (sel.rangeCount) {
range = sel.getRangeAt(0);
var children = ev.target.childNodes;
var keepLooping = true;
for(let i = 0; keepLooping; i++) {
if(children[i] == range.commonAncestorContainer || children[i] == range.commonAncestorContainer.parentNode) {
caretPos += range.endOffset;
keepLooping = false;
} else {
caretPos += children[i].textContent.length;
}
}
// set the element's innerHTML to its textContent
ev.target.innerHTML = ev.target.textContent;
// put the caret where it was before
range = document.createRange();
range.setStart(ev.target.childNodes[0], caretPos);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
});
(this isn't compatible with older versions of IE)
Just for my later life. ;)
styles.css
/* Not easy to look exactly like input field: */
/* https://stackoverflow.com/a/8957518/1707015 */
.contenteditable_div {
/* box-shadow: 1px 1px 1px 0 lightgray inset; */
background-color:#dddddd;
overflow-wrap:break-word;
padding:3px;
}
index.html
<!-- Firefox doesn't support contenteditable="plaintext-only" yet! -->
<div class="contenteditable_div" contenteditable="true" id="blubbi">abc</div>
script.js
// Optional: Copy font from other input field:
// $('#blubbi').css('font', $('#blubbi_input_field').css('font'));
$('.contenteditable_div').on('input', function(){
// problems with setting cursor to beginning of div!
// this.innerHTML = this.innerText;
$(this).text($(this).text());
});
Keep in mind that this solution doesn't support or care about line breaks.
And keep in mind that setting the text like this will set the cursor to the beginning of your contenteditable div - while you are typing. Still a good solution if you need it only for copy & paste. Please write a comment if you have an easy solution for this "reverse typing problem" (under 10 lines of code please). ;)
Tested on Firefox 89, Chrome 90 and Safari 14.
Is it possible to fire a specific JavaScript event when a certain DIV comes into view on the page?
Say, for example, I have a very large page, like 2500x2500 and I have a 40x40 div that sits at position 1980x1250. The div is not necessarily manually positioned, it could be there due to the content pushing it there. Now, is it possible to run a function when the user scrolls to a point where the div becomes visible?
Not automatically. You would have to catch scroll events and check for it being in view each time by comparing the co-ordinates of the div rectangle with the visible page rectangle.
Here's a minimal example.
<div id="importantdiv">hello</div>
<script type="text/javascript">
function VisibilityMonitor(element, showfn, hidefn) {
var isshown= false;
function check() {
if (rectsIntersect(getPageRect(), getElementRect(element)) !== isshown) {
isshown= !isshown;
isshown? showfn() : hidefn();
}
};
window.onscroll=window.onresize= check;
check();
}
function getPageRect() {
var isquirks= document.compatMode!=='BackCompat';
var page= isquirks? document.documentElement : document.body;
var x= page.scrollLeft;
var y= page.scrollTop;
var w= 'innerWidth' in window? window.innerWidth : page.clientWidth;
var h= 'innerHeight' in window? window.innerHeight : page.clientHeight;
return [x, y, x+w, y+h];
}
function getElementRect(element) {
var x= 0, y= 0;
var w= element.offsetWidth, h= element.offsetHeight;
while (element.offsetParent!==null) {
x+= element.offsetLeft;
y+= element.offsetTop;
element= element.offsetParent;
}
return [x, y, x+w, y+h];
}
function rectsIntersect(a, b) {
return a[0]<b[2] && a[2]>b[0] && a[1]<b[3] && a[3]>b[1];
}
VisibilityMonitor(
document.getElementById('importantdiv'),
function() {
alert('div in view!');
},
function() {
alert('div gone away!');
}
);
</script>
You could improve this by:
making it catch onscroll on all ancestors that have overflow scroll or auto and adjusting the top/left co-ords for their scroll positions
detecting overflow scroll, auto and hidden cropping putting the div off-screen
using addEventListener/attachEvent to allow multiple VisibilityMonitors and other things using the resize/scroll events
some compatibility hacks to getElementRect to make the co-ords more accurate in some cases, and some event unbinding to avoid IE6-7 memory leaks, if you really need to.
Here is a solution that is ideal in 2022. The current top answer only allows you to observe one item, and has performance issues because it fires many times every time the page scrolls.
var observer = new IntersectionObserver(function(entries) {
if(entries[0].isIntersecting === true) {
console.log('Item has just APPEARED!');
} else {
console.log('Item has just DISAPPEARED!');
}
}, { threshold: [0] });
observer.observe(document.querySelector("#DIV-TO-OBSERVE"));
This fires as soon as the item is partially on screen. Changing threshold to 1 will require the item to be fully on screen (so it will never fire if the item is bigger than the viewport). You can do values in between for example 0.25 to fire when at least 1/4 of the item is in view.
Here's an starter example using jQuery:
<html>
<head><title>In View</title></head>
<body>
<div style="text-align:center; font-size:larger" id="top"></div>
<fieldset style="text-align:center; font-size:larger" id="middle">
<legend id="msg"></legend>
<div> </div>
<div id="findme">Here I am!!!</div>
</fieldset>
<div style="text-align:center; font-size:larger" id="bottom"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
var $findme = $('#findme'),
$msg = $('#msg');
function Scrolled() {
var findmeOffset = $findme.offset(),
findmeTop = findmeOffset.top,
scrollTop = $(document).scrollTop(),
visibleBottom = window.innerHeight;
if (findmeTop < scrollTop + visibleBottom) {
$msg.text('findme is visible');
}
else {
$msg.text('findme is NOT visible');
}
}
function Setup() {
var $top = $('#top'),
$bottom = $('#bottom');
$top.height(500);
$bottom.height(500);
$(window).scroll(function() {
Scrolled();
});
}
$(document).ready(function() {
Setup();
});
</script>
</body>
</html>
It only notifies once the div comes into view from the bottom. This example does not notify when the div scrolls out of the top.