Use XPath or onClick or onblur to select an element and use jQuery to blur this element - javascript

*UPDATE:I am new to jQuery, as well as using XPath, and I am struggling with getting a proper working solution that will blur a dynamically created HTML element. I have an .onblur event hooked up (doesn't work as expected), and have tried using the $(document.activeElement), but my implementation might be incorrect. I would appreciate any help in creating a working solution, that will blur this element (jqInput) when a user clicks anywhere outside the active element. I have added the HTML and jQuery/JavaScript below.
Some ideas I have had:
(1) Use XPath to select a dynamic HTML element (jqInput), and then use jQuery's .onClick method to blur a this element, when a user clicks anywhere outside of the area of the XPath selected element.
(2) Use the $(document.activeElement) to determine where the .onblur should fire:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
I am open to all working solutions. And hopefully this will answer someone else's question in the future.
My challenge: Multiple elements are active, and the .onblur does not fire. See the image below:
NOTE: The <input /> field has focus, as well as the <div> to the left of the (the blue outline). If a user clicks anywhere outside that <input />, the blur must be applied to that element.
My Code: jQuery and JavaScript
This is a code snippet where the variable jqInput and input0 is created:
var jqInput = null;
if (jqHeaderText.next().hasClass("inline-editable"))
{
//Use existing input if it already exists
jqInput = jqHeaderText.next();
}
else
{
//Creaet a new editable header text input
jqInput = $("<input class=\"inline-editable\" type=\"text\"/>").insertAfter(jqHeaderText);
}
var input0 = jqInput.get(0);
//Assign key down event for the input when user preses enter to complete entering of the text
input0.onkeydown = function (e)
{
if (e.keyCode === 13)
{
jqInput.trigger("blur");
e.preventDefault();
e.stopPropagation();
}
};
This is my .onblur event, and my helper method to blur the element:
input0.onblur = function ()
{
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
};
inputOnBlurHandler: function (canvasObj, jqHeaderText, jqInput)
{
// Hide input textbox
jqInput.hide();
// Store the value in the canvas
canvasObj.headingText = jqInput.val();
_layout.updateCanvasControlProperty(canvasObj.instanceid, "Title", canvasObj.headingText, canvasObj.headingText);
// Show header element
jqHeaderText.show();
_layout.$propertiesContent.find(".propertyGridEditWrapper").filter(function ()
{
return $(this).data("propertyName") === "Title";
}).find("input[type=text]").val(canvasObj.headingText); // Update the property grid title input element
}
I have tried using the active element, but I don't think the implementation is correct:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
My HTML code:
<div class="panel-header-c">
<div class="panel-header-wrapper">
<div class="panel-header-text" style="display: none;">(Enter View Title)</div><input class="inline-editable" type="text" style="display: block;"><div class="panel-header-controls">
<span></span>
</div>
</div>
</div>
I thank you all in advance.

Related

input button disappears after click event bubbles up to parent

So I'm learning JS and figuring out how events work. I understand at a high-level that events bubble up through the DOM nodes. Right now I have a bookDiv that executes an updated textContent only when its child button registers a click. I added some functionality where only if event.target.tagName === "INPUT" does the textContent get updated.
My issue is that after this parent node (bookDiv) handles the click, the children of that bookDiv (which is just a <br> and the button) all disappear. I have to re-add them but this is hacky and I don't understand why this is happening. Looking for an explanation.
Note: within the generateReadStatusButtonForBook(book) I'm passing in book, an object, to an addEventListener which requires a handleEvent. I haven't included the object in the code.
Thank you for your help
function generateNewBookDiv(book) {
const bookDiv = document.createElement("div");
bookDiv.classList.add("book-item");
bookDiv.textContent = `${book.title}\r\nby ${book.author}\r\nNumber of Pages: ${book.numPages}\r\nRead?${book.isRead}`;
// quick way to get a line break after the last text content for our read status button
const lineBreak = document.createElement("br");
bookDiv.appendChild(lineBreak);
bookDiv.appendChild(generateReadStatusButtonForBook(book));
bookDiv.addEventListener("click", (event) => {
//console.log("book div activating its click event");
if (event.target.tagName === "INPUT") {
//console.log("read button was identified and bubbled up");
event.currentTarget.textContent = `${book.title}\r\nby ${book.author}\r\nNumber of Pages: ${book.numPages}\r\nRead?${book.isRead}`;
const lineBreak = document.createElement("br");
bookDiv.appendChild(lineBreak); // not sure why the <br> and <button> elements disappear after click
bookDiv.appendChild(generateReadStatusButtonForBook(book));
}
});
container.appendChild(bookDiv);
}
// add read status button for each book
function generateReadStatusButtonForBook(book) {
const readStatus = document.createElement("INPUT");
readStatus.setAttribute("type", "button");
readStatus.classList.add("read-status");
readStatus.addEventListener("click", book); // toggle read status by passing in Book object which will do the toggling itself
return readStatus;
}

Live HTML/CSS preview from a div tag and not a text area tag

I want to create a live HTML/CSS preview on a page.
But the code will not be given using textareas. The code is going to be fixed in the page (div).
I want the user to be able to alter the code and that will reflect on the live preview box.I have created the page where you can change parts of the script text (for amateurs). You can preview that here :
http://apolosiskos.co.uk/HTML-CSS-EDITOR/index3.html
01) The live preview does not work if I replace the textarea with a div.
02) Even if I use the textareas, the live preview does not work because in my HTML script I am using the codeand the xmp tags.
--> Snippet that works with a textarea but not with a div :
var wpcomment = document.getElementById('WPComment');
wpcomment.blur = wpcomment.onkeypress = function(){
document.getElementById('prevCom').innerHTML = this.value;
}
#prevCom
{
background:#124;
color:#fff;
min-width:20px;
min-height:50px;
font-size:25pt;
}
<textarea name="WPcomment" id="WPComment" placeholder="Add comments:">aaaaa</textarea>
<div id="prevCom"></div>
with no success. Is there any other addEventListener() method I can replace keyup with?
Yes, blur
If you would like to add keydown events on a <div> element, you can do the following:
First, you need to set the tabindex attribute:
<div id="a-div" tabindex="1" />
Then,
(2) Bind to keydown:
$('#mydiv').bind('keydown', function(event) {
//console.log(event.keyCode);
});
If you would like your div to be "focused" from the start:
$(function() {
$('#mydiv').focus();
});
You should place your preview code it within a function, then you can simply call it once the document has loaded.
https://jsfiddle.net/michaelvinall/4053oL1x/1/
The separate issue of your preview only rendering when you press the enter key, is because of the following if statement:
if(e.which == 13 && $(this).val().length > 0)
The e.which == 13 within your if is specifying that the code within the block should only be ran if the key pressed by the user was the enter key (code 13). By removing this portion of each if statement, any key pressed will execute the code within the block:
if($(this).val().length > 0)
Your function is call when keyup is trigger, but no after page load.
You must do it : Define function to call them when 2 different event are fired.
$(function() {
function GetHtml(){
var html = $('.html').val();
return html;
}
function GetCss(){
var Css = $('.css').val();
return Css;
}
var previewRendering = function(){
console.log('kikou');
var targetp = $('#previewTarget')[0].contentWindow.document;
targetp.open();
targetp.close();
var html = GetHtml();
var css = GetCss();
$('body',targetp).append(html);
$('head', targetp).append('<style>' + css + '</style>');
};
$('.innerbox').on("keyup",function(){
previewRendering();
});
$(document).ready(function() {
previewRendering();
});
});
This code can not work because load event is only compatible with this list of HTML tags: body, frame, iframe, img, input type="image", link, script, style
$('.innerbox').load(function()

Check that two elements aren't in focus

I have to input elements #Core and #Price that cannot share a parent element. I need to test that both of them are not in focus and when they are not run a function.
I thought I could just do a check to make sure when one blurs the other isn't given focus like so:
$('#Core').blur(function() {
if(!$("#Price").is(":focus")) {
getSellingPrice()
}
});$('#Price').blur(function() {
if(!$("#Core").is(":focus")) {
getSellingPrice()
}
});
But this seems to fire even when I give focus to the other input node. My guess is that when the blur happens it checks the seconds focus before its yet been selected. But I am uncertain as to how to change the code to get the desired behavior of making sure both elements aren't in focus before triggering the function call.
Any ideas on how I might accomplish this or insight into why this current code isn't working are greatly appreciated.
You can just check that the active element is neither
var elems = $('#Core, #Price').blur(function() {
setTimeout(function() {
if ( elems.toArray().indexOf(document.activeElement) === -1 ) {
getSellingPrice();
}
});
});
But you'll need a timeout to make sure the focus is set etc.
Blurring an element passes focus to the body element before transferring it to a sub element clicked. Horrible as may be a one shot timer can be used to decouple blurring with checking what element was clicked. Concept code triggered by blur events (translate to your coding standards, jQuery and application as needed):
function blurred(el)
{
setTimeout(checkFocus, 4); // ( 4 == Firefox default minimum)
}
function checkFocus()
{ var a = document.getElementById("a");
var b = document.getElementById("b");
var infocus = document.activeElement === a || document.activeElement === b;
if(infocus)
console.log( "One of them is in focus");
else
console.log(" Neither is in focus");
}
HTML
a: <input id="a" type="text" onblur="blurred(this)"><br>
b: <input id="b" type="text" onblur="blurred(this)">

jQuery highlight plugin cancels text selection, making copy impossible while also rendering links unclickable

I'm using the jQuery Highlight plugin to select some text on a web page.
I've hooked up selecting and deselecting with mouse events:
document.addEventListener('mouseup', doSelect);
document.addEventListener('mousedown', doDeselect);
The functions are:
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$('body').highlight(selection);
}
}
function doDeselect() {
$('body').unhighlight();
}
Short and easy. The library searches for the selected text and wraps each occurrence in a <span> and so the text stands out.
It's working great, but I have two issues with how it behaves.
The problem is that once the span elements are applied, I cannot click hyperlinks (the ones that were found/selected), they don't react to clicks (I have to deselect the text first).
Once the span elements are added, the original selection is somehow lost, i.e. I cannot copy what I selected with CTRL+C.
These issues can be seen in this jsfiddle.
Why is this happening?
The code
The working demo is available here: jsfiddle
JavaScript
var $body = $('body');
var $copyArea = $('#copyArea');
document.addEventListener('mouseup', doSelect);
document.addEventListener('mousedown', doDeselect);
document.addEventListener('keydown', keyPressHandler);
function keyPressHandler(e) {
if(e.ctrlKey && e.keyCode == 67) {
$copyArea.focus().select();
}
}
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$copyArea.val(selection);
$body.highlight(selection);
}
}
function doDeselect(e) {
var elem = $(e.target).parents('a');
if(elem.length == 0) {
$copyArea.val('');
$body.unhighlight();
}
}
HTML
Sample text to select.
<br/>Sample text to select.
<br/>Sample text to select.
<br/>google.com
google.com
<a href="http://google.com" target="_blank">
<span>
<span>google.com</span>
</span>
</a>
<textarea id="copyArea"></textarea>
CSS
.highlight {
background-color: #FFFF88;
}
#copyArea {
position:fixed;
top:-999px;
height:0px;
}
Part 1 - Clicking through the selection
Presumably, the reason clicking on a highlighted link doesn't work is because the process that disables the highlighting kicks in first and cancels the click.
To bypass that, we implement a condition that checks if the target element of the mousedown event has an a element as ancestor. If that is true, we simply do not execute $body.unhighlight();, allowing the click to pass through and open the link.
function doDeselect(e) {
var elem = $(e.target).parents('a');
if(elem.length == 0) {
$copyArea.val('');
$body.unhighlight();
}
}
Part 2 - Copying the selection
Presumably, again, the reason the selection is lost is because the document is modified by the highlighting, which introduces elements into the DOM.
My first idea was to reapply the selection after the modification was done. This became annoying and I went in a different direction, which allowed me to stumble upon this:
The Definitive Guide to Copying and Pasting in JavaScript
This offered a simple and efficient idea: using an hidden element that could contain selectable text.
Therefore, to allow copying the selected text that we highlighted despite having lost the original selection:
We add a hidden textarea element to our document.
<textarea id="copyArea"></textarea>
We get a reference to that element.
var $copyArea = $('#copyArea');
We add an event handler for the keydown event.
document.addEventListener('keydown', keyPressHandler);
We add the event handler.
function keyPressHandler(e) {
if(e.ctrlKey && e.keyCode == 67) {
$copyArea.focus().select();
}
}
We modify doSelect() to add some logic that will set the selection as the value of the textarea element, in the form of $copyArea.val(selection);.
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$copyArea.val(selection);
$body.highlight(selection);
}
}
What does the handler do ? it captures the combination CTRL+C and focuses on the text in the hidden textarea, which ends up being copied by the keyboard command we just issued.

