Wrapping Formstone Wallpaper jquery plugin in an AngularJS directive - angularjs

Trying hard to implement the Formstone Wallpaper JQuery plugin into my AngularJS application. I followed the instructions on the site just to learn that AngularJS and JQuery don't work well together. In many articles in the net it was mentioned that I had to wrap jquery plugins in AngularJS directives to use it the right way. I found this tutorial by David Boike on how to warp the Knob jquery plugin into an AngularJS directive.
I tried to follow along and achieve that for the Formstone Wallpaper plugin. This is my attempt:
'use strict';
angular.module('app').directive('formstoneWallpaper',[function() {
return {
restrict: 'E',
link: function (scope, elem, attrs) {
elem.wallpaper({
source: {
poster: attrs.poster,
mp4: attrs.mp4,
ogg: attrs.ogg,
webm: attrs.webm
}
});
}
};
}]);
Then my html markup changes to:
<div class="container-fluid">
<div class="row wall">
<formstone-wallpaper
poster="modules/launch/videos/ocean.jpg"
mp4="modules/launch/videos/ocean.mp4"
ogg="modules/launch/videos/ocean.ogv"
webm="modules/launch/videos/ocean.webm"
></formstone-wallpaper>
</div><!--row-->
</div><!--container-->
Yet this does not result in the desired full-width responsive video wallpaper. Instead the width and height is somehow set to 0px. I therefore do not see anything on my website. However, when I kill the wallpaper-container and wallpaper-media classes, the problem is partially resolved in that the video finally appears (however, it is not responsive and fittet to screen size-the reason why we are doing this exercise in the first place). Here is a screenshot from my chrome inspector.
Can someone help me to improve the code for the directive?

friends, it turned out the above directive is actually alright. The real problem that I had was my lack of understanding of nested relative positioning. I used this "resize" directive to dynamically set the height of my container to the height of the viewport.
This is the css that finally fixes the my issue:
formstone-wallpaper {
display: block;
position: relative;
width: auto;
height: auto;
padding: 100px 0;
min-height: 100%;
background: no-repeat center center;
background-attachment: scroll;
background-size: cover;
}
Set the "resize" attribute on your container like so:
<div class="container-fluid" data-ng-style="style()" resize>
<div class="row">
<formstone-wallpaper
poster="modules/launch/videos/ocean.jpg"
mp4="modules/launch/videos/ocean.mp4"
ogg="modules/launch/videos/ocean.ogv"
webm="modules/launch/videos/ocean.webm"
></formstone-wallpaper>
</div><!--row-->
</div><!--container-->

Related

AngularJS UI Grid and Popover alignment

Hi I'm adding a popover to UI grid in AngularJS. The idea is when the user mouse-over a row a popover will show up, and the popover contains a directive. I've successfully implemented this part, but now the problem is that part of the popover is blocked by the ui grid table, like this:
I want to bring the popover to the front, and I've tried setting z-index for both the ui grid table and the popover. Related code is here:
JS part:
function rowTemplate() {
var template = [];
...
template.push('popover-template="\'popover.html\'" popover-placement="bottom" popover-trigger="click"></div>');
return template.join(' ' );
}
HTML:
<div class="gridStyle" ui-grid="vm.grid" ui-grid-resize-column ui-grid-selection style="margin-top:0px; height:200px; z-index: 4; position: relative">
</div>
<script type="text/ng-template" id="popover.html">
<div style="height: 150px; width: 600px; overflow-x: auto; overflow-y: hidden; z-index: 10; position: relative">
<directive-related part />
</div>
</script>
But after I set the z-index it's still not working. How can I resolve this?
Some of my references are here: popover: popover, z-index: z-index.
Thanks!
Note: I am making the assumption here that you are using ui-bootstrap.
I have found that usually you need to use the append-to-body attribute with ui-grid custom formats.
Try changing the template like so to add that attribute:
template.push('popover-template="\'popover.html\'" popover-append-to-body="true" popover-placement="bottom" popover-trigger="click"></div>')

Angular Bootstrap - Tooltip not showing

