I have the following code in my HTML file:
<div id="calc-parent">
<div class="row">
<div class="column" id="calc-display-val">0</div>
</div>
I need to get the value of calc-display-val, so I have the following JavaScript code:
let calcDisplayVal = document.getElementById("calc-display-val")
function pressOne() {
console.log(calcDisplayVal)
}
But instead of 0, I get "HTMLDivElement {}"
How can I get the value of calc-display-val?
You can use .innerHTML for this :
let calcDisplayVal = document.getElementById("calc-display-val")
function pressOne() {
console.log(calcDisplayVal.innerHTML)
}
pressOne()
<div id="calc-parent">
<div class="row">
<div class="column" id="calc-display-val">0</div>
</div>
If you need only the print of your div's content:
console.log(document.getElementById("calc-display-val").innerHTML)
<div id="calc-parent">
<div class="row">
<div class="column" id="calc-display-val">0</div>
</div>
</div>
Related
I have the following html structure
<div id="container">
<div id="child_1" data-customId="100">
</div>
<div id="child_2" data-customId="100">
</div>
<div id="child_3" data-customId="100">
</div>
<div id="child_4" data-customId="20">
</div>
<div id="child_5" data-customId="323">
</div>
<div id="child_6" data-customId="14">
</div>
</div>
And what I want to do is to get the count of child divs that contains different data attribute. For example, I'm trying this:
$(`div[id*="child_"]`).length); // => 6
But that code is returning 6 and what I want to retrieve is 4, based on the different data-customId. So my question is, how can I add a filter/map to that selector that I already have but taking into consideration that is a data-attribute.
I was trying to do something like this:
var divs = $(`div[id*="child_"]`);
var count = divs.map(div => div.data-customId).length;
After you getting the child-divs map their customid and just get the length of unique values:
let divs = document.querySelectorAll(`div[id*="child_"]`);
let idCustoms = [...divs].map(div=>div.dataset.customid);
//idCustoms: ["100", "100", "100", "20", "323", "14"]
//get unique values with Set
console.log([... new Set(idCustoms)].length);//4
//or with filter
console.log(idCustoms.filter((item, i, ar) => ar.indexOf(item) === i).length);//4
<div id="container">
<div id="child_1" data-customId="100">
</div>
<div id="child_2" data-customId="100">
</div>
<div id="child_3" data-customId="100">
</div>
<div id="child_4" data-customId="20">
</div>
<div id="child_5" data-customId="323">
</div>
<div id="child_6" data-customId="14">
</div>
</div>
Note: $ is equivalent to document.querySelectorAll in js returns a NodeList that's why I destructure it by the three dots ...
You'll have to extract the attribute value from each, then count up the number of uniques.
const { size } = new Set(
$('[data-customId]').map((_, elm) => elm.dataset.customid)
);
console.log(size);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="child_1" data-customId="100">
</div>
<div id="child_2" data-customId="100">
</div>
<div id="child_3" data-customId="100">
</div>
<div id="child_4" data-customId="20">
</div>
<div id="child_5" data-customId="323">
</div>
<div id="child_6" data-customId="14">
</div>
</div>
No need for jQuery for something this trivial, though.
const { size } = new Set(
[...document.querySelectorAll('[data-customId]')].map(elm => elm.dataset.customid)
);
console.log(size);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="child_1" data-customId="100">
</div>
<div id="child_2" data-customId="100">
</div>
<div id="child_3" data-customId="100">
</div>
<div id="child_4" data-customId="20">
</div>
<div id="child_5" data-customId="323">
</div>
<div id="child_6" data-customId="14">
</div>
</div>
Note that the property customid is lower-cased in the JavaScript. This could be an easy point of confusion. You might consider changing your HTML from
data-customId="14"
to
data-custom-id="14"
so that you can use customId in the JS (to follow the common conventions).
I have some HTML - pretty nasty, but not mine and so I don't have control over it. I need to extract some data from the form, the First name value (ABDIGANI) and the Surname value (AHMED). What is the best way to do this with javascript?
<div class="voffset3"></div>
<div class="container well panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-md-3">
<span class="ax_paragraph">
First name
</span>
<div class="form-group">
<div class="ax_h5">
ABDIGANI
</div>
</div>
</div>
<div class="col-md-3">
<span class="ax_paragraph">
Surname
</span>
<div class="form-group">
<div class="ax_h5">
AHMED
</div>
</div>
</div>
</div>
</div>
</div>
</div>
You could consider HTML in most cases well structured. Try this the following snippet.
Edit: did a change due to the first comment.
Edit: if you have more than one rows, you should use
document.querySelectorAll('.container > .panel-body > .row');
and fetch the pairs for each found element as below.
const markers = ['First name', 'Surname'];
const mRx = [new RegExp(markers[0]), new RegExp(markers[1])];
function findMarker(element) {
for(let i = 0; i < mRx.length; i++) {
if(element.innerHTML.match(mRx[i])) {
return markers[i];
}
}
return null;
}
function findValue(el) {
return el.parentElement.querySelector('.form-group > div').innerHTML.trim();
}
const pairs = [... document.querySelectorAll('.ax_paragraph')]
.map(el => {
return {el: el, mk: findMarker(el)};
})
.filter(n => n.mk !== null)
.map(o => {
return {key: o.mk, value: findValue(o.el)};
});
console.log(pairs);
var x = document.querySelectorAll(".panel-body > div >.col-md-3 > div > div");
x.forEach(myFunction);
function myFunction(item, index) {
//console.log(item.innerHTML.trim());
if (index===0){
console.log("First name : "+item.innerHTML.trim());
}
if (index===1){
console.log("Surname : "+item.innerHTML.trim());
}
}
<div class="voffset3"></div>
<div class="container well panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-md-3">
<span class="ax_paragraph">
First name
</span>
<div class="form-group">
<div class="ax_h5">
ABDIGANI
</div>
</div>
</div>
<div class="col-md-3">
<span class="ax_paragraph">
Surname
</span>
<div class="form-group">
<div class="ax_h5">
AHMED
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Check this
const firstName = document.querySelector('.row .form-group div').textContent.trim();
const surname = document.querySelector('.row > div:last-child .form-group div').textContent.trim();
note: Its better to change html according to functionality needs, like if you need firstname then you must keep an id attribute to div which is having first name, same goes to surname. then select those fields using id selector, because even if you change html page structure in future, functionality will not get effected.
Check below for reference on how the html should actually be(just to make sure you know it, but the solution you are seeking is above in first two lines)
eg:
<div class="voffset3"></div>
<div class="container well panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-md-3">
<span class="ax_paragraph">
First name
</span>
<div class="form-group">
<div class="ax_h5" id="firstNameField">
ABDIGANI
</div>
</div>
</div>
<div class="col-md-3">
<span class="ax_paragraph">
Surname
</span>
<div class="form-group">
<div class="ax_h5" id="surnameField">
AHMED
</div>
</div>
</div>
</div>
</div>
</div>
</div>
document.querySelector('.form-group > div').textContent but without modifying the html there is no way to distinguish first name and surname.
If you can't edit the HTML, you can use the XPATH for Example.
One final problem..how to dynamicaly change class name of same instruments by adding number?
<div class="score">
<div class="system">
<div class="stff_Flute"></div>
<div class="stff_Flute"></div>
<div class="stff_Clarinet"></div>
</div>
<div class="system">
<div class="stff_Flute"></div>
<div class="stff_Flute"></div>
<div class="stff_Clarinet"></div>
</div>
</div>
To this?...
<div class="score">
<div class="system">
<div class="stff_Flute_1"></div>
<div class="stff_Flute_2"></div>
<div class="stff_Clarinet"></div>
</div>
<div class="system">
<div class="stff_Flute_1"></div>
<div class="stff_Flute_2"></div>
<div class="stff_Clarinet"></div>
</div>
</div>
I have this code https://jsfiddle.net/7cLoxn29/1/ but something is wrong...
I'm not terribly fond of jQuery, so I created a vanilla JS solution for you (hopefully that's OK!):
let parents = document.querySelectorAll(".system")
parents.forEach((parent) => {
let children = parent.querySelectorAll("div")
children = Array.from(children).reduce((accumulator, current) => {
if (current.className in accumulator) {
accumulator[current.className].push(current)
} else {
accumulator[current.className] = [current]
}
return accumulator
}, {})
for (var key in children) {
if (children[key].length > 1) {
children[key].forEach((child, i, target) => {
child.className = `${child.className}_${i+1}`
})
}
}
})
Note that this is ES2015 JS code.
Here's an updated fiddle: https://jsfiddle.net/7cLoxn29/5/
I'm using this plugin called Dragula which needs an ObservableArray as a source for the data..
HTML/Knockout-bindings
<div class="widget-container">
<div class="widget-content visible" id="team-setup">
<div class="header">
<p>Lagoppsett</p>
<p></p>
</div>
<div class="col-sm-12">
<div class="row">
<div class="widget-container">
<div class="col-xs-6 widget-content visible">
<div class="header">
<p>Tilgjengelige spillere</p>
<p></p>
</div>
<div class="player-card-container-mini" data-bind="dragula: { data: availablePlayers, group: 'playerz' } ">
<div class="player-card-mini">
<div class="player-card-left">
<div class="player-avatar" style="margin-left: 85%;">
<img src="Content/Images/player-female.png" id="imgAvatar" runat="server" />
<div class="player-shirt-no" data-bind="text: ShirtNo"></div>
</div>
</div>
<div class="player-card-subtext">
<div class="player-text">
<div class="player-card-header-small" data-bind="text: PlayerName"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-6 widget-content visible">
<div class="header">
<p>Lag</p>
<p></p>
</div>
<div data-bind="foreach: teamsetup">
<div data-bind="foreach: SubTeams">
<h1 data-bind="text: TeamSubName"></h1>
<div class="player-card-container-mini" data-bind="dragula: { data: Players, group: 'playerz' } " style="border: 1px solid red; min-height:200px">
<div class="player-card-mini">
<div class="player-card-left">
<div class="player-avatar" style="margin-left: 85%;">
<img src="Content/Images/player-female.png" id="img1" runat="server" />
<div class="player-shirt-no" data-bind="text: ShirtNo"></div>
</div>
</div>
<div class="player-card-subtext">
<div class="player-text">
<div class="player-card-header-small" data-bind="text: PlayerName"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="clear:both"> </div>
</div>
</div>
Knockout code :
var TeamSetupViewModel = function () {
var self = this;
self.teamsetup = ko.observableArray();
self.availablePlayers = ko.observableArray();
self.testPlayers = ko.observableArray();
}
var model = new TeamSetupViewModel();
ko.applyBindings(model, document.getElementById("team-setup"));
var uri = 'api/MainPage/GetTeamSetup/' + getQueryVariable("teamId");
$.get(uri,
function (data) {
model.teamsetup(data);
model.availablePlayers(data.AvailablePlayers);
model.testPlayers(data.AvailablePlayers);
console.log(data);
}, 'json');
});
The problem is... that i'm having a ObservableArray at the top node, and i do need ObservableArrays further down in the hierarchy.
model.availablePlayers works fine, but when accessing the other players in the html/ko foreach loops through teamsetup -> SubTeams -> Players it doesn't work due to Players isn't an ObservableArray. (There might be everyting from 1 to 7 SubTeams with players).
So how can i make the Players in each SubTeams an ObservableArray ?
See the image for the datastructure :
You could use Mapping plugin, but if players is the only thing you need, you can do it manually:
Simplify your view model:
var TeamSetupViewModel = function () {
var self = this;
self.availablePlayers = ko.observableArray();
self.subTeams = ko.observableArray();
}
After you get the data from the server, populate the view model converting the array of players on every team to an observable array of players:
$.get(uri,
function (data) {
model.availablePlayers(data.AvailablePlayers);
model.subTeams(data.SubTeams.map(function(t) { t.Players = ko.observableArray(t.Players); return t; }));
}, 'json');
});
Finally, remove the following line in your template (with its closing tag) - nothing to iterate over anymore:
<div data-bind="foreach: teamsetup">
... and update the name of the property in the next line, so it is camel case like in the VM:
<div data-bind="foreach: subTeams">
Requirement goes like this :- I have left navigation panel which has to be in sync with the items added in the main active view by the user and has to display in tree structure. Basic idea is to provide context aware sub-view that change based on active view.
Custom directive used to display tree structure: https://github.com/nickperkinslondon/angular-bootstrap-nav-tree/blob/master/src/abn_tree_directive.js
my HTML code: (using ng-click)
<div class="add-data-request-panel" style="min-height:1071px;"
ng-click="expandPanel()">
<ul>
<li class="icon-drd icon-drd-diactive" ng-if="panelCollapse" ></li>
<li class="icon-pie-chart icon-pie-active" ng-if="panelCollapse"></li>
<li class="icon-publish-req" ng-if="panelCollapse"></li>
<li class="icon-view-changes" ng-if="panelCollapse"></li>
</ul>
</div>
<div class="data-slider-panel" style="min-height:1071px;display" ng-if="panelExpand">
<div class="data-slider-row mtop" ng-click="collapsePanel()">
<div class="slider-row-left">
<span class="first-char" >S</span>
<span class="second-char">ection</span>
</div>
<div class="slider-row-right">
<div class="icon-drd icon-drd-diactive">
</div>
</div>
</div>
<div class="data-slider-row">
<div class="slider-row-left">
Section2
<div class="sub-slider-row-left">
<abn-tree tree-data="mainArrayObj"></abn-tree> // passing data to tree directive
</div>
</div>
<div class="slider-row-right">
<div class="icon-pie-chart icon-pie-active">
</div>
</div>
</div>
<div class="data-slider-row" ng-click="collapsePanel()">
<div class="slider-row-left">
Section3
</div>
<div class="slider-row-right">
<div class="icon-publish-req">
</div>
</div>
</div>
<div class="data-slider-row" ng-click="collapsePanel()">
<div class="slider-row-left">
Section4
</div>
<div class="slider-row-right">
<div class="icon-view-changes">
</div>
</div>
</div>
</div>
JS implementation in my controller
$scope.panelExpand = false; //setting default flag
$scope.panelCollapse = true; //setting default flag
$scope.expandPanel = function() {
$scope.panelExpand = true;
$scope.panelCollapse = false;
$scope.mainArrayObj = []; // array that holds the data passed in html to custom directive
initialJsonSeparator($scope.model.Data); // method used for iteration
};
$scope.collapsePanel = function() {
$scope.panelExpand = false;
$scope.panelCollapse = true;
};
my HTML code: (using ng-mouseover which is not working and displaying the data passed to navigation bar)
<div class="add-data-request-panel" style="min-height:1071px;" ng-mouseover="hoverIn()"
ng-mouseleave="hoverOut()">
<ul>
<li class="icon-drd icon-drd-diactive"></li>
<li class="icon-pie-chart icon-pie-active"></li>
<li class="icon-publish-req"></li>
<li class="icon-view-changes"></li>
</ul>
</div>
<div class="data-slider-panel" style="min-height:1071px;display"
ng-mouseover="hoverIn()" ng-mouseleave="hoverOut()" ng-show="hoverEdit">
<div class="data-slider-row mtop">
<div class="slider-row-left">
<span class="first-char">S</span>
<span class="second-char">ection1</span>
</div>
<div class="slider-row-right">
<div class="icon-drd icon-drd-diactive">
</div>
</div>
</div>
<div class="data-slider-row">
<div class="slider-row-left">
Section2
<div class="sub-slider-row-left">
<abn-tree tree-data="mainArrayObj"></abn-tree> // array that holds the data passed in html to custom directive
</div>
</div>
<div class="slider-row-right">
<div class="icon-pie-chart icon-pie-active">
</div>
</div>
</div>
<div class="data-slider-row">
<div class="slider-row-left">
Section3
</div>
<div class="slider-row-right">
<div class="icon-publish-req">
</div>
</div>
</div>
<div class="data-slider-row">
<div class="slider-row-left">
Section4
</div>
<div class="slider-row-right">
<div class="icon-view-changes">
</div>
</div>
</div>
</div>
js Implementation for the ng-mouseOver: (while debugging all the iteration and methods executed as expected)
$scope.hoverIn = function() {
this.hoverEdit = true;
$scope.mainArrayObj = []; // array that holds the data passed in html to custom directive
initialJsonSeparator($scope.model.Data); //method used to iterate the data
};
$scope.hoverOut = function() {
this.hoverEdit = false;
};
Any solution to this issue would be of gr8 help. If there is any other better approach other than the ng-mouseOver and ng-mouseLeave to implement hover, please do let me know.