How to apply CSS code from array in AngularJS? - javascript

I'm creating a web game with different levels and need to change a div style using code stored inside an array in AngularJS. The game has two screens: the left one the user types the code in HTML and, the right one shows the result. This screen has a background and a div with the element created by the code. Each level has a different style for the background, so it needs to be loaded when the user changes the current level.
The HTML code is as follows:
<div id="background" ng-class="css"></div>
And the code in AngularJS is:
$scope.css = [
{
//level one
'background-image': 'url(url1)',
'position' : 'absolute',
...
},
{
//level two
'background-image': 'url(url2)',
...
}];
Another approach is to use a variable called $scope.cur_level that I'm using get number of current level to use it in ng-class with conditions:
ng-class="cur_level = '0' ? 'level_one' : 'level_two'"
In this case, each level style was created in the CSS file. However, the style of the first level is loaded for every level. I really want use the array approach. What is the best way to do this?

Here's the correct way of using the ng-class directive:
(function () {
"use strict";
const app = angular.module("app", []);
app.controller("app.GameCtrl", $scope => {
$scope.currentLevel = "1";
$scope.setLevel = () => {
$scope.currentLevel = $scope.currentLevel === '1' ? '2' : '1';
};
}
);
})();
.container {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
width: 100px;
height: 100px;
color: #FFF;
font-size: 3em;
}
.level-one {
background-color: red;
}
.level-two {
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app" ng-controller="app.GameCtrl">
<div class="container" ng-class="{'level-one': currentLevel === '1', 'level-two': currentLevel === '2'}">
{{currentLevel}}
</div>
Change Level
</div>

Related

Hide section with data atribute and based on localStorage item

My idea is to hide some sections based on visitor sport. He would see a popup display when he enters the site for the first time. This popup has multiple buttons that should determine what content he will see further on. When he clicks on a button all the content with the selected sport would continue to be shown and all other sports content would hide. Also when data-sport="all" the function should not hide this section affecting all the other sports.
I used a localStorage() for saving this setting in the device preventing the user to be click the preferred sport everytime. The js is supposed to be a loop for always have a localStorage() item "stSport" and when the device doesn't have this item it launches the popup to capture the sport.
I've got this but it's not working presuming that some little thing is wrong.
Could you help me out?
Thanks in advance! :)
HTML:
<section data-sport="soccer"></section>
<section data-sport="basketball"></section>
<section data-sport="all"></section>
<div id="sportsModal">
<div id="sportsModal-group">
<button onclick="sportRemove()" class="sportsModal-sport">All</button>
<button onclick="sportExecute(soccer)" class="sportsModal-sport">Soccer</button>
<button onclick="sportExecute(futsal)" class="sportsModal-sport">Futsal</button>
<button onclick="sportExecute(basketball)" class="sportsModal-sport">Basketball</button>
<button onclick="sportRemove()" class="sportsModal-sport">Other</button>
</div>
</div>
CSS:
#sportsModal {
background-color: rgba(255,255,255,0.15);
position: fixed;
width: 100%;
height: 100%;
display: none;
justify-content: center;
align-items: center;
top: 0;
z-index: 99999;
left: 0;
}
#sportsModal-group {
display: flex;
flex-direction: column;
}
.sportsModal-sport {
margin-bottom: 10px;
}
JS:
function sportFunnel() {
$("#sportModal").css("display", "fixed");
}
function sportExecute(n) {
localStorage.removeItem("stSport");
localStorage.setItem("stSport", n);
var vstSports = localStorage.getItem("stSport");
$("*[data-sport]").hide();
var dataSport = "*[data-sport='" + vstSports + "']";
var dataSportAll = "*[data-sport='all']";
$(dataSportAll).show();
$(dataSport).show();
}
$(document).ready( function() {
if(!localStorage.getItem("stSport")){
sportFunnel();
var vstSports = localStorage.getItem("stSport");
}
else {
var stSportChosen = localStorage.getItem("stSport");
$("*[data-sport]").hide();
var dataSport = "*[data-sport='" + stSportChosen + "']";
var dataSportAll = "*[data-sport='all']";
$(dataSportAll).show();
$(dataSport).show();
}
});
function sportRemove() {
localStorage.removeItem("stSport");
var vstSportsValue = localStorage.getItem("stSport");
sportFunnel();
};
Welcome to SO.
I've created a simple fiddle using your example: https://jsfiddle.net/Dganenco/vxja4kb1/ When I've tried to run your code, I received an error msg in console that says: Uncaught ReferenceError: soccer is not defined
Fix for your issue is straight-forward - add quotes!
<button onclick="sportExecute('soccer')" class="sportsModal-sport">Soccer</button>
<button onclick="sportExecute('futsal')" class="sportsModal-sport">Futsal</button>
<button onclick="sportExecute('basketball')" class="sportsModal-sport">Basketball</button>

