I need to have a ng-click-event nested into another ng-click-event.
This doesn't seem to be a problem in the Chrome client I am able to use here at work, but the standard browser is IE9.
The problem is that clicking on the inner control does not trigger the function corresponding to the inner control, but rather the function of the parent control.
The code looks a little like this:
angular.module('App', [])
.controller('Controller', function() {
var self = this;
self.outer_function = function($event) {
alert('Outer function called');
}
self.inner_function = function($event) {
$event.stopPropagation();
alert('Inner function called');
}
});
.outer {
border: 1px solid black;
padding: 10px;
display: inline-block;
}
.inner {
margin: 0 10px;
padding: 5px;
border: 1px solid red;
display: inline-block;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="App">
<div ng-controller="Controller as ctrl">
<button class="outer" data-ng-click="ctrl.outer_function($event)">
This is the div
<div class="inner" data-ng-click="ctrl.inner_function($event)">
Inner div
</div>
</button>
</div>
</div>
Is there anything I am forgetting? Or a workaround to make this work in IE9?
Thanks in advance!
Related
I am new to css. How can I add a status button which changes color depending on chat availability on top of another button?
You can use the position property.
See an example code here.
Some resources:
https://www.w3schools.com/css/css_positioning.asp
https://developer.mozilla.org/en-US/docs/Web/CSS/position
From the picture i can tell you don't have to use 2 html elements on top of each other, but you can use css properties like border and background-color to achieve exactly as the button in your picture.
I posted how in the code below with even a little bit of javascript to toogle the button status (not needed for styling, so if you don't know any javascript yet, you can skip that part).
let isOpen = false;
const btn = document.querySelector("#btn");
const dot = document.querySelector(".dot");
const txt = document.querySelector("#text");
btn.addEventListener("click", () => {
if (isOpen) {
dot.style.backgroundColor = "red";
txt.innerHTML = "The chat is now closed";
} else {
dot.style.backgroundColor = "green";
txt.innerHTML = "The chat is now open";
}
isOpen = !isOpen;
});
.dot {
height: 25px;
width: 25px;
background-color: red;
border-radius: 50%;
display: inline-block;
border: 5px solid gray;
}
#wrapper {
border: 1px solid black;
text-align: center;
padding: 10px;
}
#btn {
margin-top: 10px;
}
<div id="wrapper">
<span class="dot"></span>
<p id="text">The chat is now closed</p>
</div>
<button id="btn">Toogle</button>
I have this html tag which reffers to the backButton provided by the WinJS library:
<button data-win-control="WinJS.UI.BackButton"></button>
I want to change its size. How can I do that? I tried using CSS by adding the ID "backButton" and font-size OR width/height properties, like this:
#backButton {
font-size: small;
}
#backButton {
height: 30px;
width: 30px;
}
EDIT: Code added and a picture of what happens when changing the values of width/height of the button.
// For an introduction to the Page Control template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232511
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/anime/anime.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
// TODO: Initialize the page here.
this.renderAnimeInfo(Identifier.file);
},
unload: function () {
// TODO: Respond to navigations away from this page.
},
updateLayout: function (element) {
/// <param name="element" domElement="true" />
// TODO: Respond to changes in layout.
},
renderAnimeInfo: function (id) {
// Path for the anime data.
var path = "data/animes.json";
// Retrieve the .json.
WinJS.xhr({ url: path }).then(
function (response) {
var json = JSON.parse(response.responseText);
for (var i = 0; i < json.length; i++) {
if (json[i].file == id) {
var animeData = json[i];
break;
}
}
},
function (error) {},
function (progress) {}
);
},
});
})();
.right {
float: right;
}
.left {
float: left;
}
.active {
background-color: blue;
}
#animeDetails {
background: red;
height: 100%;
width: 300px;
float: left;
}
#animeInfo {
display: -ms-grid;
height: 100%;
width: calc(100% - 300px);
float: right;
}
#navbar {
-ms-grid-row: 1;
padding: 20px 25px;
}
#navbar .right button {
margin-right: 4px;
}
#navbar input {
width: 150px;
}
#details {
-ms-grid-row: 2;
padding: 0 25px;
text-align: justify;
white-space: pre-line;
}
#details h3 {
width: 100%;
padding: 5px 0;
border-bottom: 1px solid #bebebe;
margin-bottom: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>anime</title>
<link href="anime.css" rel="stylesheet" />
<script src="anime.js"></script>
</head>
<body>
<div id="animeDetails"></div>
<div id="animeInfo">
<div id="navbar">
<div class="left">
<button class="left" data-win-control="WinJS.UI.BackButton"></button>
<h3>Back</h3>
</div>
<div class="right">
<button type="button" class="active">Details</button>
<button type="button">Episodes</button>
<button type="button">Characters</button>
<button type="button">Staff</button>
<input type="search" placeholder="Search" />
</div>
</div>
<div id="details">
<div id="synopsis">
<h3>Synopsis</h3>
<span>
</span>
</div>
</div>
</div>
</body>
When using the width/height properties, what happens is that the button does resize to the specified value, but the icon inside (which is not a background) doesn't. http://i.imgur.com/lMqmL0G.png
Possibly you have to set display: inline-block to button because the width of an element with display: inline (the default for buttons) is exactly the same as its content because it only takes up the space needed to display its contents so try with:
With id selector
#backButton {
height: 30px;
width: 30px;
display: inline-block;
}
<button id="backButton" data-win-control="WinJS.UI.BackButton"></button>
With style inline
<button data-win-control="WinJS.UI.BackButton" style="width: 30px; height: 30px; display: inline-block"></button>
Try to set the styles to child element .win-back
#backButton .win-back{
/*---styles---*/
}
You haven't given your button an ID. The CSS does not know what tag to link to.
<button id="backButton" data-win-control="WinJS.UI.BackButton"></button>
edit: you may find the following reference useful CSS Selectors
I'd like to add a box containing smileys icons above the comment area which opens using jQuery on click. What I come up with is this:
<div class="emo">
<i href="#" id="showhide_emobox"> </i>
<div id="emobox">
<input class="emoticon" id="icon-smile" type="button" value=":)" />
<input class="emoticon" id="icon-sad" type="button" value=":(" />
<input class="emoticon" id="icon-widesmile" type="button" value=":D" /> <br>
</div>
</div>
css:
.emoticon-smile{
background: url('../smileys/smile.png');
}
#icon-smile {
border: none;
background: url('../images/smile.gif') no-repeat;
}
jQuery:
// =======show hide emoticon div============
$('#showhide_emobox').click(function(){
$('#emobox').toggle();
$(this).toggleClass('active');
});
// ============add emoticons============
$('.emoticon').click(function() {
var textarea_val = jQuery.trim($('.user-comment').val());
var emotion_val = $(this).attr('value');
if (textarea_val =='') {
var sp = '';
} else {
var sp = ' ';
}
$('.user-comment').focus().val(textarea_val + sp + emotion_val + sp);
});
However I have difficulty placing buttons in a nice array and make background image for them (the button values appear before image and the array is not perfectly rectangular. So I'm wondering maybe this is not the best way to render this box.
Any ideas to do this properly?
First show images, on hover hide image and show text. No need for input elements to get text of Dom Node
Something like this:
$(document).ready(function() {
$(".wrapper").click(function() {
var value = $(this).find(".smily-text").text();
console.log(value);
alert("Smily text is '" + value + "'");
});
});
.smily {
background: url(http://www.smiley-lol.com/smiley/manger/grignoter/vil-chewingum.gif) no-repeat center center;
width: 45px;
height: 45px;
}
.smily-text {
display: none;
font-size: 20px;
text-align: center;
line-height: 45px;
height: 45px;
width: 45px;
}
.wrapper {
border: 1px solid red;
float: left;
cursor: pointer;
}
.wrapper:hover .smily {
display: none;
}
.wrapper:hover .smily-text {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="smily"></div>
<div class="smily-text">:)</div>
</div>
<div class="wrapper">
<div class="smily"></div>
<div class="smily-text">:(</div>
</div>
<div class="wrapper">
<div class="smily"></div>
<div class="smily-text">:]</div>
</div>
<div class="wrapper">
<div class="smily"></div>
<div class="smily-text">:[</div>
</div>
I have a container in which I would like to display items as though they were in two columns.
Each item has a different height because the content in it varies.
This is currently what it looks like:
I would like to remove the extra space between items vertically to look closer to this:
so that it looks as though the items are stacking.
A link to my sample code:
http://plnkr.co/edit/oc1XT4ia9GdIc4rzZ41Q?p=preview
As the question is using AngularJS this answer is compatible with that.
You'll need to create a divs wrapping around the repeat, and a repeat for each column you want, and then display or hide elements in there by ng-show="($index)%2==columnIndex".
Then float the two wrapping divs, and add a standard clearfix to the 1px solid black container so it wraps around the floating elements.
'use strict';
var app = angular.module( 'myApp', [] );
app.controller( 'myCtrl', [ '$scope', function ( $scope ){
$scope.value = 'test';
$scope.items = [];
var count = 10;
for(var i=0; i<count; i++){
var item = {
height: Math.round(Math.random()*30) + 20
};
$scope.items.push(item);
}
}] );
.itemContainer {
display: block;
width: 80%;
border: 1px solid black;
padding: 10px;
}
.item {
border: 1px solid blue;
padding: 5px;
margin: 1px;
display: block;
}
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.clearfix {
display: inline-block;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<div class='itemContainer clearfix'>
<div style="display:inline-block; float:left; width:40%;">
<div class="item" ng-repeat="item in items" style="height: {{item.height}}px" ng-show="($index)%2==1" >
{{item}}
</div>
</div>
<div style="display:inline-block; float:left; width:40%;">
<div class="item" ng-repeat="item in items" style="height: {{item.height}}px" ng-show="($index)%2==0" >
{{item}}
</div>
</div>
</div>
</body>
</html>
You can do a repeat around the repeat wrapping float:left elelements, and specify how many columns you want, and if you want dynamic resizing of columns youll have to watch for resizes and change the column size with it.
To prevent the double processing issue you'd ideally use a filter, and not ng-show.
In the future hopefully we can use the flexible boxes layout module without breaking it for certain browsers.
Just for the record. This is an HTML and CSS-only version of one approach to achieve this.
HTML:
<div id="LeftColumn">
<div class="left_cell">Just</div>
<div class="left_cell">The</div>
<div class="left_cell"></div>
<div class="left_cell"></div>
</div>
<div id="RightColumn">
<div class="right_cell">For</div>
<div class="right_cell">Record</div>
<div class="right_cell"></div>
<div class="right_cell"></div>
</div>
CSS:
#LeftColumn {
width: 200px;
float: left;
}
#RightColumn {
width: 200px;
float: left;
margin-left:4px;
}
.left_cell {
width:200px;
height:30px;
border: 1px solid blue;
margin-bottom:2px;
}
.right_cell {
width:200px;
height:42px;
border: 1px solid blue;
margin-bottom:2px;
}
Check the fiddle here. As you can see, the thing is just to put the contents of each column on separate div elements, and float the two divs.
You can use the new flex display method to achieve this.
HTML
<div >
<div style="height: 45px;"></div>
<div style="height: 31px;"></div>
<div style="height: 31px;"></div>
<div style="height: 34px;"></div>
<div style="height: 27px;"></div>
<div style="height: 23px;"></div>
<div style="height: 41px;"></div>
<div style="height: 34px;"></div>
<div style="height: 48px;"></div>
<div style="height: 47px;"></div>
</div>
CSS
body > div {
height: 220px;
padding: 1px;
display: flex;
flex-flow: column wrap;
border: 1px solid;
}
body > div > div {
border: 1px solid blue;
margin: 1px;
}
After a bit of research, I see that it is indeed difficult to do with just CSS, so I wrote a small AngularJS directive to do some of the processing.
Demo Here: http://plnkr.co/edit/UyRS0clrCwDpSrYgBsXS?p=preview
var app = angular.module( 'myApp', [] );
app.controller( 'myCtrl', [ '$scope', function ( $scope ){
$scope.value = 'test';
$scope.items = [];
var count = 20;
for(var i=0; i<count; i++){
var item = {
height: Math.round(Math.random()*30) + 20,
value: Math.round(Math.random()*30) + 20
};
$scope.items.push(item);
}
}] );
app.directive('columns', function(){
return {
restrict: 'E',
scope: {
itemList: '=',
colCount: "#"
},
link: function(scope, elm, attrs) {
//console.log(scope.itemList);
var numCols = 3;
var colsArr = [];
for(var i=0; i< numCols; i++){
colsArr.push(angular.element("<div class='column'>Col "+(i+1)+"</div>"));
elm.append(colsArr[i]);
}
angular.forEach(scope.itemList, function(value, key){
var item = angular.element("<div class='item' style='height:"+value.height+"px;'>"+value.value+"</div>");
// find smallest column
var smallestColumn = getSmallestColumn();
angular.element(smallestColumn).append(item);
});
function getSmallestColumn(){
var smallestHeight = colsArr[0][0].offsetHeight;
var smallestColumn = colsArr[0][0];
angular.forEach(colsArr, function(column, key){
if(column[0].offsetHeight < smallestHeight){
smallestHeight = column[0].offsetHeight;
smallestColumn = colsArr[key];
}
});
console.log(smallestColumn);
return smallestColumn;
}
}
};
});
with this being the html:
<columns item-list="items" col-count='3' class='itemContainer'></columns>
So what I'm trying to accomplish seems like easy CSS etc. Im changing a messaging system and what the conversations to start at the bottom sorta like Facebook or text message where it has one person on the left and the other on the right.
How do I get the divs to go up as new content is added via ajax? I saw this similar question but didn't quite understand what he mean focus on the LI. An example would be great.
Something like this perhaps?
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}
function prependChild(parent, element)
{
if (parent.childNodes)
parent.insertBefore(element, parent.childNodes[0]);
else
parent.appendChild(element)
}
window.addEventListener('load', mInit, false);
function mInit()
{
byId('btnAddNew').addEventListener('click', onAddBtnClicked, false);
}
function onAddBtnClicked()
{
var txtInputElem = byId('newMsgTxtInput');
var msgTxt = txtInputElem.value;
var li = newEl('li');
li.appendChild( newTxt( msgTxt ) );
var ulTgt = byId('msgTarget');
var existingLiItems = ulTgt.querySelectorAll('li');
var numItemsExisting = existingLiItems.length;
if (numItemsExisting%2 != 0)
li.className = 'even';
else
li.className = 'odd';
prependChild(ulTgt, li);
}
</script>
<style>
.controls
{
display: inline-block;
padding: 8px;
margin: 8px;
border: solid 1px #555;
border-radius: 4px;
color: #777;
background-color: #ddd;
}
#msgTarget
{
width: 275px;
border: solid 1px #555;
margin: 8px;
border-radius: 4px;
}
/*
Doesn't work 'properly' - since we add items at the top, rather than the bottom
The first item added will be 'even', then the second item gets added and now it's the first child 'even'
so, the item added first is now an 'odd' child. A better way may be to count the number of existing li
items the ul contains, before assigning the new li elements a class of even or odd that will enable css
styling.
#msgTarget li:nth-child(odd)
{
background-color: #CCC;
}
#msgTarget li:nth-child(even)
{
background-color: #5C5;
}
*/
.odd
{
background-color: #CCC;
}
.even
{
background-color: #5C5;
}
</style>
</head>
<body>
<div class='dlg'>
<div class='controls'>
<input id='newMsgTxtInput'/><button id='btnAddNew'>Add message</button>
</div>
<ul id='msgTarget'></ul>
</div>
</body>
</html>