Remove unique ID from the DOM - javascript

I am working on a site that has a pretty funky modal box implemented and right now it is out of scope to implement something new so I am doing my best trying to work with what currently exists. The way it works is every time a new modal window is created it is assigned a unique ID.. for example
<div id="window_1308937649703" class="dialog">
To close the window the close button has an onclick like :
onclick='Windows.close("window_1308937649703", event)'
I am trying to destroy the window from another click event but I am unsure on what the best way to accomplish this would be. I am thinking I could use the dialog class to pull the associated unique #window_ id. Is there also some javascript I could use to getElementsByClassName('dialog') and remove it completely from the DOM ? I do have the Prototype library to work with as well if that is any help. I cant make much sense of the actual modal scripts so I am hoping for some kind of work-around solution.

To totaly remove the dialog from the dom use:
function removeNodeByID ( nodeId){
var node = document.getElementById( nodeId );
node.parentElement.removeChild(node);
};
with
onclick="removeNodeById('window_1308937649703')"
this way you just need the ID of the dialog which you mentioned you could retreive in the question.

There's not much you can do re: getElementsByClassName() in raw JavaScript (except rolling your own), although Prototype has some good functionality for this.
Another possible approach: does the close button have a generic ID? If so, and if you're able to add plugins (sorry, I've never used Prototype), you could look at this thread to get an idea how to trigger the click event on that close button once you've selected it.

As you have prototype you could simply use:
$$('.dialog').first().remove();
Also, if you are using prototype, you should probably avoid onClick, and use an event observer instead:
<button id="dialogremover">Remove</button>
<script type="text/javascript">
$('dialogremover').observe('click', function(ev) {
ev.stop();
$$('.dialog').first().remove();
});
</script>
This has two benefits:
It's much easier on the eyes!
It's possible to put the JS in an external script an clean up your HTML.

Related

Duplicating IDs Jquery

So, I have done some research, and it's pretty clear that id should be unique in the DOM. This is my issue, and I am curious what the best solution to it is:
I am using jQueryUI tabs as well as a custom menu and ajax to load specific pages into a content pane without re-rendering the browser. From some of these sub pages, a user can open a popup (done with a jQueryUI dialog) to edit customer information. Because these load a server side page, in each place that this form would be generated, it uses the same ids.
I have found that there are a number of ways to close a dialog without removing it from the DOM. This causes confusion later when it, or another form is opened elsewhere, and now there are conflicting ids present in the DOM. I am working on tracking down all the ways to close a dialog, and making sure to replace them with .dailog("destroy").remove() to make sure that they are erased from the DOM, but I want to be sure the solution here is fool proof in the event that someone one gets left on the page.
My two immediate thoughts:
1.) Generate a random string to append to each form element's id when the form is rendered, fully preserving uniqueness of the id.
2.) Use more specified selectors when getting the form data, i.e. scoping it to the popup that was created, the page that it was created from, and then the tab that it is under, and not worrying as much about id uniqueness.
The first feels ugly, and in theory you COULD randomly duplicate the string and still run into an issue. The later just feels bulky and ugly to me. Is there an option I am missing? What is best practice when it comes to dealing with IDs that can be duplicated in this way?
Thanks,
Eric
You may use classes if you need "similar" objects. Id's purpose is to identify object uniquely.
By the way, classes are widely used, for example, in Bootstrap.
UPDATE: I think your "second" approach is bad, as you eventually can change the layout, but, in this way, you should track every change, and remember WHERE to change your selectors (possibly, it will be multiple places).
Before inserting the new element into the list, you could check if there is already an element existing on the page with that id. If it does exist than delete it.
Like:
if($("#"+your_id).length!==0)
$("#"+your_id).remove();
//insert the new element
But if you need that element as well, i would suggest that you use classes to group elements used for same purposes.
Here is what you can do to distinguish between the different dialogs when you try to close them:
1) Change each dialog id into a class, so that your dialogs can share the same class. Using the same id is not recommended.
2) You can create a click listener for the button that closes the correct dialog by using the event callback parameter. See the working snippet below.
var closeButtons, i, closeButtonsLen;
closeButtons = document.getElementsByClassName('close');
for (i = 0, closeButtonsLen = closeButtons.length; i < closeButtonsLen; i += 1) {
closeButtons[i].addEventListener('click', function (e) {
e.target.parentNode.setAttribute('hidden', true); // if you want to hide the dialog
});
}
<div class="dialog"><button class="close">first x</button></div>
<div class="dialog"><button class="close">second x</button></div>
<div class="dialog"><button class="close">third x</button></div>
You can replace e.target.parentNode.setAttribute('hidden', true); with whatever you need to do. e.target.parentNode gets the dialog element.