I have a simple form that is inside Angular UI Bootstrap's tabs. Form controls have tooltips associated with them to show errors. I'm using custom event that will toggle tooltip visibility.
The idea is to have tooltip visible on required fields.
With UI-Bootstrap version 1.3.2 and Angular 1.4.8 everything is working fine but since I upgraded to Angular 1.5.3 tooltip is not showing anymore. It will show once I actually type something in the text field and delete it which makes me believe that now requires the model to be initialized.
I have here two plunks that will show exactly what is going on:
Working plunk (with angular 1.4.8) - https://plnkr.co/edit/IkuOdCrcFJ8lBeNA5sSh
<data-uib-tabset>
<data-uib-tab>
<data-uib-tab-heading>Tab 1</data-uib-tab-heading>
<form name="testform">
<input type="text" name="test" id="test"
data-ng-model="test"
data-ng-required="1"
data-tooltip-append-to-body="true"
data-tooltip-placement="right"
data-uib-tooltip="Required!"
data-tooltip-trigger="none"
data-tooltip-is-open="testform.test.$error.required" />
</form>
</data-uib-tab>
<data-uib-tab>
<data-uib-tab-heading>Tab 2</data-uib-tab-heading>
Content 2
</data-uib-tab>
</data-uib-tabset>
Not so working plunk (with angular 1.5.3) - https://plnkr.co/edit/Wl3Bq13FKPnqW7RqwfiJ
I noticed as mentioned in the comments that there is a class being attached - uib-position-measure. It has 3 styles that are causing the issue:
top: -9999px !important
left: -9999px !important
visibility: hidden !important
EDIT - I'm reorganizing my post now that I've dug pretty deep into this. Still don't think I have a great solution, but at least have some info and options.
Solution 1
Simply remove the culprit class uib-position-measure with javascript and then adjust the top and left styles on .tooltip.
Plunker
window.onload = function() {
var tooltip = document.getElementsByClassName('tooltip')[0];
tooltip.className = tooltip.className.replace(/\buib-position-measure\b/,'');
}
.tooltip {
top: 42px;
left: 150px;
}
Solution 2
Overwrite the styling that is causing the issue with javascript.
Plunker
<script type="text/javascript">
window.onload = function() {
var tooltip = document.getElementsByClassName('tooltip')[0];
tooltip.setAttribute("style", "visibility: visible !important; top: 42px !important; left: 150px !important;");
}
</script>
Solution 3
I was able to find where the .uib-position-measure class is created in the ui-bootstrap.js file. I removed !important from the visibility, top and left. After that I was able to fix the issue using css on the .tooltip class.
Plunker
ui-bootstrap.js is the file I created, copied the original over, and modified the uib-position-measure class - it is at the bottom on line 7327.
In style.css I simply added the below:
.tooltip {
visibility: visible;
top: 42px;
left: 150px;
}
Related Issue
I was also able to find an issue on GitHub related to this - https://github.com/angular-ui/bootstrap/pull/5530
Someone removed some inline styles and added them as a class, so that they could be overwritten by CSS instead of using javascript. This may be the best way to handle it - https://github.com/angular-ui/bootstrap/pull/5530/commits/44643775dece535b3ffa62d7edae86eaa12ac154. The problem is finding the location of the uib-position-measure inline styling and handling it the same way.
Using popover-popup-delay repositions the element and the class uib-position-measure is no longer active on it.

Styling text color in angularjs at runtime

I have a html page with this code
<p id="roonnameDiv" >{{chatRoom}}</p>
and an app.js with the following code . It reflects the value corrrectly but if I try to style it with color at runtime it doesnt not reflect on the html page
$scope.$parent.chatRoom = $stateParams.roomId;
$scope.$parent.chatRoom.style = {"color":"green"};
I even tried using ng-color but in vain . Have head using html-unsafe tags t add html5 code to angular variables at runtime , perhaps I could use that to provide style of element but could not find any examples .
Essentially the requirement is of having various styled ( color ,size and fonts ) in roonnameDiv using angular framework
..................Edit .............................
I used the ngstyle as suggested by answers below
$scope.$parent.chatRoom = $stateParams.roomId;
$scope.myStyle = {color: "green"};
however the output text was just plain grey . On exploring it thorugh chorome inspector , I found it is inheriting some styles through body.
Switching off the body color tag just turns the text black instead of green .
Following is the body
<body ng-app="xyz" ng-controller="AppController" class="ng-scope">
This is the body style
body {
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 14px;
line-height: 1.42857143;
color: #333;
background-color: #fff;
}
I want specific style class to apply for different text components without affetcting the overall body style . Could you suggest how to do so ?
You can use ng-style directive.
In Markup
<p id="roonnameDiv" ng-style="myStyle">{{chatRoom}}</p>
In controller
$scope.myStyle = {color: "green", background: "blue"} // Write all the required styles here.
More on ng-style directive at: https://docs.angularjs.org/api/ng/directive/ngStyle
try this
<p id="roonnameDiv" ng-style="chatRoom.style" >{{chatRoom}}</p>

