How can I apply a saved configuration - javascript

I'm working on an admin page and so far I've only worked on PHP and a bit of HTML. But now, I have run into a problem, what I would like to know is how I could apply this configuration automatically through HTML as shown in the following script:
<?php
if(isset($_SESSION['userID']))
{
$sql_result=$db->ExecuteQuery("SELECT `admin_set` FROM `users` WHERE `id`={$_SESSION['userID']}");
if($sql_result!=false)
{
//exit("Ok");
$j_settings=$sql_result->fetch_assoc()['admin_set'];
$_SESSION['admin_set']=$j_settings;
include_once("./classes/admin_settings.class.php");
$settings=new AdminSettings((string)$j_settings);
//echo '<script language="javascript" type="text/javascript" src="path/to/your/file.js"> sidebarColor('.') </script>';
}
}
function GetThemeKey(int $index) : string
{
switch($index)
{
case 0:
return "primary";
case 1:
return "dark";
case 2:
return "info";
case 3:
return "success";
case 4:
return "warning";
case 5:
return "danger";
default:
return "primary";
}
}
?>
<div class="card-body pt-sm-3 pt-0">
<!-- Sidebar Backgrounds -->
<div>
<h6 class="mb-0">Sidebar Colors</h6>
</div>
<a href="javascript:void(0)" class="switch-trigger background-color">
<div class="badge-colors my-2 text-start">
<span class="badge filter bg-gradient-primary<?=($settings->HighlightColor==0? ' active':'')?>" data-color="primary" onclick="sidebarColor(this)"></span>
<span class="badge filter bg-gradient-dark<?=($settings->HighlightColor==1? ' active':'')?>" data-color="dark" onclick="sidebarColor(this)"></span>
<span class="badge filter bg-gradient-info<?=($settings->HighlightColor==2? ' active':'')?>" data-color="info" onclick="sidebarColor(this)"></span>
<span class="badge filter bg-gradient-success<?=($settings->HighlightColor==3? ' active':'')?>" data-color="success" onclick="sidebarColor(this)"></span>
<span class="badge filter bg-gradient-warning<?=($settings->HighlightColor==4? ' active':'')?>" data-color="warning" onclick="sidebarColor(this)"></span>
<span class="badge filter bg-gradient-danger<?=($settings->HighlightColor==5? ' active':'')?>" data-color="danger" onclick="sidebarColor(this)"></span>
</div>
</a>
<!-- Sidenav Type -->
<div class="mt-3">
<h6 class="mb-0">Sidenav Type</h6>
<p class="text-sm">Choose between 2 different sidenav types.</p>
</div>
<div class="d-flex">
<button class="btn bg-gradient-dark px-3 mb-2 active" data-class="bg-gradient-dark" onclick="sidebarType(this)">Dark</button>
<button class="btn bg-gradient-dark px-3 mb-2 ms-2" data-class="bg-transparent" onclick="sidebarType(this)">Transparent</button>
<button class="btn bg-gradient-dark px-3 mb-2 ms-2" data-class="bg-white" onclick="sidebarType(this)">White</button>
</div>
<p class="text-sm d-xl-none d-block mt-2">You can change the sidenav type just on desktop view.</p>
<!-- Navbar Fixed -->
<div class="mt-3 d-flex">
<h6 class="mb-0">Navbar Fixed</h6>
<div class="form-check form-switch ps-0 ms-auto my-auto">
<input class="form-check-input mt-1 ms-auto" type="checkbox" id="navbarFixed" onclick="navbarFixed(this)">
</div>
</div>
<hr class="horizontal dark my-3">
<div class="mt-2 d-flex">
<h6 class="mb-0">Sidenav Mini</h6>
<div class="form-check form-switch ps-0 ms-auto my-auto">
<input class="form-check-input mt-1 ms-auto" type="checkbox" id="navbarMinimize" onclick="navbarMinimize(this)">
</div>
</div>
<hr class="horizontal dark my-3">
<div class="mt-2 d-flex">
<h6 class="mb-0">Light / Dark</h6>
<div class="form-check form-switch ps-0 ms-auto my-auto">
<input class="form-check-input mt-1 ms-auto" type="checkbox" id="dark-version" onclick="darkMode(this)">
</div>
</div>
Currently, what this script does is load a sidebar on the right that is displayed when a button is pressed. Specifically, my problem is that I want it to automatically apply the saved color when this element is loaded as well as make it change color when I click on one of the options and call the sidebarColor(this) function in a JavaScript file:
Pink color image
Blue color image
But if I refresh the page this color goes back to color 0 (pink). In the tests that I am doing, I have a PHP class called Admin Settings where I am setting the color 4 (orange) by default, as you can see in the previous code, I have modified the HTML so that the color is selected in the buttons based on this new default value and when I refresh the page, this button is correctly selected. But this color is not automatically applied on the page:
Problem image
So my question is: Where and how would I have to apply the sidebarColor() function so that it is called automatically when the element loads?
sidebarColor function:
function sidebarColor(a) {
var parent = a.parentElement.children;
var color = a.getAttribute("data-color");
for (var i = 0; i < parent.length; i++) {
parent[i].classList.remove('active');
}
if (!a.classList.contains('active')) {
a.classList.add('active');
} else {
a.classList.remove('active');
}
var sidebar = document.querySelector('.sidenav');
sidebar.setAttribute("data-color", color);
if (document.querySelector('#sidenavCard')) {
var sidenavCard = document.querySelector('#sidenavCard');
let sidenavCardClasses = ['card', 'card-background', 'shadow-none', 'card-background-mask-' + color];
sidenavCard.className = '';
sidenavCard.classList.add(...sidenavCardClasses);
var sidenavCardIcon = document.querySelector('#sidenavCardIcon');
let sidenavCardIconClasses = ['ni', 'ni-diamond', 'text-gradient', 'text-lg', 'top-0', 'text-' + color];
sidenavCardIcon.className = '';
sidenavCardIcon.classList.add(...sidenavCardIconClasses);
}
}