Getting siblings value with javascript

I create a textarea and a button on a loop based on a certain condition:
while($row_c= mysqli_fetch_array($result_comments))
{
//some code goes here
<textarea type="text" id="pm_text" name="text"></textarea><br>
<button name="send_comment" id="post_comment" class="button" onClick="post_pm_comment()">Post</button>
}
Now in my function "post_pm_comment" I would like to access the text written in the textarea when the post button is clicked.
I tried this, but it only gives me the text of the first textarea and button created:
function post_pm_comment(thidid, pm_id, path, pm,getter)
{
var pm_text = document.getElementById("pm_text").value;
}
What should I do?
Thank you
Your code is outputting an invalid DOM structure, because id values must be unique on the page. You cannot have the same id on more than one element. Remove the id values entirely, you don't need them.
Having done that, the minimal-changes answer is to pass this into your handler:
onClick="post_pm_comment(this)"
...and then in your handler, do the navigation:
function post_pm_comment(postButton)
{
var pm_text;
var textarea = postButton.previousSibling;
while (textarea && textarea.nodeName.toUpperCase() !== "TEXTAREA") {
textarea = textarea.previousSibling;
}
if (textarea) {
pm_text = textarea.value; // Or you may want .innerHTML instead
// Do something with it
}
}
Live Example | Source

Categories

Resources