Jquery remove function follow up

I submitted this question last week:
chrome not working with jquery remove
and was able to resolve it (stupidity on my part really), however my example was very simple. Currently I'm trying to use .remove to eliminate a complete div from a page before sending an array of inputs to an ajax function. However, I am not able to get .remove to work at all.
Here's my latest try:
http://jsfiddle.net/CJ2r9/2/
I get function not defined on the jsfiddle on multiple browsers. On my application I get absolutely no errors, but nothing works either.
I'm relatively new to javascript scopes, so if the problem is scope-wise then please let me know how I'm screwing up.
I have also tried using the .on jquery function, but it's a bit more confusing considering my div ids are dynamically loaded from the server (jstl, spring MVC, etc). If that's a solution please let me know how I can get on the right track.
Thank you!
The two problems in your jsFiddle are:
Scope: removeElem is not in global scope, since you left the default configuration option to execute the code on DOM ready. You can change it to "no wrap" to make the funciton global.
The elements you want to remove don't exist. The div elements have IDs like "removeXXXp" and in your event handlers you pass "removeXXXs".
Here is an other, simpler solution (in my opinion) for element removal. Given your markup:
<div class="scheduleSet" id="remove315p">
<!-- ... -->
Remove
</div>
You can use .on like so:
$('.schduleSet a.optionHide').on('click', function() {
// traverses up the DOM tree and finds the enclosing .schduleSet element
$(this).closest('.scheduleSet').remove();
});
You don't even need IDs at all.
I made a simple fiddle, the inline onclick doesn't see the function defined in javascript so I get a ReferenceError: myRemove is not defined.
By adding the listener in js, .remove() works fine.
Sorry I don't know what causes the difference in behavior though.
Test it out: http://jsfiddle.net/xTv5M/1/
// HTML5
<div id="removeme">foo bar</div>
<button onclick="myRemove('removeme')">Go</button><br>
<div id="removeMe2">foo bar</div>
<button id="go2">Go Again</button>
// js
function myRemove(name){
$('#'+name).remove()
};
$('#go2').click(function(){ myRemove('removeMe2') });
I see that you are already using jquery. Why dont you do it this way:
<div id="foo">This needs to be removed</div>
Remove
function removeElem(element){
$('#'+element).remove();
}
$(function(){
$("#remove").click(function(){
removeElem($(this).data('remove'));
});
})
Fiddle here: http://jsfiddle.net/vLgpk/
They way this works is, using data-remove (can be anything like data-xyz btw), binds the remove link with the div. You can then read this binding later when remove is clicked.
If you are new to jQuery, and wondering what data-remove is, its just custom attribute that you can add to you code which can be later retrieved using the data() call on the element. Many great frameworks like Bootstrap use this approach.
Advantage of using this approach in my opinion is you can have the remove links anywhere in your UI and they don't need to be related structurally to your divs by siting inside them.

Javascript call function when html inject finished onclick

