Reset/Render again element in polymer - javascript

Their is option in polymer to reset element/ custom element to the original state. Like render the element again?
I want all the inner variables values to delete and that the element will look the same as I load the page.
Thanks

I see to ways:
First one is just to write 'reset' method which resets all vars so that bound ui gets to the initial state.
The second one is to remove the element with Polymer.dom(parent).removeChild and then create new one of same type with document.createElement and put it at old element's place with Polymer.dom(parent).appendChild/insertBefore.
I'd choose first one - seems to be more testable and confined to the lement.

Related

How to get around dynamic elements when web-scraping?

The code below works as I am able to click a button on the webpage using Python/Selenium/Firefox.
button on the webpage
driver.execute_script('''return document.querySelector('dba-app').shadowRoot.getElementById('configRenderer').shadowRoot.querySelector('ing-default-layout-14579').querySelector('dba-overview').shadowRoot.querySelector('ing-feat-agreement-overview').shadowRoot.querySelector('ing-ow-overflow-menu-14587').shadowRoot.querySelector('button')''').click()
However, some elements are dynamic and the numbers are changing anytime you rerun the script.
The changing elements:
'ing-default-layout-14579'
'ing-ow-overflow-menu-14587'
What must I do to get around the dynamic elements?
One option is to look for other attributes that stay the same across pageloads. For example, given your HTML, you could do:
document.querySelector('#configRenderer') // returns the config renderer element
document.querySelector('[data-tag-name="ing-default-layout"]') // returns the ing-default-layout element
document.querySelector('[data-tag-name="dba-overview]') // returns the dba-overview element
And so on. Or you could the same method to identify a parent or a child, and then navigate to the child or parent respectively.
If the HTML isn't stable enough even for that, another approach would be to search through all elements, and find the one(s) whose tagName starts with what you need.
for (const elm of document.querySelectorAll('*')) {
if (elm.tagName.toLowerCase().startsWith('ing-ow-overflow-menu')) {
// do stuff with elm, which is the overflow menu element
}
}

Dynamically create tooltip for an element

I am trying to show a tooltip when user selects random text on the page - think of annotating text.
I was able to dynamically create v-tooltip component. I have selected element in JS, but having trouble wrapping it with v-tooltip component. I was able to wrap it, but the tooltip is positioned to the top of the page, not on the wrapped element itself. I am also not sure my approach is the best one either.
Here is a JSFiddle example: https://jsfiddle.net/6xk7zLv9/
Is there better way to dynamically generate Vue components and insert into the DOM? How can I correctly attach tooltip to the selected element.
You need to specify a side prop (top/bottom/left/right) on the tooltip.
The activator slot is also optional, instead you can use the position-x and position-y props to place it wherever you want without replacing DOM elements: https://codepen.io/kaelwd/pen/LYWLxVe?editors=1010
window.getSelection().getRangeAt(0).getBoundingClientRect() will give you the position of the current selection: https://codepen.io/kaelwd/pen/poewRaE?editors=1010
If you want to get really fancy you can call getClientRects instead and have the tooltip follow the end of the selection: https://codepen.io/kaelwd/pen/vYxZgjb?editors=1010
https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection
https://developer.mozilla.org/en-US/docs/Web/API/Selection/getRangeAt
https://developer.mozilla.org/en-US/docs/Web/API/Range/getClientRects

jQuery plugin instances and remove/destroying them?

I have a situation in which a plugin that I have on the page will be references more than a few times. The issue is that the elements that will call the plugin will be created on the fly. And then removed etc... for instance.
I have a div structure and it creates some child elements.
i. I add the plugin instance on these children. They do some magic etc..
ii. User clicks a button, new set of child elements are created -- I create the plugin instances.
NOW -- what happens to those created in point "i" above? I am not using "widget" so I don't have the destroy method.
So, can I just call the child elements, and just loop thru them and destroy the data element etc.. ala.
$.each('[some_class_that_represents_all_elements]', function(a,b){
$(b).data('PLUGIN_NAME') = null; // or
delete $(b).data('PLUGIN_NAME'); // or
$(b).data('PLUGIN_NAME', null);
})
If the elements are removed from the DOM, do the plugin instances also get removed/cleaned up?
jQuery by default will cleanup any data you store using $(el).data() when you call the $(el).remove() method.
If you use $(el).detach() the data is preserved.
http://api.jquery.com/jQuery.data/
jQuery ensures that the data is removed when DOM elements are removed
via jQuery methods, and when the user leaves the page.