How do I create a list with definitions using javascript and JQuery? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am familiar with HTML5 & CSS3, and just starting to learn JS. I need help creating a list of string variables, and attach definitions to all of them.
Basically, I need a two column table, where the left column is the list of strings, and when you click the words, it pulls up the definition on the right. I also need to make sure that the page doesn't reload when you click on the different words.
The photo (link below) best illustrates what I'm trying to create.
http://i.imgur.com/vaqXGpW.png?1
Well I think I got what you want, it took me a while. The only thing you have to do now is to edit the values in the array to display other text. (Delta is set).
$(document).ready(function() {
var list = {
'Alfa': 'Alfa Text',
'Bravo': 'Bravo Text',
'Charlie': 'Charlie Text',
'Delta': 'Delta is the fourth letter of the Greek alphabet.<br/><br/>In the system of Greek numerals it has a value of 4.',
'Echo': 'Echo Text',
'Foxtrot': 'Foxtrot Text',
'Golf': 'Golf Text',
'Hotel': 'Hotel Text',
'India': 'India Text',
'Juliet': 'Juliet Text',
'Kilo': 'Kilo Text',
'Lima': 'Lima Text',
'Mike': 'Mike Text',
'November': 'November Text',
'Oscar': 'Oscar Text',
'Papa': 'Papa Text',
'Quebec': 'Quebec Text',
'Romeo': 'Romeo Text',
'Sierra': 'Sierra Text',
'Tango': 'Tango Text',
'Uniform': 'Uniform Text',
'Victor': 'Victor Text',
'Whiskey': 'Whiskey Text',
'X-ray': 'X-ray Text',
'Yankee': 'Yankee Text',
'Zulu': 'Zulu Text'
};
$.each(list, function(index, value) {
var listitem = $('<li></li>');
$('.letterlist').append(listitem.text(index));
});
$('.letterlist li').on('click', function() {
//Remove class from previous item
$('.selected').removeClass('selected');
//Add class to current item
$(this).addClass('selected');
var block = $('.block.right');
var descr = $('<p></p>');
var value = $(this).text();
//Empty header and content
block.children('h1').empty();
block.children('.content').empty();
//Add header and content
block.children('h1').text(value);
block.children('.content').append(descr.html(list[value]));
});
});
.block {
width: 250px;
height: 400px;
float: left;
font-family: Arial, sans-serif;
border: 3px solid #000;
overflow-y: auto;
}
.letterlist,
.letterlist li {
list-style: none;
padding: 0 20px;
}
.letterlist li.selected {
color: #f00;
background: #fac6c7;
}
.letterlist li:hover {
cursor: pointer;
}
.left {
font-size: 28px;
}
.content {
background: #fac6c7;
font-size: 20px;
margin: 10px 20px 20px;
padding: 16px 12px;
}
h1 {
text-transform: uppercase;
text-align: center;
margin: 10px 0 0 0;
}
p {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="block left">
<ul class="letterlist"></ul>
</div>
<div class="block right">
<h1></h1>
<div class="content">Select an item</div>
</div>
There are multiple ways you can implement this, but if you'd like to specifically generate everything from data using JavaScript (if you've gotten the data from an AJAX request to some API, for instance), then you can obtain/create an object with the key-value pairs matching up to words and their definitions respectively:
var dictionary = {
first: '<h2>First</h2> Is the 1st definition.',
second: '<h2>Second</h2> Is the 2nd definition.',
third: '<h2>Third</h2> Is the 3rd definition.'
};
Let's say you have some appropriately styled markup to start off with as a shell, which consists of two panels - one which will contain an unordered list of words, and another which will contain the definition text:
<div id="words" class="panel">
<ul></ul>
</div>
<div id="definition" class="panel"></div>
From here, you can iterate through each of the pairs in the dictionary object, where you then create HTML elements, assign click handlers, and append the elements to the DOM for each:
// For each of the word/definition pairs....
$.each(dictionary, function(word, definition) {
// Create a list item to hold the word
var listItem = $('<li>').addClass('word').text(word);
// Give the word item a click handler to display it's definition when clicked
listItem.click(function() {
// Set the definition HTML to the current word's definition
$('#definition').html(definition);
});
// Append it to the list of words in the DOM
$('#words ul').append(listItem);
});
Notice that the click handler is capturing the definition in context within the current iteration of the dictionary.
Here's a full, but minimal, example implementation of this method using jQuery with some explanatory comments:
$(function() {
// Define a dictionary of words, perhaps fetched from an API
var dictionary = {
first: '<h2>First</h2> Is the 1st definition.',
second: '<h2>Second</h2> Is the 2nd definition.',
third: '<h2>Third</h2> Is the 3rd definition.'
};
// For each of the word/definition pairs....
$.each(dictionary, function(word, definition) {
// Create a list item to hold the word
var listItem = $('<li>').addClass('word').text(word);
// Give the word item a click handler to display it's definition when clicked
listItem.click(function() {
// Set the definition HTML to the current word's definition
$('#definition').html(definition);
// Add the highlight class to the current element only
$('#words li').removeClass('highlight');
$(this).addClass('highlight');
});
// Append it to the list of words in the DOM
$('#words ul').append(listItem);
});
});
.panel {
display: inline-block;
float: left;
border-style: solid;
border-width: medium;
min-width: 200px;
min-height: 250px;
margin: 5px;
padding: 5px;
}
.word.highlight {
font-weight: bold;
}
.word {
list-style-type: none;
}
<div id="words" class="panel">
<ul></ul>
</div>
<div id="definition" class="panel"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
First of all: Keep your concerns separate. This means you keep your templates in HTML, your styles in CSS and your application logic in JS.
JS
var definitions = {
alpha: 'Alpha definition',
beta: 'Beta definition'
};
var $definitionsList = $('ul#definition-list');
var $definitions = $(document.createDocumentFragment());
for (var key in definitions) {
$('<li/>')
.text(key)
.on('click', displayDefinition.bind(null, key, definitions[key]))
.appendTo($definitions);
}
$definitionsList.append($definitions);
function displayDefinition(name, definition) {
$('#definition-display h1').text(name);
$('#definition-display p').text(definition);
}
HTML
<body>
<ul id="definition-list"></ul>
<div id="definition-display">
<h1></h1>
<p></p>
</div>
</body>
CSS
#definition-list {
// Some cool styles for the list
}
#definition-list li {
// Some cool styles for the list items
}