Related

How to look for child elements in a collection

im very new to javascript and probably thats a silly question. What I am trying to achieve is to loop through rows of a "table", get the innerHTML of specific child nodes and multiply them together.
The html looks like this:
<div class="parent">
...
<div class="countChild">
<div class="container">
<span class="count">5</span>
</div>
</div>
<div class="valueChild">
<span class="value">30</span>
</div>
...
</div>
<div class="parent">
...
<div class="countChild">
<div class="container">
<span class="count">2</span>
</div>
</div>
<div class="valueChild">
<span class="value">30</span>
</div>
...
</div>
To be specific: I want to get both the values inside the'countChild' and the 'valueChild'. In this example those are 5 and 30 for the first row and for the second row its 2 and 30. Then perform a muiltiplication.
What I tried to do is to get all the parent nodes and then iterating through them to get the child nodes.
const parents = document.getElementsByClassName('parent');
for(var row in parents) {
var count = row.getElementsByClassName('countChild').lastChild.innerHTML;
var value = row.getElementsByClassName('valueChild').lastChild.innerHTML;
....
}
However the debugger already throws an error when im trying to get the childs. The error message is row.getElemenstByClassName is not a function. I guess the collection cannot be used like this and my understanding of how to use js to get information from the document is wrong.
Edit: This is what the tree looks like
<div class="listing-entry">
<div class="value-container d-none d-md-flex justify-content-end">
<div class="d-flex flex-column">
<div class="d-flex align-items-center justify-content-end">
<span class="font-weight-bold color-primary small text-right text-nowrap">30</span>
</div>
</div>
</div>
<div class="count-container d-none d-md-flex justify-content-end mr-3">
<span class="item-count small text-right">5</span>
</div>
</div>
You should access parents like an array (not really array but you can cast it to one). Btw, I encourage you to use querySelectorAll and querySelector instead of getElementsByClassName
const parents = document.querySelectorAll(".parent")
parents.forEach(function(row) {
var countChild = row.querySelector(".countChild")
var valueChild = row.querySelector(".valueChild")
var count = countChild ? countChild.innerText : 0
var value = valueChild ? valueChild.innerText : 0
console.log(count, value, count * value)
})
<div class="parent">
...
<div class="countChild">
<div class="container">
<span class="count">5</span>
</div>
</div>
<div class="valueChild">
<span class="value">30</span>
</div>
...
</div>
<div class="parent">
...
<div class="countChild">
<div class="container">
<span class="count">2</span>
</div>
</div>
<div class="valueChild">
<span class="value">30</span>
</div>
...
</div>
Edit: I'm using querySelector instead of getElementsByClassName, and checking if child exists before accessing its innerText property.
Edit: here's a function to get all text nodes under a specific node. Then you can combine them and trim the result to get the value you want.
function textNodesUnder(node) {
var all = [];
for (node = node.firstChild; node; node = node.nextSibling) {
if (node.nodeType == 3) {
all.push(node);
} else {
all = all.concat(this.textNodesUnder(node));
}
}
return all;
}
var nodes = textNodesUnder(document.querySelector(".listing-entry"))
var texts = nodes.map(item => item.nodeValue.trim())
console.log(texts)
<div class="listing-entry">
<div class="value-container d-none d-md-flex justify-content-end">
<div class="d-flex flex-column">
<div class="d-flex align-items-center justify-content-end">
<span class="font-weight-bold color-primary small text-right text-nowrap">30</span>
</div>
</div>
</div>
<div class="count-container d-none d-md-flex justify-content-end mr-3">
<span class="item-count small text-right">5</span>
</div>
</div>

