I'm trying to dynamically add a page to iron-pages, but the element doesn't recognize the dynamically added content. I think this happen during html rendering, but I don't know how to trigger it again. The jsbin below demonstrates what I'm trying to do: http://jsbin.com/nuhone/4/edit?html,console,output. Basically, I have an iron-pages with one existing page. I'm trying to add a second page dynamically, but unable to do so because iron-pages doesn't recognize this newly added div.
Took a look at your code - basically 2 issues.
Polymer.domAPI
When inserting or removing nodes, use it.
Race Condition
iron-pages extends IronSelectableBehavior - ie MutationObservers have already been setup nicely to detect whenever you add/remove pages. However, this takes time to trigger. Wrap your next steps with Polymer.async() to place them at the end of the microtasks queue.
document.addEventListener("WebComponentsReady", function() {
var newDiv = document.createElement("div");
newDiv.innerHTML = "Def";
var ironPage = document.querySelector("iron-pages");
Polymer.dom(ironPage).appendChild(newDiv);
Polymer.Base.async(function () {
console.log(ironPage.items.length); // shows 2
ironPage.select(1);
});
});
Your jsbin fixed: http://jsbin.com/viqunoxesi/edit?html,console,output
It might help to use the Polymer DOM API like
Polymer.dom(document.querySelector("iron-pages"))
.appendChild(newDiv);
Related
I'm trying to write some JavaScript that once the page has finished loading will create a div in the place where the is placed.
Here is a stripped-back version of the code...
window.addEventListener('load', function () {
var content = document.createElement('div');
content.id = 'div-ID';
document.getElementsByTagName('body')[0].appendChild(content);
});
It works outside of the addEventListener(), however, when inside the event listener it always puts the created div below the rest of the page content not in the place the <script> tag is placed.
I'm certain the issue is to do with this line...
document.getElementsByTagName('body')[0].appendChild(content);
I need an alternative version to this which doesn't appendChild() but my JS isn't that good and everything I've tried hasn't worked.
Its most likely simple to achieve, I've tried searching Google and Stack Overflow but my search terms don't seem to be producing the desired results.
Any help on this would be much appreciated
You could do it with Node.insertBefore
As such, your code would be something like:
document.body.insertBefore( content, document.body.childNodes[0] );
The second parameter is the referenceNode, that has following comment:
referenceNode is not an optional parameter -- you must explicitly pass a Node or null. Failing to provide it or passing invalid values may behave differently in different browser versions.
I have a project which uses the jquery-ui datepicker. This date picker uses older icon that i want to change without modifiying the code of the jquery-ui-{version}.js in case of future updates.
Also, i can't use another datepicker because there is already a lot of work related to this datepicker and changing all of it would be an absolute waste of time and will possibly break the current application.
Because the datepicker is an element created via javascript, i thought that i could use the event DOMNodeInserted to modify the class of the element i want.
The architecture of my datepicker looks like this :
and here is the code i wrote :
$(document).on('DOMNodeInserted','div.ui-datepicker',function(e){
var element = e.target;
var prev = $(element).find('div.ui-datepicker-header').find('a.ui-datepicker-prev').find('span.ui-icon');
var next = $(element).find('div.ui-datepicker-header').find('a.ui-datepicker-next').find('span.ui-icon');
//The prev and next elements are not the ones i am looking for
$(prev).removeClass();
$(next).removeClass();
$(prev).empty();
$(prev).addClass('fas');
$(prev).addClass('fa-chevron-left');
$(next).empty();
$(next).addClass('fas');
$(next).addClass('fa-chevron-right');
});
As i wrote as a comment in the code, the prev and next objects are not right.
Only the first .find() worked. When i print the element on the console, it prints the element div.ui-datepicker-header as an element for prev and next. I tried separating the retrieval so to locate where the problem is, but even the .find('a.ui-datepicker-prev') doesn't work. There is no error but it still retrieves the parent eventhough i am using it to find its children. I tried using .children('a.ui-datepicker-prev') but nothing has changed.
What triggers me is that, if i take the exact same code and put it anywhere but in the .on('DOMNodeInserted') event, it works. I am a bit stuck here and i couldn't find somebody with the same problem, if you have, please share.
Any ideas are welcome.
var prev = $(element).find('div.ui-datepicker-header').find('a.ui-datepicker-prev').find('span.ui-icon');
var next = $(element).find('div.ui-datepicker-header').find('a.ui-datepicker-next').find('span.ui-icon')
shoud be
var prev = $(element).find('div.ui-datepicker-header a.ui-datepicker-prev span.ui-icon');
var next = $(element).find('div.ui-datepicker-header a.ui-datepicker-next span.ui-icon');
I have a page with a text and some words in the text can change dynamically. These words have an element and should have a tooltip. When the user hovers the word (or I guess on a touch device clicks it), a tooltip should be generated using generateSpecialMarkupElement($(element).text()). Once the HTML has been rendered to the DOM another JavaScript function has to be called replaceMarkupHTML().
I don't have control over these functions unfortunately.
Now I'm wondering if there is a simple way in bootstrap get this done. For instance a before event to run the first function and an after event to call the second one.
Here is a simple example text and simplified versions of the functions:
http://jsfiddle.net/8aqz5auk/1/
So is there a bootstrap-way of hooking/intercepting this kind of thing? Or is there maybe another simple way it could be done?
Edit: I just had an idea. When bootstrap shows a tooltip, it seems to inject an element into the DOM. The interesting part is the container with the class 'tooltip-inner'. So I tried to listen on the body for new elements matching '.tooltip-inner' to be injected and whenever that happens I try to manipulate it:
$('body').on('DOMNodeInserted', '.tooltip-inner', function () {
var el = $(this)
el.html("") // empty the tooltip element
el.append(generateSpecialMarkupElement(el.text())) // insert the generated markup element
replaceMarkupHTML() // replace the markup element with normal html
});
Unfortunately it doesn't work. It just throws a a million errors and the site freezes when I try it.
Edit 2:
Thanks to Chris Barr, I got a little bit closer: http://jsfiddle.net/8aqz5auk/2/
But the tooltip doesn't always show up and the position of the tooltip seems to be kind of wrong (shows up on top of the word, rather then next to/above/below/...).
You might want to look into the tooltip events listed in the docs: https://getbootstrap.com/docs/3.3/javascript/#tooltips-events
$('.elements-with-tooltips').on('show.bs.tooltip', function () {
// do something…
})
You can run a function: before being shown, after being shown, before hiding, after hiding, and when the element is inserted into the DOM.
I am doing a school project that is a Movie lookup app connected to guidebox API. I am using Materialize CSS and trying to organize the information into their tabs system. They are added dynamically so the documentation says to initialize in javascript. It says to use:
$(document).ready(function(){
$('ul.tabs').tabs();
});
However that doesn't work for me I guess since the tabs are not present at Doc Ready thaey are not pushed into the DOM until a submit request. I put just the
$('ul.tabs').tabs();
into a few places in my code and the best result was it working on the first movie returned on each search but for each subsequent return item the tabs break.
I could use some guidance on whether I can plug that in somewhere to make my existing code work.
https://github.com/jasonboru/group_project1_guidebox.git
There are some missing ending tags in your dynamically created dom elements.
Apart this, in this file assets/js/logic.js the following there are the following two lines:
$('.guidebox-search-results').append(movieResult);
$('ul.tabs').tabs();
That menas, whenever you add new tabs element you initialize them.
The mistake I see is: in this way you initialize every tabs not only the new one. And, because you have already initilized the old one I can suggest you to rewrite the previous two lines in this format:
$('.guidebox-search-results').append(movieResult);
$('.guidebox-search-results').find('ul.tabs').tabs();
You can bind on every event, when node inserted in dom and after that, do with it what you want.
$(document).bind('DOMNodeInserted', function(e) {
var element = e.target;
});
jQuery Mobile 1.2.0
I generate the HTML using JavaScript ($(selector).html(content)), add it to the DOM and then display it ($.mobile.changePage()).
Then I invoke an AJAX call, get some data, and re-generate the html (but the parent element, the same $(selector), stays the same, I just change its html(...)).
At this poing the HTML is not "enhanced" by jQM, no styling applied on it.
Now according to the docs I should simply call the page() function on the parent element, i.e $(selector).page().
Other places in the docs suggest triggering the create event, i.e $(selector).trigger("create").
The problem is that non of the above two methods works - the styling of jQM is not applied.
Looking at the code of jQM, I've tried triggering the pagecreate event on that element and it does work, but, this is not documented anywhere, so I'm uncertain of it, especially concerning future releases of jQM.
At some poing in the docs I've read that I can call page() on a page only once..
Anyway, is there any concise/standard way to tell jQM to "enhance" the whole element and its child-elements? Or should I simply stay with triggering the pagecreate event?
Thank you!
To recreate a whole page use this:
$(selector).trigger("pagecreate");
This was my answer to a simmilar question: https://stackoverflow.com/a/14011070/1848600. There's an example of page recreation. Take a look, this should probably solve your problem.
What is the scope of
$(selector).trigger("create");
You should be able to add any elements on the 'pagecreate' event which comes right before 'pageshow' jqm styling is applied to elements. For example I dynamically add a header/footer like this
$(document).on('pagecreate', "[data-role=page]", function() {
var header = "<div data-role='header'>some header stuff</div>";
var footer= "<div data-role='footer'>some footer stuff</div>";
$(this).prepend(header);
$(this).append(footer);
$("[data-role=header]").fixedtoolbar({tapToggle: false});
$("[data-role=footer]").fixedtoolbar({tapToggle: false});
});
Make sure you're using jquery 1.7 or above I think that's when the on method was introduced;
It sounds like you may be generating the DOM and then changing the page, try it the other way around go to the page first then dynamically edit the dom.
EDIT
set the reload page option to true
$.mobile.changePage($(page), {reloadPage: true});
Edit 2
$(selector).children().each(function(){
$(this).trigger('create');
})