Change CSS Property through JavaScript. (Uses ID's and Classes)

I'm trying to resize a panel using JavaScript to fit a small image into a panel, and struggling badly.
It's within the bold:
<body id="visCinemaTransRefund"><br>
<div id="content"><br>
<ul class="PayPanel" id="paymentDetails"><br>
Here's the CSS that needs modifying:
visCinemaTransRefund .PayPanel { width: 435px; }
How would I be able to modify with width of this panel?
I've also got a form I'm trying to resize within CSS:
visCinemaTransRefund FORM (width: 1005px;)
document.getElementById('paymentDetails').style.width = '1000px';
Have you tried using:
document.getElementById("paymentDetails").getElementsByClassName("PayPanel")[0].style.width="1000px"
Remember: getElementsByClassName return an array of elements, so using [0] you are indexing first element (and, of course, the only one).
Since getElementsById return a single elements, getElementsByClassName could be useless.
If you want to do this using CSS class :
HTML:
<div id="myDiv" class="medium"></div>
<button id="btn">Click me</button>
CSS:
#myDiv {
background-color: gray;
}
.medium {
height: 50px;
width: 50px;
}
.big {
height: 100px;
width: 100px;
}
JS:
document.getElementById("btn").onclick = function() {
var element = document.getElementById("myDiv"); // or document.getElementsByClassName("className")
if (element.className == "medium") {
document.getElementById("myDiv").className = "big";
} else {
document.getElementById("myDiv").className = "medium";
}
};
JSFIDDLE
Use the following code to change the width of tags by accessing HTML element from the DOM using getElement functions and setting width to it using setAttribute javaScript function.
document.getElementById("paymentDetails").setAttribute("style","width:500px;");
document.getElementById("visCinemaTransRefund").getElementsByTagName("form")[0].setAttribute("style","width:1000px;");
Using JavaScript:
document.getElementById('paymentDetails').style.width = '1000px';
Using JQuery:
$("paymentDetails").width(1000);
$("paymentDetails").css("width","1000px");

Dynamic Widgets/UI Elements using Angular

