I am creating DOM elements programatically using unique IDs provided by a server. I need to fetch the attribute named posterId when clicking over one of them.
I am attempting to pass the event currently to no avail.
I have tried using:
onClick="handlePosterClick(event)
onClick="handlePosterClick(this)
onClick=handlePosterClick(this.posterId)
This function generates all of the Divs and elements that compose the entire block:
function createMovieDivForCarrousel(){
var carrousel = '';
for(var j = 0; j < movieGenres.length; j++){
//creates a slider, section title and defines mouseovers
carrousel += '<div class="slider"><h3>'+movieGenres[j]+'</h3><span onmouseover="scrollL()" onmouseout="clearScroll()" class="handle handlePrev active"><i class="fa fa-caret-left" aria-hidden="true"></i></span><div id="scroller" class="row"><div class="row__inner">';
for(var i = 0; i < recommendedMovies.length; i++){
if(recommendedMovies[i].genre[0].toLowerCase() == movieGenres[j].toLowerCase()){
carrousel +='<div class="gui-card"><div class="gui-card__media"><img class="gui-card__img" src="'+recommendedMovies[i].poster+'"/></div><div class="gui-card__details" "posterId="'+recommendedMovies[i].id+'" onClick="handlePosterClick(event)"><div class="gui-card__title">'+recommendedMovies[i].title+'</div></div></div>';
}
}
carrousel += '</div></div><span onmouseover="scrollR()" onmouseout="clearScroll()" class="handle handleNext active"><i class="fa fa-caret-right" aria-hidden="true"></i></span></div>';
}
return carrousel;
}
This function handles what it is supposed to do with it, I have suppressed the unnecessary parts but just attempting to log the value does not work either:
function handlePosterClick(e) {
var indexOfClicked = search(e.target.getAttribute("posterId"));
posterArray[indexOfClicked].state = !posterArray[indexOfClicked].state;
}
window.onclick = e => {}
The element that holds both the ID and the function call is:
<div class="gui-card__details" "posterId="'+recommendedMovies[i].id+'" onClick="handlePosterClick(event)">
For reference, the IDs go from 1 to 118 and they are all unique.
Edit: doing onClick="console.log(this)" and clicking over one of the elements print the following:
<div class="gui-card__details" "posterid="11" onclick="console.log(this)"><div class="gui-card__title">Manchester by the Sea (2016)</div></div>
Removing the extra double-quotes and making it posterId rather than "posterId" also yields Uncaught TypeError: Cannot read property 'state' of undefined. I was unsure how to represent and that was the last state of the snippet.
2 problems:
1. The extra double quotes are causing a problem. It is hiding a different problem. First, remove those extra double quotes before posterId.
2. Either search isn't finding the index or the index is pointing to a null/undefined in the array. You need to debug those two parts of the code.
you can try use
document.getElementsByName("posterId");
inside the handlePosterClick()
I am trying to create an extension for VSTS using their extension kit (https://learn.microsoft.com/en-us/vsts/extend/overview?view=vsts).
<script type="text/javascript">
VSS.init();
var items = {}
// Get data service and display
VSS.getService(VSS.ServiceIds.ExtensionData).then((dataService) => {
dataService.getDocuments('MyCollection2').then((docs) => {
// keep a reference to the element instead of searching for it in each loop.
const itemsDiv = document.getElementById('items');
const contents = [];
for (let i = 0; i < docs.length; i++) {
// using template strings here to show you another way of working with strings in es6
var name = docs[i].name
contents.push(
`<div
class="listItem"
onClick="console.log(docs[i])"
onmouseover="this.style.background='#D5DBDB';"
onmouseout="this.style.background='white';">
${docs[i].name}
</div>`
)
}
// finally update the target element one time with your contents.
// The new line character isn't required, can just use '',
// but this might be easier to read for you
itemsDiv.innerHTML = contents.join('');
});
});
</script>
So what my javascript part does is I try to fetch objects from VSTS`s internal data storage (I named it MyCollection2) and display the objects as a list
HTML part
<section>
<nav>
<div class="create_button">+ Create KPI</div>
<div id="items"></div>
</nav>
<article>
<h2>Create KPI</h2>
<br>
<form action="" id="form" onsubmit="sConsole(event)">
KPI Name<br>
<input type="data" id="name">
<br><br>
Actual Value<br>
<input type="data" id="actual">
<br><br>
Potential Value<br>
<input type="data" id="potential">
<br><br>
Goal %<br>
<input type="data" id="goal">
<br><br>
<button type="submit">Create</button><span>Cancel</span>
</form>
</article>
</section>
So all the objects are rendered in the div with the id items.
Everything is fine up to this point.
The problem is the onClick="console.log(docs[i]) part in my javascript part.
My intention was to console.log the document object whenever each item in the list was clicked.
However, this doesn't print the object as I intended.
It just prints externalContentHost10 and I don't know what that is.
What can I do to make this work?
docs is defined in your function; the scope of the onclick attribute (note: should be all lowercase) is not the same. In general, you should avoid inline event handlers as they’re not very flexible or maintainable. You should instead use addEventListener, which means ditching innerHTML and working with proper element nodes. A few other changes I would make are:
Flattening the promises (removing the nesting) by returning them
Using for...of for iteration
Using const (and let, but in this case const is enough) instead of var so that your variables have the right scope
This gives us:
VSS.init();
const items = {};
// Get data service and display
VSS.getService(VSS.ServiceIds.ExtensionData)
// the callback on the next line returns a promise, which the JavaScript engine will follow, so you don't need to nest the next `then`
.then((dataService) => dataService.getDocuments('MyCollection2'))
.then((docs) => {
// keep a reference to the element instead of searching for it in each loop.
const container = document.getElementById('items');
// this loop will remove any existing children
while (container.firstChild !== null) {
container.removeChild(container.firstChild);
}
// `for...of` is a simpler way to iterate over a collection
for (const doc of docs) {
// create a `div` element
const div = document.createElement("div");
// add a text node to it
div.appendChild(document.createTextNode(doc.name));
// add event listeners to change its background
div.addEventListener("mouseover", e => { div.style.background = "#D5DBDB"; });
div.addEventListener("mouseout", e => { div.style.background = "white"; });
// add a `click` listener
div.addEventListener("click", e => { console.log(doc); });
// add the new div to the container
container.appendChild(div);
}
});
If you wanted to use classes instead to manage the styling—which is the recommended method—then you could implement the event listeners using classList:
div.addEventListener("mouseover", e => div.classList.add("hover-class"));
div.addEventListener("mouseout", e => div.classList.remove("hover-class"));
(classList has toggle and replace methods, but they aren’t supported by IE at all, and Edge only seems to support toggle, so whether to use them depends on your minimum supported version.)
But you would probably be better off defining a CSS :hover class rather than doing all this, if styling is all you want to change.
var = cooldynamicelement
How could I store the inner html I grab with jQuery from my div ie. <div class="username"> </div> to store as an accessible variable in jQuery eg. cooldynamicelement so I can grab and use at different areas of my site by just calling ie. $cooldynamicelement and updates with the dynamic .username element value.
1. Store HTML into localStorage
var dynamicElementHTML = localstorage.dynamicElementHTML || $(".username").html() || "";
localstorage["dynamicElementHTML"] = dynamicElementHTML;
To make it available to other pages a way would be to use the power of localstorage
https://developer.mozilla.org/en/docs/Web/API/Window/localStorage
If you're actually interested in the whole element (not only it's inner HTML) than instead of .html() use .prop("outerHTML")
2. Binding using jQuery (essential idea)
If you only want a way to reflect some variable HTML as actual html and make it alive you could do like:
var $myElement = $("<div />", {
class : "userData",
append : $someDynamicElements,
appendTo : $someParentElement,
on : {
contentUpdate : function() {
$(this).html( $someDynamicElements );
}
}
});
than whenever your $someDynamicElements changes you can trigger a contentUpdate
$myElement.trigger("contentUpdate")
3. Binding using jQuery (concept)
Here's the same elements binding concept gone wild:
// Here we will store our elements
var EL = {};
// Create desired HTML elements like this:
var LIST = {
username: $("<b/>", {
html : "UNKNOWN",
click : function() {
alert( $(this).text() );
}
}),
email: $("<a/>", {
html : "test#test.test",
href : "mailto:"+ "test#test.test"
}),
// add more here, you got the idea.
// don't forget that you can assign any JS / jQuery propery to your element.
// You can go insane using .on() and later .trigger()
};
// Our small "program" that replaces data-bind elements
// with dynamic elements from our list
$("[data-bind]").replaceWith(function(i){
var bind = this.dataset.bind;
if(!LIST[bind]) return;
if(!EL.hasOwnProperty(bind)) EL[bind] = [];
var klon = LIST[bind].clone(true)[0];
EL[bind].push(klon);
return klon;
});
// That's it. Now goes your code ///////////////
$(EL.username).css({color:"red"}); // just to test if it works :D
$("[data-target]").on("input", function(){
var target = this.dataset.target;
$(EL[target]).html( this.value );
});
// P.S: Even having thousands of elements inside EL
// say you have "EL.tableRows" you can do fabulously
// quick stuff like i.e: sorting, cause you iterate over a plain JS array.
// After the sorting of EL.tableRows is done and you need a jQuery
// representation simply use $(EL.tableRows).
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Dynamic element Binding in jQuery</h2>
Enter some text and see the update trigger in different places<br>
<input data-target="username"><br>
Welcome <span data-bind="username"></span> !!<br>
You name is <span data-bind="username"></span> Click the red text!<br>
<span data-bind="email"></span>
Well if you want to have the jqueryObject in a variable, just do this:
$(function(){
window.$cooldynamicelement = $("div.username");
})
that way you're able to use $cooldynamicelement in a global context. If is that what you want. This way you're saving a reference to your .username element and thus every time you use it will be updated.
NOTE: If you decide to do this, be careful with polluting your global context.:
Codepen: http://codepen.io/leongaban/pen/YyWmOo?editors=101
In my app, I have a simple array of div id names media = ["twitter", "news", "blogs"]
I then have a simple for loop which attempts to grab the #ids from the markup and add them into my vm.parameters object.
Currently the div's are showing as null:
Code in my Controller:
var vm = this;
vm.parameters = {};
var media = ['twitter', 'news', 'blogs'];
console.log(vm);
console.log(media);
initParameters();
function initParameters() {
console.log('initParameters called...');
for (var i=0; i<media.length; i++) {
vm.parameters[media[i]] = {};
vm.parameters[media[i]].start = 0;
vm.parameters[media[i]].limit = 10;
vm.parameters[media[i]].total = 0;
vm.parameters[media[i]].div = document.getElementById(media[i]);
console.log('getElementById =',document.getElementById(media[i]));
}
console.log('media = ',media);
console.log('vm.parameters = ',vm.parameters);
}
Markup (Using the Ionic framework):
<ion-slide id="twitter">
<h3>Twitter stream</h3>
<p>Here is content for Twitter</p>
</ion-slide>
<ion-slide id="news">
<h3>News stream</h3>
<p>Here is content for News</p>
</ion-slide>
<ion-slide id="blogs">
<h3>Blogs</h3>
<p>Here is content for blogs</p>
</ion-slide>
You will need to do an onload event before trying to get the id's. This is because the controllers run before the DOM loads:
window.onload = function(){
initParameters();
}
DOM code doesn't belong in controllers. The controller will run before the route template is even loaded so you are looking for elements that don't exist yet.
Generally there shouldn't be any need to look for elementById . Normally you would let your data model drive creation of the view
If you must do dom manipulation like this you need to do it in a directive to be assured the element(s) exist when your code runs
You can also use
$rootScope.$on('$viewContentLoaded', function(){
// your code
});
in your angular.run(), will execute once content loaded.
I just created script that shows/hides (toggles) block of HTML. There are four buttons that each can toggle its HTML block. When any HTML block is opened, but user has been clicked on other button than that HTML block's associated button... it hides that HTML block and shows new one.
Here is what I have at the moment:
$('.btn_add_event').click( function() {
$('.block_link, .block_photos, .block_videos').hide();
$('.block_event').toggle();
});
$('.btn_add_link').click( function() {
$('.block_event, .block_photos, .block_videos').hide();
$('.block_link').toggle();
});
$('.btn_add_photos').click( function() {
$('.block_event, .block_link, .block_videos').hide();
$('.block_photos').toggle();
});
$('.btn_add_videos').click( function() {
$('.block_event, .block_link, .block_photos').hide();
$('.block_videos').toggle();
});
Any ideas how to reduce code size? Also, this script isn't very flexible. Imagine to add two new buttons and blocks.
like Sam said, I would use a class that all the blocks share, so you never have to alter that code. Secondly, you can try 'traversing' to the closest block, therefore avoiding it's name. That approach is better than hard coding each specific block, but if the html dom tree changes you will need to refactor. Last, but best, you can pass in the class name desired block as a variable to the function. Below is something you can copy paste that is close to what you started with.
$('.myAddButtonClass').click( function() {
$('.mySharedBlockClass').filter(':visible').hide();
//find a good way to 'traverse' to your desired block, or name it specifically for now.
//$(this).closest(".mySharedBlockClass").show() complete guess
$('.specificBlockClass').show();
});
I kept reading this "When any HTML block is opened, but user has been clicked on other button than that HTML block's associated button" thinking that my eyes were failing me when Its just bad English.
If you want to make it more dynamic, what you can do is add a common class keyword. Then
when the click event is raise. You can have it loop though all the classes that have the
keyword and have it hide them all (except the current one that was clicked) and then show the current one by using the 'this' keyword.
you can refer below link,
http://chandreshmaheshwari.wordpress.com/2011/05/24/show-hide-div-content-using-jquery/
call function showSlidingDiv() onclick event and pass your button class dynamically.
This may be useful.
Thanks.
try this
$('input[type=button]').click( function() {
$('div[class^=block]').hide(); // I resumed html block is div
$(this).toggle();
});
Unfortunatly I couldn't test it, but if I can remember right following should work:
function toogleFunc(clickObject, toogleTarget, hideTarget)
{
$(clickObject).click(function()
{
$(hideTarget).hide();
$(toogleTarget).toggle();
});
}
And the call:
toogleFunc(
".btn_add_videos",
".block_videos",
".block_event, .block_link, .block_photos"
);
and so far
Assuming the buttons will only have one class each, something like this ought to work.
var classNames = [ 'btn_add_event', 'block_link', 'block_photos', 'block_videos' ];
var all = '.' + classNames.join(', .'); // generate a jquery format string for selection
$(all).click( function() {
var j = classNames.length;
while(j--){
if( this.className === classNames[j] ){
var others = classNames.splice(j, 1); // should leave all classes but the one on this button
$('.' + others.join(', .')).hide();
$('.' + classNames[j]).toggle();
}
}
}
All the buttons have the same handler. When the handler fires, it checks the sender for one of the classes in the list. If a class is found, it generates a jquery selection string from the remaining classes and hides them, and toggles the one found. You may have to do some checking to make sure the strings are generating correctly.
It depends by how your HTML is structured.
Supposing you've something like this
<div class="area">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
...
<div class="sender">
<a class="one"></a>
<a class="two"></a>
<a class="three"></a>
</div>
You have a class shared by the sender and the target.
Your js would be like this:
$('.sender > a').click(function() {
var target = $(this).attr('class');
$('.area > .' + target).show().siblings().hide();
});
You show your real target and hide its siblings, which aren't needed.
If you put the class postfixes in an array, you can easily make this code more dynamic. This code assumed that it doesn't matter in which order toggle or hide are called. If it does matter, you can just remember the right classname inside the (inner) loop, and toggle that class after the loop.
The advantage to this approach is that you can extend the array with an exta class without needing to modifying the rest of the code.
var classes = new Array('videos', 'event', 'link', 'photos');
for (var i = 0; i < classes.length; ++i)
{
$('.btn_add_' + classes[i]).click(
function()
{
for (var j = 0; j < classes.length; ++j)
{
if (this.hasClass('btn_add_' + classes[j]))
{
$('.block_' + classes[j]).toggle();
}
else
{
$('.block_' + classes[j]).hide();
}
}
});
}
You could make this code more elegant by not assigning those elements classes like btn_add_event, but give them two classes: btn_add and event, or even resort to giving them id's. My solution is based on your description of your current html.
Here is what I think is a nice flexible and performant function. It assumes you can contain your links and html blocks in a parent, but otherwise it uses closures to precalculate the elements involved, so a click is super-fast.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" ></script>
<script type="text/javascript">
// Enables show/hide functionality on click.
// The elements within 'container' matching the selector 'blocks' are hidden
// When elements within 'container' matching the selector 'clicker' are clicked
// their attribute with the name 'clickerAttr' is appended to the selector
// 'subject' to identify a target, usually one of the 'blocks'. All blocks
// except the target are hidden. The target is shown.
//
// Change clickerAttr from 'linkTarget' to 'id' if you want XHTML compliance
//
// container: grouping of related elements for which to enable this functionality
// clicker: selector to element type that when clicked triggers the show/hide functionality
// clickerAttr: name of the DOM attribute that will be used to adapt the 'subject' selector
// blocks: selector to the html blocks that will be shown or hidden when the clicker is clicked
// subject: root of the selector to be used to identify the one html block to be shown
//
function initToggle(container,clicker,clickerAttr,blocks,subject) {
$(container).each(
function(idx,instance) {
var containerElement = $(instance);
var containedBlocks = containerElement.find(blocks);
containerElement.find(clicker).each(function(idxC, instanceClicker) {
var tgtE = containerElement.find(subject+instanceClicker.getAttribute(clickerAttr));
var clickerBlocks = containedBlocks.not(tgtE);
$(instanceClicker).click(function(event) {
clickerBlocks.hide();
tgtE.toggle();
});
});
// initially cleared
containedBlocks.hide();
}
);
}
$(function() {
initToggle('.toggle','a.link','linkTarget','div.block','div.');
});
</script>
</head>
<body>
Example HTML block toggle:
<div class="toggle">
a <br />
b <br />
c <br />
<div class="A block"> A </div>
<div class="B block"> B </div>
<div class="C block"> C </div>
</div> <!-- toggle -->
This next one is not enabled, to show scoping.
<div class="toggle2">
a <br />
<div class="A block">A</div>
</div> <!-- toggle2 -->
This next one is enabled, to show use in multiple positions on a page, such as in a portlet library.
<div class="toggle">
a <br />
<div class="A block">A</div>
</div> <!-- toggle (2) -->
</body>
</html>