I've got this situation:
There is a calendar script to pick a date. When the date is picked a function called onclick to make a select box available for time pick. Now its not like its display:none-->display:block, the select being generated by JS. My goal is to customize this select. For that I got a jquery script "custom.select" which just turns the select to spans. The problem is that if I add the call for this script to the onclick right after the calendar call it does not take. I am pretty sure its because at that stage the html for the select is not injected yet. If I call the custom.select function from the firebug console after the select is visible - it works just fine.
So the question is: how do I call it so it will do its magic on select box?
Thanks
Use delegation with .on():
$(function(){
$(document).on('click','.classdynamic',function(){
//do stuff here
});
});
You should delegate event to the closest static container of your target element. This means changing $(document).on('click','.classdynamic',function(){...});
by something like: $('#staticContainer').on('click','.classdynamic',function(){...});
Figuring out when elements are added is not an easy task. I answered a similar question here.
The best way would be to have some control on the script that creates the select, and append your code to it. One way to achieve this is with Aspect Oriented Programming (AOP) - not easy either.
With current browsers, the most straightforward way is to use setTimeout in a loop and poll the page until the element exists.
Ok I got this thanks to Christophe! I used the Selector Listeners script from here: http://www.backalleycoder.com/2012/08/06/css-selector-listeners/
It was even more complicated coz the parent was not present either )). So what I did was that I attached the listener to the onclick just after the calendar call lol. I needed to make another function though to make it work with the script, here is the code:
var doSelect = function(){
jQuery('#timeslots').customSelect();
};
jQuery(document).ready(function(){
jQuery('.td_calendar').on('click','#anchor1',function(){
cal.select(document.forms['frmRequest'].startdate,'anchor1','yyyy-MM-dd');
document.getElementById('slots').addSelectorListener('#timeslots', doSelect);
});
});

Show context-menus only when certain elements are clicked

I am kinda stuck with something and I need your help.
I am trying to show context-menus only when a user right-clicks on a certain elements in the page.
I thought I solve this problem by using getElementByClassName(...) and adding an onClick listener to each one of the elements, and when the user clicks on any of them I will then create the context-menus. And then remove the content menu later when everything is done.
Problem is that I don't have the full class names of those elements, all I know that they start with "story".
I am not sure how to go about doing this. Is there a way to use regex and getting all elements with a class name of story? Or is that not possible.
Thanks in advance,
There's this library that allows for regex selectors.
<div class="story-blabla"></div>
$("div:regex(class, story.*)")
However, you may not want to implement a full library. There's another solution:
$('div').filter(function() {
return this.class.match(/story.*/);
})
This will return the objects you want.
You can do this using attribute starts with selector
document.querySelectorAll("[class^=story]")

browsing through nodes

this is what an html structure of the webpage looks like:
<body>
<form>
<input type='file'/>
</form>
<div id='list'>
<div>value here<input id='delete' type='button'/></div>
</div>
</body>
i have found javascript code that triggers on 'delete' button click and removes input 'file' element. it uses this piece of code where element is input 'file' mentioned above:
deleteButton.onclick=function(){this.parentNode.element.parentNode.removeChild(
this.parentNode.element );}
i am trying to understand logic(rules) behind 'this.parentNode.element' ? why not accessing element directly 'element.parentNode.remove...'
many thanks
i am trying to understand logic(rules) behind 'this.parentNode.element' ?
There's no element property on the Node, Element, HTMLElement, or HTMLDivElement interfaces. So my guess would be that elsewhere in that code, you'll find something that's explicitly adding that property to the element instance of the div containing the button. You can do that, add arbitrary properties to element instances. These are frequently called "expando" properties and should be done very, very, very carefully.
Not the answer to the question, just opinion. It's better avoid constructions like
this.parentNode.element.parentNode
Because in case when you change your DOM structure, you will need rewrite you JS. So I think it's better to give id attributes to tags, and use next construction to get DOM element:
document.getElementById('element_id')
or if you will use some js framework (like jQuery) you can use even easier construction to get DOM element
$("#ement_id")
Ok, "removeChild" is a strange method, and quite probably, ill-conceived. It should look like:
<div>value here<input id='deleteMe' type='button'/></div>
var node = document.getElementById('deleteMe');
node.remove(); // <--- does not exist, but sure would be nice!!!
No, instead we have to do these shenanigans:
var node = document.getElementById('deleteMe');
node.parentNode.removeChild(node); // verbose! Convoluted!
We have to get the node's parent, call the method, then refer to the node again. This doesn't look like any other DOM methods as far as I recall. The good news is you can make it happen all in one line, chained, like a jQuery method.
You are best served to start over or copy somebody else's code. The use of "this" means it was within an object (or class), referring to other methods or properties within that object. You should stick to non-object variables and functions for now.
Hope that helps.

Categories