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!
Related
I was wondering how you can link to a element that is loaded from an external javascript (it's like a chat widget hosted on an external website). I googled a lot of threads on stack overflow with similair issues but none of the code worked as expected.
The code that appears in the header of my website;
var shadow = 'box-shadow: none;'
var customStyle = '.ExampleLauncherContent__bubble {' + shadow + '}';
var myExample = new ExamplePopup({
index: 'https://example.com/example.html',
launcherOptions: {
style: customStyle,
}
});
Then the element is styled like this on the custom CSS section of my website
.ExampleLauncher:before {
content: "Example";
position: absolute;
padding: 15px;
padding-left: 75px;
opacity: 1;
color: #333;
border-radius: 30px;
background: #FFF;
z-index: -1;
}
Now I would like to make the entire CSS styled element clickable with a link, but I am not sure how to integrate the code, example i found in other threads that did not work as expected (or maybe I implemented wrong)
<script>
a onclick="jsfunction()" href="#"
</script>
<script>
div.ExampleLauncher("click", function() {
alert("You clicked this div");
});
</script>
<script>
$(".ExampleLauncher").keyup(function(event){
if(event.keyCode == 13){
$(".ExampleLauncher").click();
}
});
</script>
<script>
$(".ExampleLauncher").click(function(){
window.location=$(this).find("a").attr("href");
return false;
});
</script>
<script>
$('.ExampleLauncher').onclick="myExample.open()
});
</script>
Regarding recent comments, this is script used to trigger the chatbot popup with a textlink
myLandbotpop.on('landbot-load', function(){
var buttonOpen = document.getElementsByClassName("openbot")[0];
buttonOpen.addEventListener("click", myLandbotpop.open)
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>
I am new to jquery and have problem with one part of my script. basically I am making dropdown div when mouse is over the button, but div starts moving up and down like crazy. here is what i have done: `
<script type="text/javascript">
public var boolean opened = false;
$("#drop1").slideUp();
$("#first").mouseover(function(){
$("#drop1").slideDown();
});
$("#first").mouseout(function(){
$("#drop1").slideUp();
});
});
also I tried using boolean variable but it gives me error.
<script type="text/javascript">
$(document).ready(function(){
public var boolean opened = false;
$("#drop1").slideUp();
$("#first").mouseover(function(){
if(!opened){
$("#drop1").slideDown();
opened = true;
}
});
$("#first").mouseout(function(){
if(opened){
$("#drop1").slideUp();
opened = false;
}
});
});
here is HTML if you want, but I think there is everything ok.
<link rel="stylesheet" type="text/css" href="design.css">
<div id="first" style="position: absolute; left: 0px;">
<a class="btn" href = "TheShooter/Launcher.exe" ><b>LAN shooter project</b></a>
<div id="drop1">
<em>shooter project main page</em> <br/>
info: Local Area Network multiplayer game, made with unity. Project not finished yet, but sometimes fun to play. <br/>
controls: walking: w,a,s,d<br/>
shoot: LMB.<br/>
zoom: RMB.
</div>
</div>
Thanks for any help.
--Nick.
So it looks like you might be more used to strongly typed languages like C#. JavaScript and its library jQuery are loosely typed, meaning you don't declare scope or type. Here's your code above cleaned up a bit to use correct syntax and solve the issues you're seeing:
$(document).ready(function(){
var opened = false;
// Instead of sliding this up, give the #drop1 element
// a property of display: none; to start - then remove the line below
$("#drop1").slideUp();
$("#first").mouseover(function(){
if(!opened){
// Below, I'm using a callback, which means the boolean
// won't update to true until after the animation is finished
$("#drop1").slideDown(400, function() {
opened = true;
});
}
})// Since it's the same element, we can chain events
.mouseout(function(){
if(opened){
// Another callback
$("#drop1").slideUp(400, function() {
opened = false;
});
}
}
});
});
Let me know if you have any questions about the above!
Hi please refer this fiddle which should answer your question. No need to add any boolean or conditional checking:
<div id="wrap">
<div id="text">text</div>
<div id="video">video</div>
and js
$(document).ready(function(){
$("#wrap").mouseover(function(){
$("#video").stop().slideDown("slow");
});
$("#wrap").mouseout(function(){
$("#video").slideUp("slow");
});
});
and css
#text
{
margin-top:20px;
float:center;
font:VNF-Museo;
font-size:40px;
color: #333;
margin-left:auto;
margin-right:auto;
border: 1px solid #000;
}
#video
{
display:none;
width:1024px;
height:278px;
border: 1px solid #000;
}
I think you should try something like this:
$(document).ready(function() {
$("#first").mouseover(function(){
$("#drop1").slideDown("slow");
});
$("#first").mouseout(function(){
$("#drop1").slideUp("slow");
});
});
See this example above, from the jQuery offical documentation, for more information:
http://api.jquery.com/mouseover/
http://api.jquery.com/mouseout/
Here is one more answer with live example,
$(document).ready(function(){
$("#drop1").mouseover(function(){
$("#first").slideDown("slow");
});
$("#drop1").mouseout(function(){
$("#first").slideUp("slow");
});
});
#first, #drop1 {
padding: 5px;
text-align: center;
background-color: #acacac;
border: solid 1px #c3c3c3;
}
#first {
padding: 50px;
display: none;
background-color: skyblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<div id="drop1">Mouse over on panel to slide down</div>
<div id="first">Hello Stackoverflow ..!</div>
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
}
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.