Clicking Yes button will add 1 and No button will Reset it back to 0. Just Like Streaks

Help me writing the Javascript Please!!
I want to make a streak just like the snapchat streaks when you click yes button and the streaks will be broken when the cross/reset/no button is pressed!
But here comes the Main thing that i want every users streak to be stored in their account ,for which i'll add Authentication on the Project Later!
I'm using MongoDB for storing Users and Streaks
The Streaks will be Displayed here:
<p class="mt-2 text-gray-400">
Praying without any Break since
<span id="streaks">0</span> day(s)!
</p>
These are the Buttons:
<div class="group relative flex justify-between items-center mt-2">
<h1 class="text-lg">Have you offered all Prayers Today?</h1>
<div class="flex flex-row">
<!-- YES Button -->
<button
id="answer_yes"
onclick="updateScores"
class="flex p-2 m-1 border-2 rounded hover:text-white text-green-400 border-green-400 hover:bg-green-400"
>
<span>✓</span>
</button>
<!--NO BUtton-->
<button
id="answer_no"
class="flex p-2 m-1 border-2 rounded hover:text-white text-red-400 border-red-400 hover:bg-red-400"
>
<span>✗</span>
</button>
</div>
</div>
THe Javascript i was trying was this:
const yes = {
score: 0,
button: document.querySelector("#answer_yes"),
display: document.querySelector("#streaks"),
};
const resetButton = {
score: 0,
button: document.querySelector("#answer_no"),
display: document.querySelector("#streaks"),
};
function updateScores(streaks) {
streaks.score += 1;
streaks.display.classList.add("has-text-success");
streaks.button.disabled = true;
streaks.display.textContent = streaks.score;
}
yes.button.addEventListener("click", function () {
updateScores(streaks);
});
resetButton.addEventListener("click", reset);
function reset() {
for (let p of [yes, resetButton]) {
p.score = 0;
p.display.textContent = 0;
p.button.disabled = false;
}
}
P.S: I'm a Beginner so bear with my useless and shitty Code! This my First Full-Stack Project and i can't even create the Javascript.
I saw that your current code is all basic HTML and JavaScript and it is not working. So I made it work.
After changing, this is your HTML code:
<p class="mt-2 text-gray-400">
Praying without any Break since
<input id="streaks" value=0 disabled/> day(s)!
</p>
<div class="group relative flex justify-between items-center mt-2">
<h1 class="text-lg">Have you offered all Prayers Today?</h1>
<div class="flex flex-row">
<button
id="answer_yes"
onclick="onYesButton()"
class="flex p-2 m-1 border-2 rounded hover:text-white text-green-400 border-green-400 hover:bg-green-400"
>
<span>✓</span>
</button>
<button
id="answer_no"
onclick="onNoButton()"
class="flex p-2 m-1 border-2 rounded hover:text-white text-red-400 border-red-400 hover:bg-red-400"
>
<span>✗</span>
</button>
</div>
</div>
And this is your JS code:
function onYesButton() {
if (+document.getElementById('streaks').value >= 0) {
document.getElementById('streaks').value =
+document.getElementById('streaks').value + 1;
}
}
function onNoButton() {
if (+document.getElementById('streaks').value >= 1) {
document.getElementById('streaks').value =
+document.getElementById('streaks').value - 1;
}
}
You can check it now, the functionality works as you wanted.

