JavaScript code doesn't work on dynamically generated html code - javascript

I am trying to run a JavaScript code after Angular template generated, but I find the JavaScript codes don't run on dynamic generated views.
For example, in this code div2 is generated by clicking on div1 and alert("aaa") runs by clicking on div1, but does not run when div2 is clicked.
body of index.html
<div id="div1" ng-init="showDiv2 = false">
<div class="alertonclick" ng-click="showDiv2 =true" style="background-color: red"><br/></div>
</div>
<div id="div2" ng-if="showDiv2">
<div class="alertonclick" style="background-color: green"><br/></div>
</div>
and script in index.html:
<script src="~/index.js"></script>
index.js
$(document).ready(function () {
$(".alertonclick").click(function () {
alert("aaaa");
});
});

The problem is that the association between class alertonclick and it's function is done when the page is loaded. But the div2 isn't created at that point. To fix this, one solution would be to use ng-show instead of ng-if:
<div id="div1" ng-init="showDiv2 = false">
<div class="alertonclick" ng-click="showDiv2 =true" style="background-color: red"><br/></div>
</div>
<div id="div2" ng-show="showDiv2">
<div class="alertonclick" style="background-color: green"><br/></div>
</div>
That way the div2 is generated from the beginning and has the alertonclick function but it's hidden.

The problem is that you put the click listener for the ".alertonclick" class, after the page was rendered. At that time the second div is not present in the DOM. A possible solution would be to reset the click listener after the second div is displayed.

Related

Preload HTML from within Javascript file, into the DOM, but don't execute

Im creating a simple JS game, which will run in the browser and will pull the files directly from the pc. Because of this needed to make a workaround the "Cross-origin" error, which went smoothly, I put all the HTML within a JS and loaded the JS from the tag in the index.html. Everything was going smoothly so far.
You click "press any key to continue" -> but then next you click "New Game" and you get event listener error "can't set property of null". Which i don't understand how it happens, because the element is already in the "DOM" , the css could pick it up, but the event listener could not? So i tried moving all scripts on top, rearranging stuff, nothing worked. Pre-loading all HTML into the index.html, without executing it will definitely work, but how can i achieve this exactly? My Configuration atm is:
index.html (root folder)
/components/main_menu.js
/components/character_creation.js
function MainMenu()
{/*
<div id="mm_wrapper_grid">
<div id="mm_subgrid1">
</div>
<div id="mm_subgrid2">
<div id="mm_subgrid2_image"></div>
<div id="mm_new_game"><p id="mm_new_game_p" class="grow">New Game<p></div>
<div id="mm_load_game"><p id="mm_load_game_p" class="grow">Load Game</p></div>
<div id="mm_options"><p id="mm_options_p" class="grow">Options</p></div>
<div id="mm_credits"><p id="mm_credits_p" class="grow">Credits</p></div>
</div>
</div>
*/}
function CharacterCreation()
{/*
<div> Character Creation test
</div>
*/}
<div id ="game">
<div id="loading_screen">Press Any Key To Continue</div>
</div>
<script type="text/javascript">
document.getElementById("loading_screen").addEventListener("click", function() {callback("game", MainMenu)});
document.getElementById("mm_new_game_p").addEventListener("click", function() {callback("game", CharacterCreation)});
function callback(arg1, func)
{
var html = func.toString();
var htmlstart = html.indexOf('/*');
var htmlend = html.lastIndexOf('*/');
var html = html.substr(htmlstart+2, htmlend-htmlstart-2);
document.getElementById(arg1).innerHTML = html;
}
</script>
You have the problem because you are trying to add the second listener for getElementById("mm_new_game_p") when this element doesn't exist on the page. I suggest you to add the follwing line of code to make sure, that it's true:
<script type="text/javascript">
document.getElementById("loading_screen").addEventListener("click", function() {callback("game", MainMenu)});
console.log('#mm_new_game_p', document.getElementById("mm_new_game_p"));
document.getElementById("mm_new_game_p").addEventListener("click", function() {callback("game", CharacterCreation)});
...
You have to add this listener after this element will be created (after calling of MainMenu() function).
To tell the truth, I can see such storing of html templates in js functions for the first time. It's hard to support your code and I've modified it a little bit below. This is not the best way to implement it, but my goal is show you a solution based on your code. What you can see here:
all the templates for pages are in html (not in JS);
you can add listeners from html code using HTML attribute onclick - and in this case you can be sure, that element exists on the page.
If you want to add listeners from JS, than you have to create own functions for each pages which you have and after HTML template of a page will be added to #game container you will need to create event listeners for the buttons which are on the created page.
openPage("game", "loading_screen");
function openPage(parentDOMElementId, name) {
console.log('openPage:', name);
var pageHtml = document.getElementById("page_" + name).outerHTML;
document.getElementById(parentDOMElementId).innerHTML = pageHtml;
}
<div id="game"></div>
<div class="templates" style="visibility: hidden;">
<div id="page_loading_screen" onclick="openPage('game', 'main_menu')">
Press Any Key To Continue
</div>
<div id="page_main_menu">
<div id="mm_subgrid1">
</div>
<div id="mm_subgrid2">
<div id="mm_subgrid2_image"></div>
<div id="mm_new_game">
<p id="mm_new_game_p" class="grow" onclick="openPage('game', 'character_creation')">New Game
<p>
</div>
<div id="mm_load_game">
<p id="mm_load_game_p" class="grow">Load Game</p>
</div>
<div id="mm_options">
<p id="mm_options_p" class="grow">Options</p>
</div>
<div id="mm_credits">
<p id="mm_credits_p" class="grow">Credits</p>
</div>
</div>
</div>
<div id="page_character_creation">
Character Creation test
</div>
</div>