How to implement a flip over effect using AngularJS animations?

What would be the best way to achieve a flip over effect using AngularJS animations?
I would like the flip over effect to occur on click. Every time it's clicked, it should flip over to the other side.
Ideally, I guess, I'm looking for a directive implementation that uses Angular animations.
PLNKR - here is a seed of a configurable angular directive that provides 3d flipping functionality. I do not see any good reason why to use ngAnimate for it.
basic usage
<flip flip-width="200px" flip-height="100px">
<flip-panel>
content-front
</flip-panel>
<flip-panel>
content-back
</flip-panel>
</flip>
Comments
It appends css-styles on its own, to be fully independent.
In a proper, generic directive all names should be configurable.
flip-width and flip-height sets style of flip and both flip-panels.
Directive makes some basic check, if both front and back are set.
First flip-panel is front and the second is back.
Due to usage of transclusion content of the flip-panel may be arbitrary html. (you are right Misha no transclusion needed)
It only works in -webkit. (update to make it work in Firefox, just duplicate all pieces with -webkit with no prefix - you do not need -moz)
UPDATE
PLNKR - here is an updated and extended version. It shows what I meant by making the directive configurable. In more details:
Introduced flipConfig via provider, that allows to set in app.config:
default dimensions
css class names
speed of the transition
if the flip action is triggered by a click on the panel
Introduced flip-show attribute that specifies which side to show.
Changing flip-show we can trigger the flip action from outside of the directive.
It works in Firefox and [almost:-)] in IE11.
(btw: it is just a seed and it may be improved in a lot of ways. E.g: specifying axis, specifying origin of the transform, specifying radius and margin of the panels, allowing flip on hover, defaults colors, margins and so on)
I had the same usecase just recently for an angular memory game.
My implementation is the same by the idea of the other answers. I also released the flipping code along with a DEMO.
Github: https://github.com/zwacky/angular-flippy
P.s.: Looks i'm late to the party ;)
You can use ng-click and ng-class to add a class when the flip container is clicked.
<div class="flip-container" ng-click="flip = !flip" ng-class="{'flip': flip}">
<div class="flipper">
<div class="front" style="background: lightblue;">
front
</div>
<div class="back" style="background: lightgreen;">
back
</div>
</div>
</div>
This is essentially the angular way of doing what Walsh suggested in his article:
Adding the flip class to the container element will flip the card using JavaScript -- no user hover required. A JavaScript comment like document.querySelector("#myCard").classList.toggle("flip") will do the flip!
The only change to David Walsh's css was removing the :hover selector - the html structure is unchanged. It works nicely in chrome and firefox.. but the flip isn't as pretty in IE.
Here is a working demo: http://plnkr.co/edit/0dn775vpuoOeh2PS1T6k?p=preview
Update
I created a simple directive to encapsulate this basic technique. It allows you to flip over a black card, to reveal a picture on the other side.
app.directive("flipReveal", function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'template.html',
scope: {
url: '=',
flip: '='
}
}
})
Here is a link to a new demo: http://plnkr.co/X4pSav
Disclaimer Based on #artur's answer https://stackoverflow.com/a/23139242/1319998 , but hopefully both simplified and made more flexible.
A custom directive is the way to go, one that can be used as:
<flip flip-side="{{side}}">
<flip-front>
Front side contents
</flip-front>
<flip-back>
Rear contents
</flip-back>
</flip>
I think it should have certain properties:
Programatically controlled by an attribute. In this case, a string that is equal to 'front' or 'back'
<flip flip-side="{{side}}">....</flip>
this would allow programmatic access via the surrounding scope.
Integrated with ngAnimate/$animate. Specifically, if ngAnimate is removed or disabled, the animation should not occur, but the reveal of the other side happen immediately. Using $animate.addClass/$animate.removeClass would achieve this, adding/removing a flip-visible class together with display:block and display:none styles to make sure the right side is visible/hidden when the animations are disabled.
flip > flip-front, flip > flip-back {
display: none;
}
flip > .flip-visible {
display: block;
}
Controlled by CSS, with defaults. So if you want to change the duration of the flip, it's a CSS, and not a Javascript, addition.
So it will have a style sheet to add styles required for the various stages of $animate.addClass / $animate.removeClass CSS animations explained at Year of Moo and $animate docs . The class will be flip-visible, so the extra classes will be .flip-visible-add, .flip-visible-add-active, .flip-visible-remove, and .flip-visible-remove-active classes.
The full set of styles can be seen at http://plnkr.co/edit/bbYbMhiURnm6FqC9patp?p=preview, but the main construction is of the form:
.flip-visible-add {
// Initial setup: time and initial, pre-animation, transform
}
.flip-visible-add.flip-visible-add-active {
// Target transform
}
Putting all this together, the directive is quite short:
app.directive("flip", function($animate) {
return {
restrict : "E",
controller: function($scope, $element, $attrs) {
var elements = {
'front': $element.find('flip-front'),
'back': $element.find('flip-back')
};
$attrs.$observe('flipSide', function(visibleSide) {
visibleSide = visibleSide || 'front';
var otherSide = visibleSide == 'front' ? 'back' : 'front';
$animate.removeClass(elements[otherSide], 'flip-visible');
$animate.addClass(elements[visibleSide], 'flip-visible');
});
}
}
});
This can all be seen in an example, together with the stylesheets to make it all work, at http://plnkr.co/edit/bbYbMhiURnm6FqC9patp?p=preview
I realise there is a benefit to not integrating with the $animate service, and having a purely class-based solution.
If you use $animate with addClass and removeClass, but interrupt the animation (say, by clicking quickly and repeatedly on the element), the animation will 'jerk' to its end/starting point, and then animate from that position, at least on Chrome. Using a pure CSS solutions avoids this issue, and always animates from the exact current point, giving a smoother effect.
An added benefit is the solution is also simpler, and you don't need a custom directive.
For example, the HTML can be as follows:
<flip class="{{side === 'front' ? 'flip-front' : 'flip-back'}}">
<flip-front>
Front side contents
</flip-front>
<flip-back>
Rear contents
</flip-back>
</flip>
I use custom elements, but they don't need to have any directives attached: they are just for CSS to hook into:
flip > flip-front, flip > flip-back {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* Time can be overriden */
transition: -webkit-transform 0.5s;
transition: transform 0.5s;
}
/* Front visible */
flip > flip-front {
-webkit-transform: perspective(800px) rotateY(0);
transform: perspective(800px) rotateY(0);
}
flip > flip-back {
-webkit-transform: perspective(800px) rotateY(180deg);
transform: perspective(800px) rotateY(180deg);
}
/* Back visible */
flip.flip-back > flip-front {
-webkit-transform: perspective(800px) rotateY(-180deg);
transform: perspective(800px) rotateY(-180deg);
}
flip.flip-back > flip-back {
-webkit-transform: perspective(800px) rotateY(0);
transform: perspective(800px) rotateY(0);
}
This can be seen in a demo at http://plnkr.co/edit/A7IeGa1JEsZishmTDTaK?p=preview
I would simply add / remove a class on click.
If you want to hook into the angular animation system then take a look at the $animate service, in particular add/remove/setClass(). The service is usually used in directives. You might want to create a directive that reacts on a click event and triggers the animation. You even get informed when the animation has completed.
Chances are that it's not worth it ;)
You are going to want to create 3 divs.
<div class="wrapper">
<div class="front"></div>
<div class="back"></div>
</div>
You then position back behind front using z-index, and flip it upside down using rotateX (-180deg or so). Set a transition on wrapper as well.
Then, on click of wrapper, rotateX(+180deg). This will pretty much infinitely flip it over.
** Update: For angular, bind to click and use setClass to toggle between two classes on wrapper, one at rotateX(0deg) , the other at rotateX(180deg)
Here is a slightly modified version of artur's answer:
DEMO
angular.module('FlipDemo', []).directive("flip", function() {
return {
restrict : "A",
scope: true,
link: function(scope, element) {
var $panels = element.css({ position: 'relative' }).children().addClass("flip-panel");
var frontPanel = $panels.eq(0);
var backPanel = $panels.eq(1);
scope.showFrontPanel = function() {
frontPanel.removeClass("flip-hide-front-panel");
backPanel.addClass("flip-hide-back-panel");
};
scope.showBackPanel = function() {
backPanel.removeClass("flip-hide-back-panel");
frontPanel.addClass("flip-hide-front-panel");
};
scope.showFrontPanel();
}
}
});
.flip-panel {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-webkit-transition: -webkit-transform .4s;
-moz-transition: -moz-transform .4s;
-webkit-transform: perspective(800px) rotateY(0deg);
-moz-transform: perspective(800px) rotateY(0deg);
}
.flip-hide-back-panel {
-webkit-transform: perspective(800px) rotateY(180deg);
-moz-transform: perspective(800px) rotateY(180deg);
}
.flip-hide-front-panel {
-webkit-transform: perspective(800px) rotateY(-180deg);
-moz-transform: perspective(800px) rotateY(-180deg);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.1/angular.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app="FlipDemo">
<div style="width: 100px; height: 150px">
<div flip style="width: 100%; height: 100%">
<div style="background-color: green">
<div>Front</div>
<button ng-click="showBackPanel()">Show Back</button>
</div>
<div style="background-color: blue">
<div>Back</div>
<button ng-click="showFrontPanel()">Show Front</button>
</div>
</div>
</div>
<br>
<div style="width: 150px; height: 100px">
<div flip style="width: 100%; height: 100%">
<div style="background-color: green">
<div>Front</div>
<button ng-click="showBackPanel()">Show Back</button>
</div>
<div style="background-color: blue">
<div>Back</div>
<button ng-click="showFrontPanel()">Show Front</button>
</div>
</div>
</div>
</body>
</html>
Main differences:
Works in Chrome and Firefox.
More flexibility with when the flip happens.
Just one directive rather than two. Less code.
I took the CSS outside of the directive for clarity sake.

Adding border-radius to a map

I have a website running on a mapping platform called Ushahidi. The default template is quite boxy so I was fiddling with the CSS and rounding everything off using border-radius.
It has helped with other elements but the map is such a square it won't ease up!
It might be that it's not possible, wondered if anyone here had any experience of this. The html using inspect element and view source are different. Not sure what this means exactly but guessing that the html is pulled in by the map provider?
Here is the html on view source:
<div class="map " id="map"></div>
<div style="clear:both;"></div>
<div id="mapStatus">
<div id="mapScale"></div>
<div id="mapMousePosition"></div>
<div id="mapProjection"></div>
<div id="mapOutput"></div>
</div>
I've added a screen of inspect element HTML too. Looks like it's using "Open Layers". I've heard of that but don't fully understand whats going on.
Is it possible to round the edges of my map? Here is the site if that helps: http://tinyurl.com/c8djrvr
Apply the border-radius to two layers.
CSS
div.map {
border: #999 1px solid;
width: 800px;
height: 366px;
position: relative;
height: 650px;
border-radius: 25px; /* ADD THIS */
}
#OpenLayers_Map_11_OpenLayers_ViewPort {
border-radius: 25px; /* ADD THIS */
}
It works. Use however many pixels you want. I used 25px.
I would suggest more general and safer CSS selectors (since ID #OpenLayers_Map_11_OpenLayers_ViewPort is generated by OpenLayers and it's value is unpredictable; and OL 2.12 and older produce ID's, that contain dot and are therefore unsuitable for CSS selectors):
.olMap, .olMapViewport {
border-radius: 25px;
}

Resources