how to loop through an array to hide items

i have an html form in which the user clicks on the plus sign and it shows you a list of items, if you click on a minus sign it will hide those items
as follows:
<div repeat.for="categoryGrouping of categoryDepartment">
<div class="row">
<div class="col s12 m3 l3">
<div class="card blue-grey darken-1">
<div class="card-content" style="padding:10px">
<span class="card-title white-text truncate">${categoryGrouping.name}</span>
<a if.bind="categoryGrouping.hideDetails" class="btn-floating halfway-fab waves-effect waves-light" click.delegate="Activate(user, categoryGrouping)"><i class="material-icons">add</i></a>
<a if.bind="!categoryGrouping.hideDetails" class="btn-floating halfway-fab waves-effect waves-light" click.delegate="DeActivate(user, categoryGrouping)"><i class="material-icons">remove</i></a>
</div>
</div>
</div>
</div>
<div repeat.for="categoryGroupingTypes of categoryDepartmentTypes">
<div class="row" if.bind="!categoryGrouping.hideDetails">
<div repeat.for="user of categoryGroupingTypes.users" class="col s12 m3 l3 ">
<div class="card blue-grey darken-1" click.delegate="GetCrewProfiles(user)">
<div class="card-content">
<span class="card-title white-text truncate">${user.firstName} ${user.lastName}</span>
<p>${user.emailAddress || 'mock#email.com'}<br /></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
in type script
async Activate(user: userListModel[], department: any) {
this.categoryDepartment.forEach(x => {
x.hideDetails = true;
});
this.categoryDepartmentTypes = await this.getTypes(user, department.name);
department.hideDetails = false;
}
async DeActivate(user: userListModel[], department: any) {
department.hideDetails = true;
}
this.categoryDepartment stores my array as follows:
0:{hideDetails:true, name:"Hello"}
1:{hideDetails:false,name:"Test"}
so the above looks as the following image
so now for example if i had to click on the "Hello" plus sign while the details for "Test" is open it would close "Test".
How can i loop through the departments to have it remain open but only when i click the minus then it should close.
I need to pass in the department name to this await this.getTypes(user, department.name); method, so only the item i click on should pass that name in and not all the department names.
does anyone know how i can achieve this?
i tried doing the following
if (this.categoryDepartment.find(x => x.name == department.name)){
this.categoryDepartmentTypes = await this.getTypes(user, department.name);
department.hideDetails = false;
}
but it still does the same thing, it closes on the next item i click on
You hide everything in this loop:
this.categoryDepartment.forEach(x => {
x.hideDetails = true;
});
So you can remove it.

Stop Modal from closing when AngularJS gets update to model

