So, related to an earlier question, but forgive me for my naive javascript ways. Basically I now want to automatically bring a text input into focus when it is added to the DOM. Part of me thinks that I might be trying to add focus to the object before it exists, but I'm not quite sure how I would go about fixing it. Right now this is my relevant code:
var searchWrapper = document.createElement("div");
searchWrapper.id = "search-wrapper";
this.parentNode.replaceChild(searchWrapper, this);
document.getElementById("search-wrapper").focus();
But it's not quite working. Should I be setting focus as a callback on replaceChild, or is there some other way to do this?
Try the following:
Live Demo
var searchOrig = document.getElementById("search-wrapper");
var searchWrapper = document.createElement("div");
searchWrapper.id = "search-wrapper";
searchWrapper.setAttribute('tabindex', '0');
searchOrig.parentElement.replaceChild(searchWrapper, searchOrig);
document.getElementById("search-wrapper").focus();
Related
I am trying to write a ToDoList with JavaScript.
I have an input-element. Whenever I type something and press enter, it creates a new fieldset(in my example its a fieldset but it can also be a Div) with the class name ".fieldListClass" and a P-Tag as a child of fieldset. the P-tag innerHTML is the the value of input. I used Click-EventListener for that.
After each click, I assigned the query selector of all .fieldListClass to a nodeList "fieldListQuery". I even converted this nodeList into an Array but no result.
Now I want to create an addEventListner but outside the previous one. it should be a new one. And It should be a click-EventListener for all fieldListQuery which where created inside the previous function.(this part is at the bottom of my code)
When I click on it something should happen like removing the current target etc. But it wont work because outside the function it always says that this variable is undefined. I don't get it because I declared it global outside of the function.
I don't want to use DOMNodeInserted or MutationObserver yet for detecting changes inside the DOM. Simple because the first one is not recommended anymore it and the last one I have no idea how to use it. Many people saying that this is not a safe way.
Any Help please?
let addDiv = document.createElement("div"); addDiv.id = "addDivId";
let listDiv = document.createElement("div"); listDiv.id = "listDivId";
let inputText = document.createElement("input"); inputText.id = "inputTextId";
let fieldList; // = document.createElement("fieldset");
let fieldDiv; // = document.createElement("div");
let fieldDivP; // = document.createElement("P");
let fieldListArr;
let fieldListQuery;
document.body.appendChild(addDiv);
addDiv.appendChild(inputText);
document.body.appendChild(listDiv);
inputText.addEventListener("keypress", event => {
if (event.key === "Enter") {
fieldList = document.createElement("fieldset");
fieldDiv = document.createElement("div");
fieldDivP = document.createElement("P");
listDiv.appendChild(fieldList);
fieldList.className = "fieldListClass";
fieldList.appendChild(fieldDiv);
fieldDiv.appendChild(fieldDivP);
fieldDivP.innerHTML = inputText.value;
fieldListQuery = document.querySelectorAll(".fieldListClass") ;
}
})
fieldListQuery.forEach(element => { // <- it say fieldListQuery is undefined.
fieldListQuery.addEventListener("click", e => {
e.currentTarget.innerHTML="test";
})
});
´´´
Since I offered critique of your approach, I thought it is only fair I at least try to offer you some code that accomplishes (on the overall level, in light of absence of much detail about your solution) something along of what you have.
First off, I think creating trees of elements through a script when other solutions are more viable, tends to show an anti-pattern. Your script is invariably loaded in the context of an HTML document, which may already contain a lot of useful markup -- including an input field (that you were creating with createElement). If the input field is a "constant" there is no need to waste code on creating it -- just put it in your markup.
Second, even for elements or hierarchies of elements that are created "on demand" -- as a reaction to an event or however else -- it typically is much more readable and manageable to use templates. As a fallback -- if template cannot be used for some reason -- using innerHTML to create entire element trees is actually an appealing and more readable option than a lot of "boilerplate" containing createElement, appendChild, etc.
Third, you should always try to see if you can have your interactive controls be part of a form. I won't go into all reasons to do so, but suffice to say it helps user agents that screen-read content and for other accessibility systems, to name one. There are exceptions to this rule, but I don't recall looking at code where a control should not be part of a form -- so the rule is a good one.
Here is a proof-of-concept bare-bones to-do application:
<html>
<head>
<script>
function submit_create_todo_item_form() {
const new_todo_fragment = document.getElementById("todo-item-template").content.cloneNode(true);
new_todo_fragment.querySelector(".body").textContent = document.forms[0].elements[0].value;
document.body.appendChild(new_todo_fragment);
}
</script>
<template id="todo-item-template">
<div class="todo-item">
<p class="body"></p>
</div>
</template>
</head>
<body>
<form action="javascript: submit_create_todo_item_form()">
<input>
</form>
</body>
<html>
Take note that I use textContent instead of innerHTML to create content for a to-do item's body. innerHTML invokes the HTML parser and unless you plan to be typing hypertext into that single line of input field, innerHTML only costs you extra for no clear benefit. If you need to interpret the value verbatim, textContent is instead exactly what's needed. So, approach your solution with that in mind.
I hope this is useful, I worked with what I thought I had.
I'm working on something where multiple functions will add various Event listeners to an initially hidden div, let's just call it secretBlock. Only one will ever be active at any given point, but all said functions will manipulate it by:
First cloning sercetBlock to ensure no previous listeners are still attached
Then setting the display to flex
HTML:
<div id="secretBlock" hidden>Secret</div>
JavaScript:
function exampleFuction() {
var secretBlock = document.getElementById('secretBlock');
var secretClone = secretBlock.cloneNode(true);
secretBlock.parentNode.replaceChild(secretClone, secretBlock);
secretBlock.style.display = 'flex';
....
}
but the last part, setting the display, is not firing.
I assumed this had something to do with async-ness, but
setTimeout(function(){ secretBlock.style.display = 'flex' }, 999);
also had no effect.
However, one of the functions appends the div inside of another div right after setting the display, causing it to fire properly:
secretBlock.parentNode.replaceChild(secretClone, secretBlock);
secretBlock.style.display = 'flex';
otherDiv.appendChild(secretBlock);
After a bit of testing, I found out it doesn't matter when I set the display (now vs later) or where it is in the code, as long as secretBlock gets appended to another div, the display change will register, otherwise staying hidden.
.......which sorta left me clueless as to what's going on, any insight would thus be much appreciated~~
Was a reference issue.
After .replaceChild() replaces secretBlock, the initial reference:
var secretBlock = document.getElementById('secretBlock')
becomes obsolete as it still points to the old, original element which is not apart of the html document anymore. Thus you need to redirect the reference to the cloned element:
secretBlock.parentNode.replaceChild(secretClone, secretBlock);
secretBlock = document.getElementById('secretBlock');
secretBlock.style.display = 'flex';
Thanks Dr.Molle!
I'm trying to create multiple iron-collapse elements with content inside. I want the iron-collapse to expand when user clicks on a button. The problem is that I can't get each element expanded individually. The script catches only first element and does not affect the others. I've tried many code samples but without success. Can someone help me? My code is below:
var expandContent = document.getElementById('mybutton');
expandContent.onclick = function(event) {
var moreInfo = document.getElementById('moreinfo');
var iconButton = Polymer.dom(event).localTarget;
iconButton.icon = moreInfo.opened ? 'hardware:keyboard-arrow-down'
: 'hardware:keyboard-arrow-up';
/*moreInfo.toggle();*/ /* This one works to, don't know which is better */
event.currentTarget.parentElement.querySelector('iron-collapse').toggle();
};
<paper-card style="width:100%;line-height:56px;font-size:16px;font-weight:400;">
<paper-icon-button class="mybutton" id="mybutton" icon="hardware:keyboard-arrow-up" style="float:right;margin:8px;" >
</paper-icon-button>
<iron-icon icon="communication:forum"></iron-icon>
<iron-collapse id="moreinfo" class="moreinfo" style="width:100%;">
<paper-item>
<iron-icon icon="info"></iron-icon>
<paper-item-body two-line>
<div>Primary text</div>
<div secondary>Secondary text</div>
</paper-item-body>
</paper-item>
<paper-item>Second item</paper-item>
<paper-item>Third item</paper-item>
</iron-collapse>
</paper-card>
I want only one collapse to expand after it's corresponding button is being pressed. Is there way to change this code to achieve what I need, without complete rewrite, because only with this code iron-collapse works properly and changes its attribute expanded="yes/no", which I later use with cookies?
The problem is here:
var expandContent = document.getElementById('mybutton');
Why are you looking for "mybutton" on entire document? You don´t need to do that because Polymer´s encapsulate each component so you can use it in multiples situations.
As documentation say´s:
Polymer automatically builds a map of statically created instance nodes in its local DOM, to provide convenient access to frequently used nodes without the need to query for them manually. Any node specified in the element’s template with an id is stored on the this.$ hash by id.
So, you need to change document.getElementById('mybutton') to this.$.mybutton to refer the local dom button. On this way, should work.
Edit
Using your code and not doing it as it should in Polymer, maybe this will help you:
var idArray =["mybutton","mybutton2","mybutton3"];
idArray.forEach(function(item,index,array){
var expandContent = document.getElementById(item);
expandContent.onclick = function(event) {
var moreInfo = document.getElementById('moreinfo');
var iconButton = Polymer.dom(event).localTarget;
iconButton.icon = moreInfo.opened ? 'hardware:keyboard-arrow-down'
: 'hardware:keyboard-arrow-up';
/*moreInfo.toggle();*/ /* This one works to, don't know which is better */
event.currentTarget.parentElement.querySelector('iron-collapse').toggle();
};
}.bind(this));
Update
Ok, i found proper solution after reading some forums and js docs, i will write it down, maybe someone needs it too.
var elems = document.getElementsByClassName('mybutton'); // Getting all button with same class name
for(var i = 0; i < elems.length; i++) { // Adding count indexes to buttons starting from first is 0
elems[i].onclick = function(event){ //And here is function to do expand/collapse, it can be any other function too, main idea was to get work/trigger all items with same class
var expandContent = event.currentTarget.parentElement.querySelector('iron-collapse');
var iButton = Polymer.dom(event).localTarget;
iButton.icon = expandContent.opened ? 'hardware:keyboard-arrow-down' : 'hardware:keyboard-arrow-up';
event.currentTarget.parentElement.querySelector('iron-collapse').toggle();
console.log("Works ! Great !!!");
}
}
I have added an onclick function to a div here:
<script type="text/javascript">
document.getElementById("fab").onclick = function() {
location.href = 'http://your.url.here';
}
</script>
When you hover over the div, it doesnt show the URL in the bottom left of the browser like an anchor tag does (see picture): http://i.stack.imgur.com/iGLHS.png
Is there any way to make the browser show the link, when it has been added with javascript?
Add the title attribute to your element:
<div id="fab" title="http://your.url.here'></div>
Actually this is different than the popup you're seeing, but it might be as close as you can get.
As #Benten points out, you'd have to set window.status, which isn't allowed by most modern browsers.
I don't think you can directly access the property that you are looking for any more. Usually it's ignored. See this: http://www.w3schools.com/jsref/prop_win_status.asp . I'd say the other answer is your best bet.
I think something different. I hope i didnt understand it wrong. If you add -a- element as parent to your -div- it acts like what you want.
var element = document.getElementById("fab");
var aa = document.createElement("a");
aa.setAttribute('href', 'http://www.google.com');
var parent = element.parentNode;
parent.insertBefore(aa, element);
aa.appendChild(element);
please let me know if i understand it wrong?
Hey Guys -- I'm using a jQuery UI dialog box on my site but it's using absolute positioning and I need relative. My solution is to wrap the dynamically created DIV in a relatively positioned element.
I found the line of code I need to change but I think my change is affecting the "container" variable and breaking the remainder of the code. Does anyone know the best way to change this:
function initialize(instance) {
_this = instance;
// build html
var realCaller = caller != null? caller:$("body");
var cornerClass = options.showRoundCorner? "ui-corner-all ":"";
realCaller.append("<div id='"+windowId+"' class='window_panel "+cornerClass+options.containerClass+"'></div>");
container = realCaller.children("div#"+windowId);
to add "<div class=window_container>" on the "append" line, like this:
function initialize(instance) {
_this = instance;
// build html
var realCaller = caller != null? caller:$("body");
var cornerClass = options.showRoundCorner? "ui-corner-all ":"";
realCaller.append("<div class=window_container><div id='"+windowId+"' class='window_panel "+cornerClass+options.containerClass+"'></div></div>");
container = realCaller.children("div#"+windowId);
I don't know why it's breaking the rest of the script but I assume it's something to do with the way the "container" is being created and referenced by the rest of the JS.
Been working on this for over 8 hours now.. anyone can help!?
I can provide more details if necessary.
Cheers!