AngularJS ng-class updating content - css

I've got some code in AngularJS here working half percent (I will explain) :
<button ng-class="{'svgMinus-dark': isDarkTheme, 'svgMinus': !isDarkTheme}"></button>
I also tried another writing to say the same :
<button ng-class="{'svgMinus-dark': true-condition, 'svgMinus': !isDarkTheme}" href=""></button>
And I got exactly the same result (and problem). My problem is, when I do set isDarkTheme to true (working), the class doesn't edit instantly. I have to click on my button. And I don't know why, when the $scope edits itself, the class doesn't toggle instantly.
Why do I have to click to see the class of my true-condition (or false condition) update ?... Is there a way to force my ng-class update when my $scope.isDarkTheme toggle to true or false ?
thanks a lot in advance, I'm getting less and less hair haha

Here is a working example. It might not help you, but you can use it (copy it) to edit your question and create a snippet to demonstrate your code.
angular.module('myApp', [])
.controller('myCtrl', ['$scope', '$timeout', function($scope, $timeout) {
$scope.isDarkTheme = false;
$scope.toggleDarkMode = function() {
$scope.isDarkTheme = !$scope.isDarkTheme
};
$timeout($scope.toggleDarkMode, 2000)
}]);
div {
padding: 20px;
height: 100%;
}
.is-dark {
background: #111;
}
.is-dark h1 {
color: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl" ng-class="{'is-dark': isDarkTheme}">
<h1>Toggle in 2 seconds</h1>
<button ng-click="toggleDarkMode()">Toggle dark mode</button>
</div>

Related

text of md-autocomplete with md-float-label becomes invisible when leaving the input

Everything works very nice, but when you click outside the autocomplete input the text gets invisible, if you click in the input it goes black again and you see it is there.
Here is my html:
<body ng-app='myapp' layout="column" ng-controller="autocompleteController as ctrl">
<md-content layout-align="center" layout="row">
<md-input-container style="background-color: #3C83E1; padding: 1vh 1vh 1vh 1vh" flex="33" class="md-whiteframe-4dp">
<div layout="row" layout-align="center center" style="margin-bottom: 1vh; margin-top: 1vh">
<img src="http://www.simplesdental.com/assets/img/simplesdental-logo-b.svg">
</div>
<md-autocomplete
md-no-cache="ctrl.noCache"
md-autoselect="true"
md-search-text="ctrl.searchText"
md-items="item in ctrl.queryProcurar(ctrl.searchText)"
md-item-text="item.name"
md-floating-label="Nome do Paciente"
>
<span md-highlight-text="ctrl.searchText">{{item.name}}</span>
<md-not-found>
Não foi encontrado um paciente com o nome "{{ctrl.searchText}}".
</md-not-found>
</md-autocomplete>
</md-input-container>
and my js:
angular.module('myapp', ['ngMaterial'])
.controller("autocompleteController", function ($http) {
Object.filter = function (obj, predicate) {
var result = {}, key;
for (key in obj) {
if (obj.hasOwnProperty(key) && !predicate(obj[key])) {
result[key] = obj[key];
}
}
return result;
};
this.queryProcurar = function (query) {
return $http.get("https://jsonplaceholder.typicode.com/users")
.then(function (response) {
var res = response.data.filter(function (obj) {
return obj.name.toLowerCase().indexOf(query.toLowerCase()) != -1;
});
return res;
})
}
})
here, a demo: http://codepen.io/iurypiva/pen/YZQeBN
Since I was using this in an ng-repeat, I didn't want to give the same id to multiple elements in order to style it, so I looked further.
The problem actually turns out that the input portion of the md-autocomplete is wrapped in its own md-input-container. The css in question checks to see if there is an input inside an md-input-container that does not have the md-input-has-value class. The outside one (yours and mine) does not, just the inside one.
So I had choices.
I could remove the md-input-container and make it a div, as suggested in another answer. However, because I have a few other inputs inside md-input-containers already in my page, and because the md-autocomplete would not be inside the md-input-container (just the input inside it), I'd have to duplicate all the styling that md-input-container uses (text-align: vertical; padding: 2px; etc.).
Or I could add class="md-input-has-value" to my md-input-container.
I went the simpler route.
<md-input-container class="md-input-has-value">
<md-autocomplete ...
See modified your codepen
The problem is that md-input-container and md-floating-label has some weird conflicts in their css. Solved it changing de md-container to a simple div
The problem is actually just a CSS/styling issue
The easiest way to address this would be to use angular material's md-input-id attribute that is available for md-autocomplete (documentation here)
<md-autocomplete
md-input-id="searchinput"
md-autoselect="true"
md-search-text="ctrl.searchText"
md-items="item in ctrl.queryProcurar(ctrl.searchText)"
md-item-text="item.name"
md-floating-label="Nome do Paciente">
this attaches an ID (in my example I just called it searchinput) to the input that gets auto-generated by md-autocomplete that you can use to style the input.
The CSS that I tried in your codepen was then simply:
#searchinput { color: white; }
here is a fork of your codepen with these updates

Change ion-view header color in ionic

I am using the ionic starter menubar template. I would like to change the header background color of each page. I currently have:
<ion-view view-title="Search">
<ion-content>
<h1>Search</h1>
</ion-content>
</ion-view>
I tried:
<ion-view view-title="Search" class="bar bar-header bar-assertive">
<ion-content>
<h1>Search</h1>
</ion-content>
</ion-view>
But it does not work at all (content is not rendered). The header documentation does not help me. What is the correct way to do this?
Some ways to do this:
You could add the ion-nav-bar to each view.
<ion-view view-title="Page 1">
<ion-nav-bar class="bar-balanced">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
<ion-content>
...
</ion-content>
</ion-view>
Codepen example
You could also update the background-color (and any other properties) by using ng-style
Main navbar:
<ion-nav-bar class="bar-positive" ng-style="{'background-color': viewColor}">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
CSS:
.nav-bar-block, .bar {
background-color: inherit !important;
}
Controller:
$scope.$on('$ionicView.beforeEnter', function() {
$rootScope.viewColor = 'green';
});
Codepen example
Could not find a clean solution for this, but one hack might be to use the $stateChangeStart event and set the class name manually.
angular.module('starter')
.run(function ($rootScope) {
var element;
$rootScope.$on('$stateChangeStart', function (event, next) {
if (next.name) {
element = angular.element(document.querySelectorAll('ion-header-bar'));
switch(next.name) {
case 'tab.chats':
element.removeClass('bar-positive');
element.removeClass('bar-balanced');
element.addClass('bar-calm');
break;
case 'tab.dash':
element.removeClass('bar-calm');
element.removeClass('bar-balanced');
element.addClass('bar-positive');
break;
default :
element.removeClass('bar-calm');
element.removeClass('bar-positive');
element.addClass('bar-balanced');
}
}
});
});
fiddle
EDIT
The idea is same for sidebar template,
Updated fiddle
Notice the line
<ion-nav-bar class="bar-positive">
in menu.html template, it denotes the base header color class.
but subsequent changes to pages i.e states header color needs to be changed manually in $stateChangeStart event,
code:
.run(function ($rootScope) {
var element;
$rootScope.$on('$stateChangeStart', function (event, next) {
if (next.name) {
element = angular.element(document.querySelectorAll('ion-side-menu-content ion-header-bar'));
console.log(element);
switch(next.name) {
case 'app.search':
element.removeClass('bar-positive');
element.removeClass('bar-energized');
element.removeClass('bar-dark');
element.addClass('bar-assertive');
break;
case 'app.browse':
element.removeClass('bar-calm');
element.removeClass('bar-assertive');
element.removeClass('bar-dark');
element.addClass('bar-energized');
break;
default :
element.removeClass('bar-positive');
element.removeClass('bar-energized');
element.removeClass('bar-assertive');
element.addClass('bar-dark');
}
}
});
});
here the state name is checked to see which page is activating ex. app.search
then according to requirement specific color class is assigned removing other color classes.
ionic color options
hope this helps.
if you are using different states and each state has a different controller than just have a $scope variable like $scope.stateone = "true" etc. Then on your ion-nav-bar use ng-class="{'bar-positive': stateone, 'bar-stable': statetwo, 'bar-assertive': statethree}". ng-class takes classes and an expression, whichever expression is true that is the class that is assigned. you can use ng-class with any boolean expression. this is how you can have a different color on each page.
I modified the solution of #shakib to fit my needs, in my case the user sets the theme by clicking the app logo and thus the bar color should change. If this is your case you don't need to do the switch case because you want to change all views
$rootScope.$on("$stateChangeStart", function (event, toState) {
var element;
if (toState.name){
element = angular.element(document.querySelectorAll('ion-side-menu-content ion-header-bar'));
if (debugMode) console.log(element);
// I get the bar-class from my localStorage where I keep the user settings
var saved_bar_class = $localStorage.get('bar-class','bar-calm');
element.removeClass('bar-pink');
element.removeClass('bar-calm');
element.addClass(saved_bar_class);
// Here We could use a Switch Case on toState.name to put a different color to each state
}
});
Also when the user clicks the app logo I want to immediately change the bar color in order to give feedback to the user of what that button do. The above code won't do that because we haven't changed state yet, to fix this just add this code to your 'change theme' function
$scope.changeAppTheme = function () {
var element;
element = angular.element(document.querySelectorAll('ion-side-menu-content ion-header-bar'));
// some code to select the theme
element.removeClass('bar-pink');
element.removeClass('bar-calm');
element.addClass('bar-pink');
// some other code
};
In this case I just have two colors, the ionic calm and a pink one that I defined
Hope this helps someone
We got it working in CSS with:
.title.title-center.header-item {
background-color: black;
margin: 0px;
}
This means that we just refer to the Angular generated header classes directly with this CSS. Hope this helps!
Try using the following code:
<ion-view>
<ion-header-bar class="bar-assertive">
<h1 class="title">Search</h1>
</ion-header-bar>
<ion-content>
<h1>Search</h1>
</ion-content>
</ion-view>
You can override $bar-stable-text color (taken from _variables.scss from ionic lib)
For example, in your scss change
$bar-stable-text: green !default;
If you want to change the ion-nav-bar this here works like a charm:
1 . Create a main controller to take care of your index page and all views within it.
2. Add this function to the controller:
$scope.setNavColor = function(color){
for(var i =0; i < document.getElementsByTagName("ion-header-bar").length; i++){
classNames = document.getElementsByTagName("ion-header-bar")[i].className;
classNames = classNames.replace(/(bar-light|bar-stable|bar-positive|bar-calm|bar-balanced|bar-energized|bar-assertive|bar-royal|bar-dark)/g, color );
document.getElementsByTagName("ion-header-bar")[i].className = classNames;
}
}
3 . add on-select to your ion-tab tab so it will call the function whenever your tab is chosen:
<ion-tab href="#addr" on-select="setNavColor('PUT_YOUR_COLOR_HERE')> </ion-tab>
4 . add on-deselect to you ion-tab too if you want the color to go back to some value when you leave.
5 . Have fun!
//add these lines in your style.css file under /www/css/ yoyr project directory
.title.title-center.header-item {
background-color:#30393A;//#F38023!important; // for bg color
margin:0px!important;
margin-left:0px!important;
color: #ffffff!important;
text-align: center !important;
width: 100%;
}
put these lines in your style.css under /www/css/ directory of your ionic project
.title.title-center.header-item {
background-color:#4a87ee;//#F38023!important; // for bg color
margin:0px!important;
margin-left:0px!important;
color: #ffffff!important;
text-align: center !important;
width: 100%;
}
If you're using scss within your app, you can create your own custom bar class and use ionic's bar mixins in it.
$bar-custom-bg: #ccc;
$bar-custom-border: #eee;
$bar-custom-text: #fff;
$bar-custom-active-border: darken($bar-custom-border, 10%);
$bar-custom-active-bg: darken($bar-custom-bg, 10%);
.bar {
&.bar-custom {
#include bar-style($bar-custom-bg, $bar-custom-border, $bar-custom-text);
&.bar-footer{
background-image: linear-gradient(180deg, $bar-custom-border, $bar-custom-border 50%, transparent 50%);
}
.button {
#include button-style($bar-custom-bg, $bar-custom-border, $bar-custom-active-bg, $bar-custom-active-border, $bar-custom-text);
#include button-clear(#fff, $bar-title-font-size);
}
}
}
After defining your class, you can use your new custom bar class with ion-nav-bar directive.
<ion-nav-bar class="bar-custom">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>

Why Does Turn.js Only Work Once in Meteor Application?

I want to integrate Turn.js in a meteor project, but come across a "small" problem ,
the script work well the first time I "load" the template , but wouldn't work when i come across the same template.
{{#if correspondances_readingMode}}
<script >
function loadApp() {
// Create the flipbook
$('.flipbook').turn({
// Width
width:922,
// Height
height:600,
// Elevation
elevation: 50,
// Enable gradients
gradients: true,
// Auto center this flipbook
autoCenter: true
});
}
// Load the HTML4 version if there's not CSS transform
yepnope({
test : Modernizr.csstransforms,
yep: ['../../lib/turn.js'],
nope: ['../../lib/turn.html4.min.js'],
both: ['css/basic.css'],
complete: loadApp
});
</script>
<style>
.page{
width:400px;
height:300px;
background-color:white;
line-height:300px;
font-size:20px;
text-align:center;
}
</style>
<div class="flipbook">
{{#each myPost}}
<div class="page">
{{{text}}}
</div>
{{/each}}
</div>
{{/if}}
All seems to go as if the script was only executed when the user come across the template the first time , but wouldn't launch again the second time.
I have try many thing, but I came to think it's because of the handlebar {{#if}}
P.s :
On chrome the second time it's loaded it doesn't show turn.js as a script :
I was running into the same problem. I figured that the width of the booklet was calculated before the containing div got its full width. I set a delay of 1 second after rendering and now it seems to work fine.
Template.menu.rendered = function(){
setTimeout(function() {
import '/imports/turn.min.js';
$(window).ready(function() {
$('#magazine').turn({
display: 'double',
acceleration: true,
gradients: !$.isTouch,
elevation:50,
when: {
turned: function(e, page) {
// console.log('Current view: ', $(this).turn('view'));
}
}
});
});
$(window).bind('keydown', function(e){
if (e.keyCode==37)
$('#magazine').turn('previous');
else if (e.keyCode==39)
$('#magazine').turn('next');
});
}, 1000);
};
`

How do I use ":nth-of-type" to select an element after the element is updated by jQuery?

I want to style the first element with a class that I've added through jQuery.
Unfortunately, my CSS styling is ignored when I use the :nth-of-type(1) selector.
Here is the Fiddle
When you click the button "World", the first word should be red but it isn't.
How do I use :nth-of-type to select an element after a jQuery updates the element?
You're using jQuery, fall back to it when CSS fails you. This doesn't mean inline styles, let's continue to use classes (modified fiddle):
Your new CSS:
.hidden {
display: none;
}
.seen {
display: inline-block;
}
.first {
color: red;
}
The new class .first replaces your attempt to match via CSS. We'll apply it with jQuery:
$( "button.1" ).click(function () {
$("span.1").toggleClass("seen hidden");
$("span").removeClass("first");
$(".seen:first").addClass("first");
});
$( "button.2" ).click(function () {
$("span.2").toggleClass("seen hidden");
$("span").removeClass("first");
$(".seen:first").addClass("first");
});
Now that things are working we've gotten to the point of "passing our test" (even though no test is written here, this is the point we'd be at). The next step is refactor. We've got some repetitive bits. Let's clean it up. Naively I may try and do this:
var selectFirst = function() {
$("span").removeClass("first");
$(".seen:first").addClass("first");
};
$( "button.1" ).click(function () {
$("span.1").toggleClass("seen hidden");
selectFirst();
});
$( "button.2" ).click(function () {
$("span.2").toggleClass("seen hidden");
selectFirst();
});
But in reality we can do much better by moving around some information in the HTML and changing our jQuery slightly (working fiddle):
Our new HTML looks like this:
<span class="hidden" data-number="1">Hello</span>
<span class="hidden" data-number="2">World</span>
<span class="hidden" data-number="1">Hello</span>
<span class="hidden" data-number="2">World</span>
<button data-target-number="1">Hello</button>
<button data-target-number="2">World</button>
Notice the usage of data- attributes. Much cleaner, the 1 and 2 as classes was really bogging down that attribute with useless information.
Let's see what effect that had on the jQuery:
$("button").click(function() {
var number = $(this).data("target-number"),
// This line could also be "span[data-number=" + number + "]"
targetSelector = ["span[data-number=", number, "]"].join("");
$(targetSelector).toggleClass("seen hidden");
$(".first").removeClass("first");
$(".seen:first").addClass("first");
});
That's it, only one function! No repeating ourself. The refactor was successful.
Try this:
.hidden:first-child + .seen, .seen:first-child {
color: red;
}
Working Fiddle
Updated to solve the issue represented in below comment:
.hidden:first-child ~ .seen, .seen:first-child {
color: red;
}
.hidden:first-child ~ span.seen ~ span.seen {
color: black;
}
Working Fiddle

jQuery UI styled text input box

jQuery UI makes buttons look nice with $('button').button();.
Is there an equivalent for text input boxes?
There's nothing to stop you from doing $("input").button()... I like this:
$('input:text, input:password')
.button()
.css({
'font' : 'inherit',
'color' : 'inherit',
'text-align' : 'left',
'outline' : 'none',
'cursor' : 'text'
});
A fuller example.
Add the class ui-corner-all to your input and post-style the input with CSS.
$('input').addClass("ui-corner-all");
http://jsfiddle.net/TTShr/
I know this is old. But, if anyone is just looking to style their inputs to look more UIish, just add the following classes: $('input').addClass("ui-widget ui-widget-content ui-corner-all");
You could just hard code the classes too.
To sum things up I would like to add my implementation:
$('input:text, input:password, input[type=email]').button()
.addClass('ui-textfield')
.off('mouseenter').off('mousedown').off('keydown');
The CSS would be:
.ui-textfield {
font: inherit;
color: inherit;
background: none;
text-align: inherit;
outline: none;
cursor: text;
}
See it here: http://jsfiddle.net/UXdLQ/1544/
I had the same problem, I came up with the following solution. Use these classes on your input field:
ui-widget ui-state-default ui-corner-all
You may modify the padding - f.e. if you select elements on your site - to be unified.
jQuery UI v1.11.4
also add a .off('keydown') to Corin's answer to prevent the box from turning white when enter or space is pressed.
The example in your question cites jQuery UI's Button widget. The idea of this widget is to have a range of options including ease of theme-ing. There is a widget for input boxes too. Some of them that I'm aware of are as below:
Auto-Complete Widget
Default Text Plugin for input-box
Text Limit Plugin for input-box / text-area
There are many such plugins if not for widgets. You can always browse/search through at the search box available in the page http://plugins.jquery.com/
I liked the idea of simply adding the classes so much I wrote it as a jQuery plugin. Benifit here is if at some poitn in the future jQueryUI do a version it will most likely use the same format, so converting will be easy.
(function($)
{
$.fn.input = function ()
{
return this.each(function ()
{
$(this).addClass("ui-widget ui-widget-content ui-corner-all ui-button");
});
}
})(jQuery);
Call it like:
$('input, password').input();
If you wanted to add hover effects etc, just add the logic into
return this.each(function ()
{
// display logic
});
EDIT:
Added in additional class "ui-button" to make them the same height / padding etc as .button()
EDIT 2:
This turned out to be such a good idea I've carried on, adding a version for labels, and allowing custom CSS to be passed in.
// some styling for inputs
(function($)
{
$.fn.input = function (css)
{
if (!css)
css = {};
return this.each(function ()
{
$(this).addClass("ui-widget ui-widget-content ui-corner-all ui-button");
$(this).css(css);
});
}
})(jQuery);
// and labels
(function ($)
{
$.fn.label = function (css)
{
if (!css)
css = {};
return this.each(function ()
{
$(this).addClass("ui-widget ui-button");
$(this).css(css);
});
}
})(jQuery);
Then too style your inputs / labels. The class / styles of these don't actually need to exist anywhere.
$(".client-input").input();
$(".client-label").label({ "min-width": "125px", "text-align": "right" });
Outputs UI like this - with inputs and labels matching the style of the button. (Select's need work)
To have the same corners/font/padding/spacing as button, but without the button interactions (hover, active etc.)
HTML:
input type="text" class="ui-button ui-widget ui-corner-all"
if you want to align text add another custom class
CSS:
.textfield { text-align:left; }
HTML:
input type="text" class="ui-button ui-widget ui-corner-all textfield"

Resources