I have a web application that polls a server for data updates (based on a queue of tests being run on the server). I have a bootstrap-modal containing a log if a test fails. When the application receives an update from the server, any open modal is closed but the page is left with the modal screen preventing interaction.
I have tried pausing updates when a modal is opened and resuming them when it is closed, but that doesn't seem to have fixed the problem. I have also tried moving the modals for logs to sit directly under in the DOM. It seems the data changing causes the page to redraw everything inside the controller.
excerpt from index.html
<div class="row" ng-controller="testStatusController as testStatus">
Header Row (static html)
<div class="row test-table-data {{script.colorClass}}" ng-repeat="script in testStatus.scripts">
<div class="col-md-2">
<p class="align-middle"><span class="d-inline d-md-none">Name: </span><span>{{script.tcName}}</span></p>
</div>
<div class="col-md-6 align-middle">
<p><span class="d-inline d-md-none">Description: </span>{{script.description}}</p>
</div>
<div class="col col-md-2 align-middle">
<p><span class="d-inline d-md-none">Run Status: </span>{{script.status}}</p>
</div>
<div class="col col-md-2">
<p>
<span class="icon text-align-middle dripicons-wrong text-danger big" ng-if="!script.pass && script.status=='Complete'" data-toggle="modal" data-target=".{{script.tcName.slice(0,-4)}}"></span>
<span class="d-inline icon dripicons-checkmark text-success big" ng-if="script.pass"></span>
<span class="spinner-border text-primary" ng-if="script.status=='Running'"></span>
<span class="d-inline icon dripicons-clock text-primary big" ng-if="script.status=='Not Run'"></span>
</p>
</div>
<div class="modal fade {{script.tcName.slice(0,-4)}} log" ng-if="!script.pass && script.status == 'Complete'">
<div class="modal-dialog modal-lg" ng-focus="testStatus.pauseUpdates(true)" ng-blur="testStatus.pauseUpdates(false)">
<div class="modal-content log-modal">
<div class="modal-header">
<div class="modal-title text-monospace">
<h4>{{script.tcName}}</h4>
<h6>{{script.description}}</h6>
</div>
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<p class="text-monospace"><span ng-repeat="log in testStatus.getLog(script.tcName).lines track by $index">{{log.line}}<br /></span></p>
</div>
</div>
</div>
</div>
</div>
<div class="row test-table-foot">
<div class="col-md-3">
<p>Passed: <span>{{testStatus.passed()}}</span></p>
</div>
<div class="col-md-3">
<p>Failed: <span>{{testStatus.failed()}}</span></p>
</div>
<div class="col-md-3">
<p>Remaining: <span>{{testStatus.remaining()}}</span></p>
</div>
<div class="col-md-3">
<p>Total: <span>{{testStatus.total()}}</span></p>
</div>
</div>
</div>
</div>
the update Function (in main.js called every 5 seconds) Comments indicate what code was removed to help keep things brief.
testList.updateResults = function () {
if (testList.running) {
$http({url:theUrl + "?cmd=json&testRun=default",
method: "GET"
}).then(function(response){
var strRes = response.data.result;
var tmp = angular.fromJson(strRes);
// update trName if bound input not focused
testList.scripts = tmp.tc;
testList.running = false;
angular.forEach(tmp.tc, function(script, index){
if(script.status != "Complete") {
testList.running = true;
script.colorClass = "text-primary";
}
else {
if(script.pass) {
script.colorClass = "text-success";
}
else {
script.colorClass = "text-danger";
if(!(script.tcName.slice(0, -4) in testList.logs)) {
testList.getLog(script.tcName);
}
}
}
});
// update start/stop button
}, function(data){
console.log(data);
});
}
};
I would expect that AngularJS would not update sections of the DOM if the data bound to them was the same, but instead everything in the controller section is redrawn. My next instinct was to separate the logs and the status into different controllers, but I suspect I will have the same problem when a new log gets appended to the list of logs.

jquery each selector and ajax not producing the right results

