Need to know how I could possibly save the state of the darkmode?
I got this js code right here:
$('#switch').on('click', () => {
if ($('#switch').prop('checked')) {
$('body').addClass('dark');
$('main').addClass('darklight');
$('footer').addClass('darklight');
$('.topnav').addClass('darklight');
$('.lightm').addClass('darklight');
$('section').addClass('darklight');
$('button').addClass('button');
$('.links').addClass('llinks');
} else {
$('body').removeClass('dark');
$('body').addClass('light');
$('main').removeClass('darklight');
$('main').addClass('light');
$('footer').removeClass('darklight');
$('footer').addClass('light');
$('.topnav').removeClass('darklight');
$('.topnav').addClass('light');
$('.lightm').removeClass('darklight');
$('.lightm').addClass('light');
$('section').removeClass('darklight');
$('section').addClass('light');
$('button').removeClass('button');
$('button').addClass('dbutton');
$('.links').removeClass('llinks');
$('.links').addClass('dlinks');
}
})
Here is the code in Codepen with the html and css things:
https://codepen.io/TRGYT/pen/eYmNBPo
Does anyone have idea on how to achieve this? And can this darkmode state also be saved for other sites I created?
Please find the site here:
https://15min.netlify.com
Sorry in advance for the bad code, I'm a beginner...
Welcome to the world of coding. Before we get to the problem, it will be of some use to you to get to grips with the DRY principle (Don't Repeat Yourself). Your code (20 or so lines) could easily be abbreviated to just four. For example:
$("#switch").on("click", () => {
$("body").toggleClass("dark"));
// Local storage. Will get to this later
});
You could then change your CSS to respond to whether or not the body tag has the dark class. Much cleaner.
As for saving the state of the dark mode: use window.localStorage like so:
if (window.localStorage) {
const darkMode = window.localStorage.getItem("darkMode");
if (darkMode) {
$("body").addClass("dark");
} else {
$("body").removeClass("dark");
}
}
I found a way that wored. The one answer I got helped me understand it, but I was too lazy to implement it. But still thank you!
function activateDarkMode() {
$('body').addClass('dark').removeClass('light');
$('main').addClass('darklight').removeClass('light');
$('footer').addClass('darklight').removeClass('light');
$('.topnav').addClass('darklight').removeClass('light');
$('.lightm').addClass('darklight').removeClass('light');
$('section').addClass('darklight').removeClass('light');
$('button').addClass('button').removeClass('button');
$('.links').addClass('llinks').removeClass('dlinks');
}
function deactivateDarkMode() {
$('body').removeClass('dark').addClass('light');
$('main').removeClass('darklight').addClass('light');
$('footer').removeClass('darklight').addClass('light');
$('.topnav').removeClass('darklight').addClass('light');
$('.lightm').removeClass('darklight').addClass('light');
$('section').removeClass('darklight').addClass('light');
$('button').removeClass('button').addClass('dbutton');
$('.links').removeClass('llinks').addClass('dlinks');
}
$('#switch').on('click', () => {
if ($('#switch').prop('checked')) {
activateDarkMode();
localStorage.setItem("darkmode", "enabled")
} else {
deactivateDarkMode();
localStorage.setItem("darkmode", "disabled")
}
});
let mode;
mode = localStorage.getItem("darkmode");
if (mode == 'enabled') {
activateDarkMode();
$('#switch').prop('checked', 'checked');
}
All I did was putting the addClass and removeClass into a function. He also added the localStorage and let the localStorage be in a variable called mode. After I created these things, I put them into an if to check if the darkmode is turned on or not.
Related
I read that either local storage or session storage would do the trick, but I'm having a hard time trying to make it work.
function changeStyleByClass(className, classToggle){
var element = document.getElementsByClassName(className);
for (var i=0; i < element.length; i++) {
element[i].classList.toggle(classToggle);
}}
document.getElementById("bulb").addEventListener("click", () => {
changeStyleByClass("bgcolor-lightdark", "dark-mode");
changeStyleByClass("nav", "dark-mode");
changeStyleByClass("nav-item", "dark-mode");
changeStyleByClass("card", "dark-mode");
changeStyleByClass("container", "dark-mode");
changeStyleByClass("bulbicon","dark-mode");});
I'd like to navigate through pages and still keep the theme that is currently on.
Thanks in advance!
You can use localStorage.setItem to store data and localStorage.getItem to retrieve data. One thing that I've noticed is that your light bulb button turns dark mode on, but doesn't turn dark mode off. I have a solution that also simplifies your process of changing themes.
var togButton = document.getElementById("togButton");
//Check localStorage
//It's commented out because it doesn't work in Stack Overflow snippet
//darkOn = localStorage.getItem("dark") == "true" ? true : false;
setTheme();
function setTheme(){
//Save to localStorage
//It's commented out because it doesn't work in Stack Overflow snippet
//localStorage.setItem("dark", darkOn ? "true" : "false");
if(darkOn){
document.body.setAttribute("theme", "dark");
togButton.innerHTML = "Turn off dark mode.";
}
else{
document.body.setAttribute("theme", "light");
togButton.innerHTML = "Turn on dark mode.";
}
}
var darkOn = false;
function toggle(){
darkOn = !darkOn;
setTheme();
}
togButton.addEventListener("click", toggle);
/*By doing body[theme=dark] it only takes effect if the <body> tag has an attribute called theme which is dark.*/
body[theme=light] .sampleClass{
color: black;
background-color: white;
}
body[theme=dark] .sampleClass{
color: mediumseagreen;
background-color: black;
}
<body>
<h1 class="sampleClass">Theme changes.</h1>
<button id="togButton">Turn on dark mode.</button>
</body>
This method is easier because you don't need to manually type all of the classes you want to turn to dark mode, you can just have bot dark and light modes in the CSS file.
I hope you understand the javascript + css. Good luck and ask me if you can't understand part of it.
Edit: Called setTheme() right away.
Edit 2: Explanation
The part which is localStorage.getItem("dark") == "true" ? true : false" is called turnary. The turnary syntax is condition ? value if true : value if false. It is basically the same thing as doing
if(localStorage.getItem("dark") == "true"){
darkOn = true;
}
else{
darkOn = false;
}
This is because localStorage is like a Map where the keys and values are both strings.
Moving on to the next part.
darkOn = false; Just declares the variable darkOn and by default it if false. The toggle function changes darkOn to be the opposite of what it is. the exclamation mark negates boolean values, so darkOn = !darkOn; turns darkOn to false if it was previously true, and true if it was previously false.
Then it calls the setTheme function to update the theme attribute in the <body> tag, causing the css to change. It also saves the current value to localStorage.
I’m writing a simple platformer game. I use tiled maps to create level layers for overlaps and collisions. I’m stuck with a problem: I’m trying to make player be able to climb the ladder when overlap with ladder tile happens.
I have a variable in gameSettings object playerMoveY: false (so by default player can only walk left or right)
When player overlaps the ladder tile he's able to climb but after that he's always able to climb because variable playerMoveY is still = true. I don't know how to switch it back. Maybe using the flag is not a good idea. I need advice. Thank you.
let gameSettings = {
playerSpeed: 60,
playerMoveY: false,
}
//here's the code from gameScene class
this.laddersLayer.setTileIndexCallback(29, this.allowClimb, this);
this.physics.add.overlap(this.player, this.laddersLayer);
movePlayerManager() {
if (this.cursorKeys.left.isDown) {
this.player.anims.play('playerWalkLeft', true);
this.player.setVelocityX(-gameSettings.playerSpeed);
} else if (this.cursorKeys.right.isDown) {
this.player.anims.play('playerWalkRight', true);
this.player.setVelocityX(gameSettings.playerSpeed);
} else {
this.player.setVelocityX(0);
this.player.anims.play('playerStand');
}
if (gameSettings.playerMoveY) {
if (this.cursorKeys.up.isDown) {
this.player.anims.play('playerClimb', true);
this.player.setVelocityY(-gameSettings.playerSpeed);
} else if (this.cursorKeys.down.isDown) {
this.player.anims.play('playerClimb', true);
this.player.setVelocityY(gameSettings.playerSpeed);
} else {
this.player.setVelocityY(0);
}
}
}
//and here's the callback function when overlap
allowClimb() {
gameSettings.playerMoveY = true;
}
You currently only check if the player is overlapping the ladder, and subsequently setting:gameSettings.playerMoveY = true;. You need a check for other types of tiles. I've never used tiled so I don't know how it works but I would suggest trying to implement something like this in the update function:
//this is just sudo code
if(player.byLadder() == true){
player.canClimb = true;
}else{
player.canClimb = false;
}
The player.byLadder() function would somehow have to return true at all times the player can climb (before climbing, while climbing, at the end of the climb). Again, I apologize for not having more concrete code as I've never touched Tiled.
We have an application running that currently works with both 3D and 2D files, and do not experience any issues when loading 3D files and DWG.
But when trying to load a PDF neither my "onItemLoadSuccess" or "onItemLoadFail" gets run
Autodesk.Viewing.Initializer(options, function onInitialized() {
// Select the container for the viewer
viewerApp = new Autodesk.Viewing.ViewingApplication(container);
// Load settings, i.e extension manager
viewerApp.registerViewer(viewerApp.k3D,
Autodesk.Viewing.Private.GuiViewer3D, { extensions: [ 'ExtensionManager'] });
// Select model to load defined by URN
viewerApp.loadDocument(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
});
}
function onDocumentLoadSuccess(doc) {
var viewables = viewerApp.bubble.search({ 'type': 'geometry' });
if (viewables.length === 0) {
console.error('Document contains no viewables.');
return;
}
// Choose any of the avialble viewables
viewerApp.selectItem(viewables[0], onItemLoadSuccess, onItemLoadFail);
}
function onItemLoadSuccess(viewer, item) {
console.log('onItemLoadSuccess()!');
}
function onItemLoadFail(errorCode) {
console.error('onItemLoadFail() - errorCode:' + errorCode);
}
The PDF file will still open and load, so I am wondering if there might be a different way to run an onItemLoadSuccess function, or we have to do something a bit differently to ensure that our PDF's also gets loaded correctly.
Any help is highly appreciated!
Starting from Viewer v6.3 you can load PDF directly with Autodesk.PDF and pass in callbacks to loadModel like you do other models:
Autodesk.Viewing.Initializer(options, function() {
viewer.start()
viewer.loadExtension('Autodesk.PDF').then(function() {
viewer.loadModel('/path/to/pdf', { page: 1 }, onLoadSuccess, onLoadFail);
});
});
See release notes here: https://forge.autodesk.com/blog/viewer-release-notes-v-63
(Adding to Bryan's answer...)
I wrote a blog post about this. Take a look at the DEMO and sample code to help answer your question about 'onItemLoadSuccess / onItemLoadFail' events.
BLOG: https://forge.autodesk.com/blog/fast-pdf-viewingmarkup-inside-forge-viewer
DEMO: https://wallabyway.github.io/offline-pdf-markup/
Hope that helps!
Is there any simple way how to create undo redo function in Kineticjs ?
I have found a Undo Manager for HTML 5 in https://github.com/ArthurClemens/Javascript-Undo-Manager, but I don't know how to put in Kineticjs, please help me.
thank you.
I was able to implement a simple solution based on a post by Chtiwi Malek at CodiCode. I also used some of the code from this problem as an example to draw rectangles, so credits go to them and Chtiwi.
The only difference in my solution is I used toJSON() to store each layer state in an array instead of toDataURL() on the canvas. I think toJSON() is needed over toDataURL() to be able to serialize all the data necessary to store each action on the canvas, but I'm not 100% on this so if someone else knows please leave a comment.
function makeHistory() {
historyStep++;
if (historyStep < history.length) {
history.length = historyStep;
}
json = layer.toJSON();
history.push(json);
}
Call this function everytime you want to save a step to undo or redo. In my case, I call this function on every mouseup event.
Bind these 2 functions to the Undo/Redo events.
function undoHistory() {
if (historyStep > 0) {
historyStep--;
layer.destroy();
layer = Kinetic.Node.create(history[historyStep], 'container')
stage.add(layer);
}
}
function redoHistory() {
if (historyStep < history.length-1) {
historyStep++;
layer.destroy();
layer = Kinetic.Node.create(history[historyStep], 'container')
stage.add(layer);
}
}
Here's the jsfiddle. Don't forget to initialize the array and step counter up top. Good luck!
I am not familiar with KineticJS, but the approach should be similar to the provided demo (that also uses a canvas).
Perhaps another example helps. Let's say I have an app to create/move/delete colored shapes that represent musical notes. I have a way to click-drag and highlight a selection of notes. Pressing Delete on the keyboard invokes the function onDeleteGroup:
onDeleteGroup: function(gridModel) {
// collect all notes in an array
// ...
this._deleteGroup(notes);
this.undoManager.register(
this, this._createGroup, [notes], 'Undo delete',
this, this._deleteGroup, [notes], 'Redo delete'
);
}
All notes are deleted, and 2 methods are registered with the undo manager:
The undo function (undo of delete will be create)
The redo function (after undo/create will be delete again)
Both functions are straightforward:
_deleteGroup:function(notes) {
// removes each note from the model
// thereby removing them from the canvas
// ...
}
_createGroup:function(notes) {
// add each note to the model
// thereby adding them to the canvas
// ...
}
As you can see, the data object (array of notes) is passed around for creation and deleting. You can do the same for manipulating singular objects.
i have written a class for the functionality:
http://www.sebastianviereck.de/en/redo-undo-class-kinetic-js/
To solve event listeners problem, work on by making clones
$scope.makeHistory=function() {
$scope.historyStep++;
if ($scope.historyStep < $scope.history.length) {
$scope.history.length = $scope.historyStep;
}
var layerC = $scope.topLayer.clone();
$scope.history.push(layerC);
};
$scope.undoObject = function(){
if($scope.historyStep > 0) {
$scope.historyStep--;
$scope.topLayer.destroy();
if($scope.historyStep==0){
$scope.topLayerAdd(2); // will put empty layer
}
else{
var layer = $scope.history[$scope.historyStep-1].clone();
$scope.topLayerAdd(1,layer);
}
$scope.topLayer.draw();
}
};
$scope.redoObject = function(){
if($scope.historyStep <= $scope.history.length-1) {
$scope.historyStep++;
$scope.topLayer.destroy();
var layer = $scope.history[$scope.historyStep-1].clone();
if($scope.historyStep==0){
$scope.topLayerAdd(2); // will put empty layer
}
else{
$scope.topLayerAdd(1,layer);
}
$scope.topLayer.draw();
}
};
works perfectly for me.
I have made a simple accordion for my site using jQuery... It worked great, but I've recently started working on a change where if you click the currently opened segments title (the clickable area to slide up/down), it should close the current section.
var sideMenu = {
activated: {},
setup: function() {
$('.menu-category-heading').bind('click', function() {
sideMenu.slideMenu($('ul', $(this).parent()));
});
},
slideMenu: function(menuObj) {
if (sideMenu.activated == menuObj) {
$(sideMenu.activated).slideUp(400);
sideMenu.activated = null;
console.log('same');
} else {
$(sideMenu.activated).slideUp(400);
menuObj.slideDown(500);
sideMenu.activated = menuObj;
console.log('new');
}
}
}
For some reason the comparison is never working... it does if I add $(menuObj).attr('id') and the same for activated. But this is not ideal as not all items will have an id attribute.
Any suggestions as to make the object comparison work? Or any other tips?
Thank you!
You are probably saving a jQuery object (the result of a $ call) rather than the native element. Each time you do a $(myEl) a new object is created and the references will not match up, but the native element will. Try:
if (slideMenu.activated[0] == menuObj[0]) {
...
}