Child's event is not fired when parent's HTML is changed

Here's an example http://jsbin.com/ukoqud/3/edit
If you click on a red box, you'll get an alert.
If you click on a link, everything in a blue box will be replaced with just a red box. Link will disappear and if you click on a red box then, you'll get no alert.
Why this happens?
Is it related to innerHTML?
Does it work the same way in all browsers?
Here's one more example http://jsbin.com/ukoqud/1/edit In this one you'll get an alert after clicking on a link. Things happen in a quite similar way, but result is different.
I would like to understand the reason, there's no need to fix my code.
When you call $(".red"), it returns a collection of DOM elements that exist at that moment. So $(".red").click(function...) just binds a handler to the click event on those elements. If you later create new elements with the same class, they weren't in this collection, so they don't have the handler bound to them. jQuery doesn't watch the DOM for changes and update the handlers dynamically -- the bindings are just on the elements you matched at the time you called click().
You either need to bind the handler again after adding the new HTML, or use delegation with .on():
$(".blue").on("click", ".red", function(){
alert('click on a red box detected');
});
This works by binding a handler to $(".blue"), which doesn't change dynamically. The handler checks whether the element you clicked on matches the ".red" selector, so it's able to handle dynamically-added elements without requiring rebinding.
I think the reason why it works in your second example is because the red block isn't inside the blue box to start. When you move it inside, jQuery reuses the same DOM elements, so the bindings go along with it. In the first example, the red box starts out inside the blue box. When you do $('.red').parent().html(...), the first thing it does is empty $('.red').parent() (the blue box), so the original red element is removed from the DOM, and its bindings are lost.
We need to understand how setting html of an element works. Then you will figure out your answer yourself.
Take a look at this bin Updated Bin
When we set HTML of an element, it first removes all the elements inside it.
Those elements are not removed from memory depending upon whether they are garbage collected or not.
If any of the child is having a reference, then that particular child won't be garbage collected.
In your case, we are having a reference to red element so it is still present in memory but not a part of document.
When we say blue.html(red) in my example, red element becomes a part of document again but this time there won't be any handlers on it So your click does not work.
While in your example2,
red element is always a part of document hence no handlers were lost when red element is moved inside blue element.
I hope this will help.
because when u click the link, you delete everything on screen and create everything from a scratch and event binding goes away. so you should use this
$(".blue").on("click", ".red", function(){
alert('');
});
this way, binding is done differently. it doesnt bind it statically

Recursive jQuery function to amend select option values

I have a form that I am trying to alter with jQuery. Basically, my form has two elements and I need to change the value of the first option in each of them. However, there is an "add more" option that uses AJAX to dynamically generate another element that also needs changed. This add more button can be clicked an unlimited amount of times.
Right now I have this:
$(document).ready(function(){
$("#myname-0-field option:first").val("None");
$("#myname-1-field option:first").val("None");
});
This works fine, but once the "add more" button is clicked, I have more elements called "#myname-2-field", "#myname-3-field", "#myname-4-field" etc. These obviously aren't affected by adding another line into my jQuery as the document has already loaded when they are added.
So the real question is, can someone point me in the right direction of writing a function that can react when the new element is added and change it. If possible, I'm also looking for the function to be aware and look for "#myname-X-field option:first" for tidyness.
use live() function
Then using each function set value
From the jQuery API look live function
Maybe you could add class to your element, so that finding particular element would be easier and it would not add event to other similar elements.
In the example I have a Li with class
$('li.myClass').live('click', function() {
$(this).val(); // this is the getter for clicked value
$(this).val("some_value_here"); // this is the setter for clicked value
});
Now you can add more elements (that has myClass class) and it will have a click event.
Btw. if you know that all elements are inside some container (div for example) then you can write more efficient jQuery using delegate.
$('#container_id').delegate('li.myClass', 'click', function () {
});
This is more efficient because it looks your new elements only under "containter" not from the whole DOM structure.

Categories