I am trying to simplify my code but running into issues where it is not working when it place in an each loop.
Here is what I am trying to do:
- html has n parent DIV that generates a report via an AJAX call to pull data
- each div respective to report utilizes a data attribute to define which report to pull
- based no the results of the report, it should populate the html with the respective results.
HTML Code (to simplify, using n = 2):
<div class="widget-box widget-hits card no-border bg-white no-margin" data-widget-report="widget-hits">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title text-black hint-text">
<span class="font-montserrat fs-11 all-caps">Weekly Hits
<i class="far fa-chevron-right p-l-5"></i>
</span>
</div>
<div class="card-controls">
<ul>
<li>
<a data-toggle="refresh" class="card-refresh text-black" href="#">
<i class="far fa-circle fa-xs"></i>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="row-xs-height ">
<div class="col-xs-height col-top relative">
<div class="row">
<div class="col-sm-6">
<div class="p-l-20 widget-total">
<h3 class="no-margin p-b-5"></h3>
<p class="small hint-text m-t-5">
<span class="label m-r-5">%</span>
</p>
</div>
</div>
<div class="col-sm-6">
</div>
</div>
<div class="widget-chart"></div>
</div>
</div>
</div>
</div>
<div class="widget-box widget-sales card no-border bg-white no-margin" data-widget-report="widget-sales">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title text-black hint-text">
<span class="font-montserrat fs-11 all-caps">Weekly Sales
<i class="far fa-chevron-right p-l-5"></i>
</span>
</div>
<div class="card-controls">
<ul>
<li>
<a data-toggle="refresh" class="card-refresh text-black" href="#">
<i class="far fa-circle fa-xs"></i>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="row-xs-height ">
<div class="col-xs-height col-top relative">
<div class="row">
<div class="col-sm-6">
<div class="p-l-20 widget-total">
<h3 class="no-margin p-b-5"></h3>
<p class="small hint-text m-t-5">
<span class="label m-r-5">%</span>
</p>
</div>
</div>
<div class="col-sm-6">
</div>
</div>
<div class="widget-chart"></div>
</div>
</div>
</div>
</div>
JS:
$('.widget-box').each(function() {
$widget_report = $(this).data('widget-report');
if ($widget_report !== undefined) {
$.ajax({
type: 'get',
url: '/admin/reports/' + $widget_report,
dataType: 'json',
success:
function(data) {
if (data.success) {
var labelsData = [];
var seriesData = [];
var trend = data.trend * 100;
widget_class = '.' + $widget_report + ' .widget-chart';
console.log(widget_class);
$(this).find('.widget-total h3').text(data.total);
$(this).find('.widget-total p span').text(trend + '%');
trend_span = $(this).find('.widget-total p').children('span');
if(data.trend > 0) {
$(this).find('.widget-total p span.label').addClass('label-success');
$(this).find('.widget-total p').text('Higher');
}
else {
$(this).find('.widget-total p span.label').addClass('label-important');
$(this).find('.widget-total p').text('Lower');
}
$(this).find('.widget-total p').prepend(trend_span);
$.each(data.values, function(key, value){
date = new Date(value.label + 'T00:00:00');
labelsData.push(date.getMonth() + 1 + '/' + date.getDate());
seriesData.push(value.value);
});
chartData = {
labels: labelsData,
series: [seriesData]
}
alert(widget_class);
new Chartist.Bar(widget_class, chartData, {
axisX: {
showGrid: false
},
axisY: {
showGrid: false,
showLabel: false
}
});
}
}
});
}
});
Here are the problems I've encountered:
$(this).find('.widget-total h3').text is not updating the respective DIV group
widget_class for some reason is always returning the last DIV group... even if the last DIV group was returning data.success = false. Ex: above would return widget-sales twice and not widget-hits and then widget-sales.
I am scratching my head on this one... I am able to get this to work without the .each loop and distinctively create one for each... but was hoping to make this universal and allow the control rely on the data-widget-report attribute on the html.
Is this the proper approach?
Any help / direction is appreciated...
Add var in front of widget_class and $widget_report so they are scoped to the function instead of global. I think that will fix your problem. Right now $widget_report gets replaced by the last widget even before the ajax calls are completed.
As for the $(this) not working, you have to assign it to a variable before you make the ajax call.
$('.widget-box').each(function() {
var widgetBoxElement = $(this);
var $widget_report = $(this).data('widget-report');
if ($widget_report !== undefined) {
$.ajax({
type: 'get',
url: '/admin/reports/' + $widget_report,
dataType: 'json',
success:
function(data) {
if (data.success) {
// use widgetBoxElement here instead of $(this)
}
}
});
}
});

Categories

Resources