I'm working on a GUI web application which basically consists of 3 tab containers that dynamically load different tabs based on server messaging (I'm using cometd). This is a chess gaming app, so, for example, when the server brings in a Game message, I need to create a game board and add it to one of the tab containers.
I figure I can use custom directives with some templating to neatly define the behavior of these different UI components but, is there a way to programmatically add them to the template? Like, for example, adding a chessboard HTML tag and then makeing Angular compile it and linking to the directive at runtime?
Is there any other good solution to this aproach? I'm also using Grids that update with lots of rows for games and user lists, other UI components like accordions, dialogs, so I'm also looking for an Angular based UI framework.
Thanks!
Edited: Here's the code sample HTML and Js.
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta http-equiv="Content-type" value="text/html; charset=utf-8">
<title>Angular Test App</title>
</head>
<body>
<h1>AngularJS Test</h1>
<style type="text/css">
.section-wrapper {
width: 500px;
height: 400px;
border: 1px solid #eee;}
.nav-tabs li {
position: relative;
}
.nav-tabs li .close-tab {
position: absolute;
top: 0;
right: 0;
font-family: monospace;
font-size: 15px;
cursor: default;
padding: 1px 4px;
}
.nav-tabs li .close-tab:hover {
color: #fff;
background: red;
}
.nav-tabs li .detach-tab {
position: absolute;
bottom: 0;
right: 0;
font-family: monospace;
font-size: 15px;
cursor: default;
padding: 1px 4px;
}
.nav-tabs li .detach-tab:hover {
color: #fff;
background: #666;
}
</style>
<section ng-controller="LiveChessCtrl">
<div class="section-wrapper">
<tabset>
<tab ng-repeat="game in (chessGames | filter:!detached)">
<tab-heading>
{{ game.players.join(' vs ') }}
<span class="detach-tab" ng-click="detachGame(game.gameId)">D</span>
<span class="close-tab" ng-click="endGame(game.gameId)">X</span>
</tab-heading>
<div id="{{ game.gameId }}"><chess-board-controller game-id="{{ game.gameId }}"></chess-board-controller></div>
</tab>
</tabset>
</div>
</section>
<button onclick="javascript:simulateIncomingCometdMessage()">Simulate a New Game message coming from cometd server</button>
<script src="js/angularjs/1.2.16/angular.js"></script>
<script src="js/testApp.js"></script>
</body>
</html>
And here's the JS file demonstrating what I'm trying to do:
var app = angular.module("myApp", []);
app.controller('LiveChessCtrl', ['$scope', function($scope) {
var lastGameIndex = 1;
$scope.chessGames = {};
$scope.newGame = function (opts) {
opts = opts || {};
var chessGame = {
gameId: 'chessboard_' + lastGameIndex,
players: opts.players,
detached: false
};
$scope.chessGames[chessGame.gameId] = chessGame;
lastGameIndex++;
};
$scope.endGame = function (gameId) {
delete $scope.chessGames[gameId];
};
$scope.detachGame = function (gameId) {
$scope.chessGames[gameId].detached = true;
// TODO: Add a modal dialog and inject the ChessBoard custom directive inside
};
$scope.newGame({
players: ['Dummy', 'Game'],
boardSize: 'auto',
colorScheme: 'metal',
chessBoardBorder: false
});
}]);
app.directive('chessBoardController', function($compile) {
return {
template: '<div id="chessboard_[[ gameId ]]></div>',
restrict: "E"
}
});
// Instead of writing a complete cometd implementation,
// let's just say we handle incoming messages here:
var dummyGameMessages = [
{
players: ['John', 'Paul'],
boardSize: 'auto',
colorScheme: 'metal',
chessBoardBorder: false
},
{
players: ['Bill', 'Lucy'],
boardSize: 'auto',
colorScheme: 'graffiti',
chessBoardBorder: false
},
{
players: ['Joe', 'Danny'],
boardSize: 'auto',
colorScheme: 'graffiti',
chessBoardBorder: false
}
];
var curGameMsg = 0;
var simulateIncomingCometdMessage = function() {
var Game = dummyGameMessages[curGameMsg++];
if (curGameMsg > 2)
curGameMsg = 0;
// TODO: Reference LiveChessCtrl $scope to programatically call newGame with the game information
// more over, I have the issue that on certain occations, there are different stuff that I want included
// in the same TabContainer. We now know that every thing I add to this container is a chess-board-game
// directive, but what about if I want to add a grid with the list of games, for example?
}
Now in this sample we're adding chess-board-controllers to the tab container, but ideally, we should identify incomming messages from cometd and be able to add any type of controller, so the HTML markup used there and the declarative approach doesn't seem to be working, unless I'm not correctly seeing the picture here.
I'd appreciate any help!

Stacking notification bars

I like the notification bars used in stackoverflow. I have found a jQuery plugin which makes the notification bar possible with just a few lines, but this plugin does not seem to stack multiple notifications bars when required.
Does anyone know of a better plugin or how to get the plugin below to stack bars as more notifications become available?
http://www.dmitri.me/blog/notify-bar/
...
<body>
<div id="notificationArea"></div>
<!-- rest of your website -->
</body>
</html>
Then to create notifications just do this in jquery:
$('#notificationArea').prepend('<div class="notification">This is my notification</div>');
its a bit basic, but this should do the trick, and because you are "prepending" you will get the stacking you are looking for. You can use append() too, but I was assuming you'd want the most recent notifications on the top.
To get the "X" (close) button just have a link in the notification with a class of notifcationClose and do:
$('.notificationClose').click(function(){ $('this').parents('.notification').remove(); })
I know that you are looking only for bar plugin, but I write my opinion. Imagine that you have more than 2 notifications in this bar. It grows and it could fill more space than you would like to. Instead of viewing results of action, user will see only notifications to half display of monitor :)
Try to consider using bar notifications, if you know that you will have more than one notification in time often.
I recommend jGrowl which is similar to the way that in OS X works. It is simple, good-looking and ready for many notifications in time.
good luck.
I wrote this piece of Javascript that does just that.
// Show a message bar at the top of the screen to tell the user that something is going on.
// hideAfterMS - Optional argument. When supplied it hides the bar after a set number of milliseconds.
function AdvancedMessageBar(hideAfterMS) {
// Add an element to the top of the page to hold all of these bars.
if ($('#barNotificationContainer').length == 0)
{
var barContainer = $('<div id="barNotificationContainer" style="width: 100%; margin: 0px; padding: 0px;"></div>');
barContainer.prependTo('body');
var barContainerFixed = $('<div id="barNotificationContainerFixed" style="width: 100%; position: fixed; top: 0; left: 0;"></div>');
barContainerFixed.prependTo('body');
}
this.barTopOfPage = $('<div style="margin: 0px; background: orange; width: 100%; text-align: center; display: none; font-size: 15px; font-weight: bold; border-bottom-style: solid; border-bottom-color: darkorange;"><table style="width: 100%; padding: 5px;" cellpadding="0" cellspacing="0"><tr><td style="width: 20%; font-size: 10px; font-weight: normal;" class="leftMessage" ></td><td style="width: 60%; text-align: center;" class="messageCell"></td><td class="rightMessage" style="width: 20%; font-size: 10px; font-weight: normal;"></td></tr></table></div>');
this.barTopOfScreen = this.barTopOfPage.clone();
this.barTopOfPage.css("background", "transparent");
this.barTopOfPage.css("border-bottom-color", "transparent");
this.barTopOfPage.css("color", "transparent");
this.barTopOfPage.prependTo('#barNotificationContainer');
this.barTopOfScreen.appendTo('#barNotificationContainerFixed');
this.setBarColor = function (backgroundColor, borderColor) {
this.barTopOfScreen.css("background", backgroundColor);
this.barTopOfScreen.css("border-bottom-color", borderColor);
};
// Sets the message in the center of the screen.
// leftMesage - optional
// rightMessage - optional
this.setMessage = function (message, leftMessage, rightMessage) {
this.barTopOfPage.find('.messageCell').html(message);
this.barTopOfPage.find('.leftMessage').html(leftMessage);
this.barTopOfPage.find('.rightMessage').html(rightMessage);
this.barTopOfScreen.find('.messageCell').html(message);
this.barTopOfScreen.find('.leftMessage').html(leftMessage);
this.barTopOfScreen.find('.rightMessage').html(rightMessage);
};
this.show = function() {
this.barTopOfPage.slideDown(1000);
this.barTopOfScreen.slideDown(1000);
};
this.hide = function () {
this.barTopOfPage.slideUp(1000);
this.barTopOfScreen.slideUp(1000);
};
var self = this;
if (hideAfterMS != undefined) {
setTimeout(function () { self.hide(); }, hideAfterMS);
}
}
To use it you must use jQuery and ensure there are no margins or padding on the body of your page.
The parameter that the AdvancedMessageBar takes is optional. If provided it will cause the bar to disappear after a certain amount of time in milliseconds.
var mBar = new AdvancedMessageBar(10000);
mBar.setMessage('This is my message', 'Left Message', 'Right Message');
mBar.show();
If you want to stack these then just create more AdvancedMessageBar objects and they'll automatically stack.

Categories

Resources