Angular js ng-click doesn't work in child element

I'm trying to toggle a variable on click of an element in the DOM and I'm getting some strange behaviour.
Full Example Here
Essentially if I put the ng-click on the .options div and leave the controller on the .options-tab div, the event triggers (but applies to everything inside the .options div). And for some reason I am forced to apply the ng-controller again.
<div ng-app ng-controller="Swipe" class="container">
<div class="options" ng-click="swiped=!swiped2">
<div ng-controller="Swipe" class="options-tab" ></div>
</div>
</div>
If I put it on the element that I want it on, it doesn't trigger the event.
<div ng-app ng-controller="Swipe" class="container">
<div class="options">
<div ng-controller="Swipe" class="options-tab" ng-click="swiped=!swiped2"></div>
</div>
</div>
You had a few issues:
Multiple controller declarations creating duplicate scopes
ng-click="swiped1=!swiped1" on both the options and options-tab elements (it was being set and then reversed immediately)
Your 2nd example was set to ng-click="swiped=!swiped2" instead of ng-click="swiped2=!swiped2"
Updated working fiddle: http://jsfiddle.net/Xya3f/2/

Javascript on Multiple DIVs

I am using a Wordpress Theme (Incipiens) that has a show/hide Javascript to show a map on the contact page http://demo.themedev.me/wordpress_themes/incipiens/contact-us/
I want to use this function on a page multiple times to show/hide galleries.
<div class="map">
<div class="map_top">
<hr class="toolbox toolbox1">
</div>
<hr class="vertical_sep0">
<a class="show_map" href="javascript:void(0)"></a>
<div class="map_container"><div class="thismap"><iframe>........</iframe></div>
</div>
I have this working but the call to the js opens all divs. I therefore put a unique div id round each gallery and slightly changed the javscript...
<div class="map">
<div class="map_top">
<hr class="toolbox toolbox1">
</div>
<hr class="vertical_sep0">
<div id="silestone">
<div class="map_container">
[show_gallery width="124" height="124" galleryid="527"][/show_gallery]
</div>
</div>
</div>
It works but very oddly, sometimes the right one opens, sometimes the wrong one...not sure what i'm doing wrong, should I just have one javascript call that contains the ID's to all divs? If so how do I do this?
Since you have not shown the actual script you use for toggling, I assume you mean something like this (taken from the page) -
function (){
$(this).toggleClass('hide_map');
$('.map_container').slideToggle(400);
}
I would change that to -
function unhide(id){
$(this).toggleClass('hide_map');
$('#' + id).find('.map_container').slideToggle(400);
}
Does that work?

onchange event for <div> element when I have no control over when it is changed

I have a div element on a page that has other divs added to it when certain events happen. I do not know when these events happen, how they are triggered and how the other divs are added to the main div (its external so I have no idea whats happening all I have access to is the div).
How would I "monitor" for changes to the main div so an event is triggered whenever a new div is added ? I know I can use setInterval (which is what I'm doing now), but I really do not want to use it unless absoluley necessary. I would love to something as simple as form elements do with onchange but I have not found such for divs.
Example if text is not clear:
wesite.com/index.html ( the only thing I have access to)
<html>
<head></head>
<body>
<div id="theDiv">
</div>
</body>
</html>
and at times unknown to me divs get added to that div and it eventually looks like :
<html>
<head></head>
<body>
<div id="theDiv">
<div class="added"><p>Added Div</p></div>
<div class="added"><p>Added Div</p></div>
<div class="added"><p>Added Div</p></div>
<div class="added"><p>Added Div</p></div>
<div class="added"><p>Added Div</p></div>
</div>
</body>
</html>
And lets say I set up the event to trigger an alert, in this example I want to see an alert box every time a new div is added so by the time it looks like this I should have seen 5 alert boxes.
Sorry if this is difficult to follow..
The easiest way is to intercept the calls that are adding the children to the DIVs. Is this not an option?

Show a div pertaining to a certain id?

So when I run the following code, I click on a div, and another div slides out.
<div class="section" id="1">Hi</div>
<div class="under" id="1">Hola</div>
<div class="section" id="2">Foo bar</div>
<div class="under" id="2">Derp</div>
</td></table>
</td></table>
<script>
$(".section").click(function(){
var id = this.id;
$(".under").slideToggle("slow");
});
But, when I click on the div with the class "section", it shows ALL of the divs with the class "under." What I want to do is show the div "under" with an id that is equal to the id of the div selected (i.e. show "under" with id="1" when "section" with id="1" is clicked). How would I do this?
use
.next('div');
so whole code would be
<style>
.under{
display:none;
padding:5px;
background-color:gray;
}
</style>
<div class="section" id="1">Hi</div>
<div class="under" id="1">Hola</div>
<div class="section" id="2">Foo bar</div>
<div class="under" id="2">Derp</div>
<script>
$(".section").click(function(){
$(this).next('div').slideToggle("slow");
});
</script>
working demo
You can use .next, or depending on how you have things setup, .nextAll. Here is a short demo i did for a question similar to this:
http://jsfiddle.net/andresilich/AeGSQ/
Ok there are a few things wrong with your HTML; I will go through them one by one.
There is no opening <table> or <td> tag. This will result in invalid HTML.
There should be a <tr> tag containing the td tag. It is structurally incorrect as it is at the moment.
I am thinking you're using tables for layout; tables should be used for data-display only, not for page layout.
You have multiple ids the same. The idea of an id is that it identifies one element and one element only. Classes are used to style multiple elements the same.
I have rewritten your code at http://jsfiddle.net/FS3rt/. It also contracts any visible sections so that the user is presented only with the information they would like to see.

Categories

Resources