object-fit fallback solution? (AngularJS&ng-repeat) - angularjs

I've got an interesting compatability issue. Of course, object-fit: cover will not work on MS Edge and IE, so I've been trying to find a workaround for it. However, I can't seem to access an image created using ng-repeat via javascript.
I want to be able to edit the image styles from the controller, but querySelector('img') always returns null.
Heres the HTML:
<div class="js-image" id="danCarousel" style="height: 600px; width: 100%; background-color: grey;">
<!-- carousel image -->
<img ng-show="loaded" class="cimg {{fadeAnimation}}" ng-repeat="slide in slides"
ng-if="isCurrentSlideIndex($index)" ng-src="{{slide.src}}" style="position: absolute;
height: 100%; width: 100%; object-fit: cover; float: left; "/>
And here's the Javascript:
danApp.controller('indexController', function($scope, $document, $timeout, QueueService) {
$scope.state='index';
if('objectFit' in document.documentElement.style === false) {
console.log("This browser does not support object-fit");
//get the carousel image container
var carouselImages = document.getElementsByClassName('js-image');
for(var i=0; i < carouselImages.length; i++) {
console.log(i);
//get the image source url
var imageSrc = carouselImages[i].querySelector('img').getAttribute("ng-src");
console.log(carouselImages[i].querySelector('img'));
//hide the image
carouselImages[i].querySelector('img').style.display = "none";
//add background-size: cover
carouselImages[i].style.backgroundSize = 'cover';
//add in the background image src here
carouselImages[i].style.backgroundImage = 'url(' + imageSrc + ')';
//Add background-position: center center
carouselImages[i].style.backgroundPosition = 'center center';
}
console.log("Compatability settings added.");
}
else {
console.log('This browser supports object-fit');
}
Anyone know of a solution for this?

Use ng-class and either call a function in your controller to return the appropriate class name or add a class property to slide and reference it via ng-class.

Related

TypeError: The element or ID supplied is not valid. (videojs) Angular Ionic

I am trying to control a video player via videojs with in my ionic app. The code I have inside of my controller is:
$scope.$on('$ionicView.loaded', function() {
console.log('view loaded!!!');
if ($scope.post.media.length > 0) {
var myPlayer = null;
for (var i = 0; i < $scope.post.media.length; i++) {
videojs("bc-video-0").ready(function () {
myPlayer = this;
});
myPlayer.on('loadstart', function () {
console.log('well something happened');
})
}
}
});
where I use the life cycle event $ionicView.loaded to wait for all of the template code to be loaded onto the page. Then in my template file I have:
<div ng-repeat = "video in post.media | limitTo:videoLimit" class="video-box">
<!--limitTo:videoLimit |-->
<h3 class="video-title">{{video.title}}</h3>
<p ng-bind-html = "video.info"></p>
<!-- BRIGHTCOVE -->
<div style="display: block; position: relative; width: 100%;" >
<div style="display: block; position: relative; width: 100%;">
<div style="display: block; padding-top: 56.25%;" data-tap-disable="true">
<video
id="{{'bc-video-' + $index}}"
style="width: 100%; height: 100%; position: absolute; top: 0px; bottom: 0px; right: 0px; left: 0px;"
data-video-id=" {{video.file}}"
data-account="XXXXXXXXXX"
data-player="XXXXXXXXXX"
data-embed="default"
class="video-js"
controls="">
<source ng-src = "{{video.src | trusted}}">
</video>
</div>
</div>
</div>
<p style="display: none;">source: {{video.src}}</p>
</div>
but I keep getting the error:
TypeError: The element or ID supplied is not valid. (videojs)
When I inspect I see that the first video id is indeed bc-video-0, any idea on what I am missing?
Try enclosing your script inside the $timeout(). had the same issue.
Initializing player in ngAfterViewInit solved the issue for me
ngAfterViewInit() {
this.player = this.initPlayer(this.config, this.pid);
}

Ionic (or AngularJS) blocks google maps autocomplete

I'm just trying to add a simple autocomplete form to my Ionic app.
So first I tried this, it works fine.
I then tried in my app (in the browser first).
I put this in my controller, and called it with ng-init="initMaps()"
$scope.initMaps = function() {
var center = new google.maps.LatLng(51.514032, -0.128383);
var circle = new google.maps.Circle({
center: center,
radius: 50
});
var options = {componentRestrictions: {country: 'uk'}, types: ['geocode']}
var input = document.getElementById('autocomplete');
var autocomplete = new google.maps.places.Autocomplete(input, options);
autocomplete.setBounds(circle.getBounds());
console.log("maps loaded")
}
When I look at my console, I can see "maps loaded", and google warnings like:
Google Maps API warning: SensorNotRequired https://developers.google.com/maps/documentation/javascript/error-messages#sensor-not-required
I just added this line in my template form:
<input id="autocomplete" type="text" style="width: 200px;">
So, I think on a non-ionic (or angular) project it would work fine. But here, when I enter some letters, I don't get any result
Does Angular/Ionic create some interference here ? Am I forced to install other modules ?
Thanks !
Since Place Autocomplete is a part of Google Maps Places Library you probably forgot to include the loading of this library via libraries parameter, for example:
<script src="//maps.googleapis.com/maps/api/js?key={KEY}&libraries=places"></script>
Example
angular.module('ionic.example', ['ionic'])
.controller('MapCtrl', function ($scope) {
$scope.initMap = function () {
var center = new google.maps.LatLng(51.514032, -0.128383);
var circle = new google.maps.Circle({
center: center,
radius: 50
});
var options = { componentRestrictions: { country: 'uk' }, types: ['geocode'] }
var input = document.getElementById('autocomplete');
var autocomplete = new google.maps.places.Autocomplete(input, options);
autocomplete.setBounds(circle.getBounds());
}
google.maps.event.addDomListener(window, 'load', $scope.initMap);
});
.controls {
margin-top: 10px;
border: 1px solid transparent;
border-radius: 2px 0 0 2px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 32px;
outline: none;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
<script src="//maps.googleapis.com/maps/api/js?libraries=places"></script>
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
<div ng-app="ionic.example" ng-controller="MapCtrl">
<ion-header-bar class="bar-dark" >
<h1 class="title">Map</h1>
</ion-header-bar>
<ion-content>
<div id="map" data-tap-disabled="true"></div>
<input id="autocomplete" placeholder="Enter your address" class="controls" type="text"></input>
</ion-content>
</div>
Codepen

How to detect multi finger touch in ionic app

I am developing an Ionic app.In that I want to apply 1 finger swipe and 2 finger swipe and 3 finger swipe ( If it is possible ).
In a div if user swipes with single finger, it should scroll and
If user swipes with multi finger , it should select the content and select,copy options should be shown and 3 finger swipe for one more action.
edit:
I checked the question before posting this question.I am able to detect multi touch but not 2finger / 3 finger swipe. I am looking for any plugins for this actions.
Help me in this issue.
Look how 4-touch for reload is implemented in the Phonegap Developer App:
var currentTouches = {},
eventName = { touchstart: 'touchstart', touchend: 'touchend' };
if (window.navigator.msPointerEnabled) {
eventName = { touchstart: 'MSPointerDown', touchend: 'MSPointerUp' };
}
document.addEventListener(eventName.touchstart, function(evt) {
var touches = evt.touches || [evt],
touch;
for(var i = 0, l = touches.length; i < l; i++) {
touch = touches[i];
currentTouches[touch.identifier || touch.pointerId] = touch;
}
});
document.addEventListener(eventName.touchend, function(evt) {
var touchCount = Object.keys(currentTouches).length;
currentTouches = {};
if (touchCount === 4) {
evt.preventDefault();
window.location.reload(true);
}
}, false);
Hope this helps.
I am not quite sure but you might try adding a jQuery plugin
jGestures that enables you to add gesture events such as 'pinch', 'rotate', 'swipe', 'tap' and 'orientationchange' just like native jQuery events. Includes event substitution: a "tapone" event can be triggered by "clicking", a "swipe" by performing a swipe-ish mousegesture.
try this one for more https://codepen.io/edisonpappi/pen/LyqrXw
angular.module('ionicApp', ['ionic'])
.controller('MainCtrl', function($scope, $ionicGesture) {
$scope.messages = [];
var touchpad = angular.element(document.querySelector('#touchpad'));
var maxFingers = 10;
var fingers = [];
for(var i=0; i<maxFingers; i++) fingers.push(angular.element(document.querySelector('#t'+i)))
$scope.touches = new Array;
var resetTransformations = function(){
for(var i=0;i<maxFingers;i++)
fingers[i].css({"transform": "translate3D(0px, 0px, 0px)"});
}
$ionicGesture.on('dragstart',
function (event) {
$scope.messages.push({txt: "dragstart"});
}, touchpad);
$ionicGesture.on('dragend',
function (event) {
$scope.messages.push({txt: "dragend"});
}, touchpad);
$ionicGesture.on('transformstart',
function (event) {
$scope.messages.push({txt: "transformstart"});
}, touchpad);
$ionicGesture.on('transformend',
function (event) {
$scope.messages.push({txt: "transformend"});
}, touchpad);
// keep track if a finger is released:
var fingersDown = 0;
// drag = 1 finger, transform = more
$ionicGesture.on('transform drag',
function (event) {
if(fingersDown > event.gesture.touches.length)
resetTransformations();
fingersDown = event.gesture.touches.length;
$scope.touches = [];
var identifier = 0;
for(var i=0; i<event.gesture.touches.length; i++){
identifier = parseInt(event.gesture.touches[i].identifier);
$scope.touches[i] = {pageX: parseInt(event.gesture.touches[i].pageX), pageY: parseInt(event.gesture.touches[i].pageY), id: identifier};
fingers[identifier].css({"transform": "translate3D("+event.gesture.touches[i].pageX+"px, "+event.gesture.touches[i].pageY+"px, 0px)"});
}
$scope.$apply();
}, touchpad);
$ionicGesture.on('release',
function (event) {
$scope.touches = [];
$scope.$apply();
$scope.messages.push({txt: "release"});
resetTransformations();
}, touchpad);
$ionicGesture.on('touch',
function (event) {
$scope.messages.push({txt: "touch"});
}, touchpad);
});
body {
cursor: url('http://ionicframework.com/img/finger.png'), auto;
}
.full{
width: 100%;
height: 100%;
}
h4.full{
color: #FFF;
position: absolute;
top: 0px;
left: 0px;
z-index: 10;
}
.debug{
color: #fff;
padding-left: 10px;
font-size: 12px;
line-height: 12px;
}
.circle{
position: absolute;
color: #fff;
top: -44px;
left: 0px;
margin-left: -30px;
margin-top: -30px;
width: 60px;
height: 60px;
border-radius: 30px;
background: rgba(255,255,255,0.62);
}
#container{
padding-top: 38%;
z-index: 1;
position: absolute;
background: url("https://unsplash.imgix.net/46/yzS7SdLJRRWKRPmVD0La_creditcard.jpg?q=75&fm=jpg&s=7cc01cbdd45363cc0e2e8340b185bca2");
background-size: cover;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
}
<html ng-app="ionicApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>VELOCITY + IONIC</title>
<!-- add touch emulation hold SHIFT-key while using the mouse -->
<script src="http://cdn.rawgit.com/hammerjs/touchemulator/master/touch-emulator.js"></script>
<script>TouchEmulator();</script>
<link href="//code.ionicframework.com/1.0.0-beta.13/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/1.0.0-beta.13/js/ionic.bundle.js"></script>
</head>
<body ng-controller="MainCtrl">
<ion-header-bar class="bar-positive">
<h1 class="title">TRACKING MANY FINGERS</h1>
</ion-header-bar>
<ion-content class="full" scroll="false">
<h4 id="touchpad" class="full padding">Drag below with > 1 fingers.<br />Press and hold Shift + mouse key to emulate multitouch on a computer.</h4>
<div class="full world padding">
<div id="container">
<div class="debug" ng-repeat="touch in touches">
touches[{{$index}}] = FINGER <strong>{{touch.id}}</strong>: ({{touch.pageX}}, {{touch.pageY}})
</div>
<div class="debug" ng-repeat="msg in messages">{{msg.txt}}</div>
<div id="t0" class="circle">0</div>
<div id="t1" class="circle">1</div>
<div id="t2" class="circle">2</div>
<div id="t3" class="circle">3</div>
<div id="t4" class="circle">4</div>
<div id="t5" class="circle">5</div>
<div id="t6" class="circle">5</div>
<div id="t7" class="circle">7</div>
<div id="t8" class="circle">8</div>
<div id="t9" class="circle">9</div>
</div>
</div>
</ion-content>
</body>
</html>

onsen-ui gestures not working

I need to implement a menu with the exact same looks as onsen sliding-menu,but that slides from top. I was thinking to use onsen gestures to be able to drag the menu, but the gestures sample provided in the onsen guide does not work. Am I missing something?
<ons-gesture-detector>
<div id="detect-area" style="width: 300px; height: 300px;background-color:blue;">
Swipe Here
</div>
</ons-gesture-detector>
<script>
alert("in");
$(document).on('swipeleft', '#detect-area', function() {
alert("swipe");
})
</script>
Try this, it should work. Don't forget to add jquery first.
<ons-gesture-detector style="height: 300px; margin: 50px 50px;">
<div id="hoge" style="border: 1px solid #ccc; background-color: #f9f9f9; width: 100%; height: 300px; line-height: 300px; text-align: center; color: #999;">
...
</div>
</ons-gesture-detector>
<script>
var eventName =
'drag dragleft dragright dragup dragdown hold release swipe swipeleft swiperight ' +
'swipeup swipedown tap doubletap touch transform pinch pinchin pinchout rotate';
$(document).on(eventName, '#hoge', function(event) {
if (event.type !== 'release') {
$(this).text(event.type);
}
});
</script>

AngularJS directives with HTML5 drag and drop -- issue with scope object

I'm fairly new to angular and I'm having a hard time wrapping my head around where the items are being pushed to. I am not sure if I am correctly setting up the functions to be used with drag/drop and if its getting bound to an older scope object and the ng-repeat isn't being updated properly. I'm thinking there is some slight issue with the way I have this setup. Any pointers or help would be much appreciated.
What should happen is when you drag a color from the Draggable container into the Droppable container it should update the text which is linked to the scope object items. I am successfully pushing an item onto the scope object but ng-repeat isn't picking it up. I am not sure if I need a watch or what to do to get it to pay attention to the newly added items.
JS Fiddle Here: http://jsfiddle.net/RV23R/
HTML CODE:
<div ng-app="my-app" ng-controller="MainController">
<div class="container">
<header><h1>Draggables</h1></header>
<section>
<div draggable="true" ng-repeat="drag_type in drag_types">{{drag_type.name}}</div>
</section>
</div>
<div class="container">
<header><h1>Drop Schtuff Here</h1></header>
<section droppable="true">
<div><span>You dragged in: </span><span ng-repeat="items in items">{{item.name}},</span></div>
</section>
</div>
ANGULAR CODE:
var module = angular.module('my-app', []);
module.directive('draggable', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element[0].addEventListener('dragstart', scope.handleDragStart, false);
element[0].addEventListener('dragend', scope.handleDragEnd, false);
}
}
});
module.directive('droppable', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element[0].addEventListener('drop', scope.handleDrop, false);
element[0].addEventListener('dragover', scope.handleDragOver, false);
}
}
});
function MainController($scope)
{
$scope.drag_types = [
{name: "Blue"},
{name: "Red"},
{name: "Green"},
];
$scope.items = [];
$scope.handleDragStart = function(e){
this.style.opacity = '0.4';
e.dataTransfer.setData('text/plain', this.innerHTML);
};
$scope.handleDragEnd = function(e){
this.style.opacity = '1.0';
};
$scope.handleDrop = function(e){
e.preventDefault();
e.stopPropagation();
var dataText = e.dataTransfer.getData('text/plain');
$scope.items.push(dataText);
console.log($scope.items);
};
$scope.handleDragOver = function (e) {
e.preventDefault(); // Necessary. Allows us to drop.
e.dataTransfer.dropEffect = 'move'; // See the section on the DataTransfer object.
return false;
};
}
CSS (if anyone cares)
.container {
width: 600px;
border: 1px solid #CCC;
box-shadow: 0 1px 5px #CCC;
border-radius: 5px;
font-family: verdana;
margin: 25px auto;
}
.container header {
background: #f1f1f1;
background-image: -webkit-linear-gradient( top, #f1f1f1, #CCC );
background-image: -ms-linear-gradient( top, #f1f1f1, #CCC );
background-image: -moz-linear-gradient( top, #f1f1f1, #CCC );
background-image: -o-linear-gradient( top, #f1f1f1, #CCC );
box-shadow: 0 1px 2px #888;
padding: 10px;
}
.container h1 {
padding: 0;
margin: 0;
font-size: 16px;
font-weight: normal;
text-shadow: 0 1px 2px white;
color: #888;
text-align: center;
}
.container section {
padding: 10px 30px;
font-size: 12px;
line-height: 175%;
color: #333;
}
There are a couple of typos in the fiddle, but the basic problem is that your drag events are outside an angular digest cycle. You should wrap your changes in $scope.$apply (code sample coming). This forked and bugfixed (FIDDLE) shows that when you click the button, angular shows the changes and refreshes the display with new values.
Fix: (FIDDLE)
$scope.$apply(function() {
$scope.items.push(dataText);
});
A bug you had is in this code:
<span ng-repeat="items in items">{{item.name}},</span>
This should probably be ng-repeat="item in items", also items only contains the dropped text so it is an array of strings and not the original item objects.

Resources