Canvas content disappears on Chrome 49 on Mac with an AngularJS tooltip - angularjs

The problem I have - the content of an HTTP canvas disappears, when I have a tooltip on a button that opens a new tab.
This is a very specific symptom, so I'd try to walk you through it.
I'm able to reproduce it with the following HTML, but not in a plunker or jsfiddle unfortunately:
<html>
<head>
<style>
.container {
height: 300px;
width: 300px;
}
canvas {
border: 1px solid black
}
button {
margin-top: 15px;
}
</style>
</head>
<body ng-app="CanvasTooltipApp">
<div ng-controller="CanvasTooltipCtrl" class="container">
<canvas id="myCanvas" height="300"></canvas>
<button type="button" ng-click="clickMe()" tooltip="The Tooltip Text">Click Me</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.js"></script>
<script>
angular.module('CanvasTooltipApp', ['ui.bootstrap']);
angular.module('CanvasTooltipApp').config(function($tooltipProvider) {
$tooltipProvider.options({popupDelay: 1500});
});
angular.module('CanvasTooltipApp').controller('CanvasTooltipCtrl', function($scope) {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();
$scope.clickMe = function() {
window.open('http://www.google.com', '_blank');
};
});
</script>
</body>
</html>
It is reproduced only on Chrome 49 on a Mac.
To reproduce: click on the button (before the tooltip appears!), a new tab would be opened. Wait a few secs. Perhaps open another new tab. Then close all tabs and go back to the original tab. The shape of the canvas should disappear.
I use AngularJS 1.3.15 and angular-ui-bootstrap 0.14.3.
It does not seem to be reproduced with a plain bootstrap tooltip.
Only with the angular-ui-bootstrap it is reproduced.
Upgrading the angular-ui-bootstrap version does not help.
It is not reproduced on other browsers, or on other OSs.
That's it, I think.
I hope you even succeed in reproducing it without a plunker/fiddle.
Thank you very much in any case!
Daniel

I've hit this myself, though in slightly different circumstances (Canvas disappearing on Chrome 49 on OS X, looks like a bug), and have a plunker:
https://plnkr.co/edit/z4x9i8qqfjTOJDxihaG4
Windowed mode (where the symptom manifests):
https://run.plnkr.co/gl9nbHY1044dEJUI/
HTML:
<div>
<div>
<input type="number" class="form-control" placeholder="Focus here" />
</div>
<div>
<div>
<canvas id="line" class="chart chart-line" chart-data="data" chart-labels="labels" chart-legend="true" chart-series="series">
</canvas>
</div>
</div>
</div>
Looks like the same issue. I've filed a Chrome bug report.

Related

How to test AngularJs with protractor, contenteditable with 'bold' modifier, broken since webdriver update

Consider this AngularJs app
<!DOCTYPE html>
<html>
<head>
<title>
AngularJs insert text after bold checked
</title>
<script src="lib/angular/angular.js"></script>
<script type="text/javascript">
var app = angular.module('ngTestBoldInsert', []);
app.controller('ngCtrl', function ($scope) {
$scope.boldButtonClicked = function () {
document.execCommand('bold', false, null);
};
});
</script>
</head>
<body>
<div ng-app="ngTestBoldInsert" ng-controller="ngCtrl">
<h2>Edit text after click on checkbox</h2>
<label for="boldButtonId">Bold</label>
<input id="boldButtonId" type="checkbox" ng-change="boldButtonClicked()" ng-model="boldStatus">
<br /><br />
<div id="textFrame" contenteditable="true" style="padding:10px; border:1px solid black; width:30%; ">text</div>
</div>
<p>Manual: click on edit frame, input text, Click on 'bold' checkbox. click on edit frame, input some text. Now the text is bold. <br /><br />Please note that this is a simplification, in real application the bold button status is synced with the status of the text but that would make this example very complicated.</p>
</body>
</html>
And this protractor test:
'use strict';
describe('text editor', function() {
var textFrame = element(by.id('textFrame'));
var boldCheckbox = element(by.id('boldButtonId'));
it('should insert normal text', function() {
browser.get('index.html#!/');
var text = textFrame.getText();
expect(text).toBe('text');
textFrame.click();
textFrame.sendKeys(' plus normal text');
text = textFrame.getText();
expect(text).toBe('text plus normal text');
var html = browser.executeScript("return arguments[0].innerHTML;", textFrame);
expect(html).toBe('text plus normal text');
});
it('should insert bold text', function() {
boldCheckbox.click();
textFrame.click();
textFrame.sendKeys('plus bold text');
var text = textFrame.getText();
expect(text).toBe('text plus normal textplus bold text');
var html = browser.executeScript("return arguments[0].innerHTML;", textFrame);
expect(html).toBe('text plus normal text<b>plus bold text</b>');
});
});
This test works until chromedriver_76.0.3809.68
and is broken in chromedriver_77.0.3865.40
caused by webdriver update: https://bugs.chromium.org/p/chromedriver/issues/detail?id=2704
Text is no longer bold in the test.
output of the test:
Expected 'text plus normal textplus bold text' to be 'text plus normal text<b>plus bold text</b>'.
How to test this now?
First of all, try element.getAttribute("innerHTML")
If doesn't help, do element.getAttribute("outterHTML") it will return you a string like <div id="textFrame" contenteditable="true" style="padding:10px; border:1px solid black; width:30%; ">text plus normal text<b>plus bold text</b></div>, so then just do expect(html).toContain('text plus normal text<b>plus bold text</b>');
In worst case scenario, if you don't want to go this route, you have no options but to report a bug with chromedriver team, which I would suggest to do anyway, since its community driven effort
use actions as mentioned by the w3c/webdriver team
https://github.com/w3c/webdriver/issues/1469
actions api: https://w3c.github.io/webdriver/#actions
instead of textFrame.click() and textFrame.sendKeys
use
code:
browser.actions().click(textFrame).sendKeys('text plus normal textplus bold text').perform();

How to show a progress bar in AngularJS

i'm kind of new using AngularJs framework and i am not that good in English. so i hope somebody can help me solve my problem and never mind my grammar hehe. i know mostly of progress bar in angularjs triggered by ng-show, but what if i want to put a progress bar before an object tag loads. for example
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="70"
aria-valuemin="0" aria-valuemax="100" style="width:70%">
<object width="400" height="400" data="file.pdf"></object>
</div>
</div>
let assume that that "file.pdf" is being fetch from the server. that being said it needs time to load, so i want to put a progress bar on that time while the data if being fetch from the server and hide it when the object is fully loaded thank you guys.
data flow example :
(file.pdf) ----Fetching---- [controller]----Progress bar--View(html)
Hope this will help you out. This is a basic example for showing and hiding a spinner bar on button click.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Welcome to LearnKode - A code learning platform</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
<style>
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
margin: 0 auto;
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
html, body, container {
height: 100%;
width: 100%;
margin: 0;
}
</style>
</head>
<body ng-app="changeExample">
<div class="container" ng-controller="ExampleController">
<button class="btn" ng-click="ShowSpinner()">Show Spinner</button>
<button class="btn" ng-click="HideSpinner()">Hide Spinner</button>
<div ng-if="ShowSpinnerStatus" class="loader"></div>
</div>
<script>
var app = angular.module("changeExample", []);
app.controller('ExampleController', ['$scope', function ($scope) {
$scope.ShowSpinnerStatus = true;
$scope.ShowSpinner = function(){
$scope.ShowSpinnerStatus = true;
};
$scope.HideSpinner = function(){
$scope.ShowSpinnerStatus = false;
};
}]);
</script>
</body>
</html>
You can show and hide the spinner on a service call like this.
$scope.ShowSpinner();
LoginService.authenticateUser(userName, password).then(
function(response){
$scope.HideSpinner();
if( response.isSuccess ){
// Login Success
}
else{
//Login Fail
}
},
function(error){
//Network related error
$scope.HideSpinner();
}
);
Your English is really good and you need not worry about it at all. Coming back to your question, you are on the right path. You would need to use ng-show or ng-hide, whatever you choose. Let's say you choose ng-show In your controller, you would declare a variable,
$scope.isProgessBarVisible = true;
and then, within the controller itself, upon return from http call from the server, you would set it to false.
$http.get('someUrl')
.then(function successCallback(response) {
//load you pdf file content
$scope.isProgessBarVisible = false;
}
And in the HTML
<div class="progress">
<div class="progress-bar" role="progressbar" ng-show="isProgessBarVisible" aria-valuenow="70"
aria-valuemin="0" aria-valuemax="100" style="width:70%">
<object width="400" height="400" data="file.pdf"></object>
</div>
With this in place, the progress bar will show up until the file is fetched from server and displayed.
I think the problem is not just about showing/hiding the progress bar, perhaps it is about how to hide the progress bar when the <object>'s content finish loading.
Initially, I tried to use ng-load on the <object> but somehow it didn't work. So I tried to use onload which does work. But since the onLoad() handler function is outside angular environment, I had to get back the angular scope to be able to set the variable $scope.showProgress that will hide the progress bar.
See the plunkr yourself, and let me know if that is what you are looking for.
Plunkr https://plnkr.co/edit/wxgetLZdST0WcPEHyraZ
Note: I don't know whether it is possible to get the progress status number (% loaded), but at least we can show "Loading..." or a spinner icon while the <object> is loading.
http://chieffancypants.github.io/angular-loading-bar/
angular.module('app', ['angular-loading-bar']);
angular-loading-bar is a good option for $http calls

How to position polymer paper-toast element

Created Polymer app using polymer init command and selecting app-drawer-template.
In my-view1.html, linked to paper-toast.html and modified the template and script as follows:
<template>
<div class="card">
<div class="circle">1</div>
<h1>View One</h1>
<button on-tap="handleTap">open</button>
<paper-toast id="toast0" text="This toast auto-closes after 3 seconds"></paper-toast>
</div>
</template>
<script>
Polymer({
is: 'my-view1',
handleTap: function(){
this.$.toast0.open();
}
});
When the button is clicked, the toast appears but most of it appears behind the Menu drawer and only part of the toast window is visible.
I tried to center the toast using css but it does not work. Setting z-index did not work either. How can the toast window be positioned so it is not hidden behind the drawer?
Following css also can solve your problem.
paper-toast {
width: 300px;
margin-left: calc(50vw - 150px);
}
Added the following css class to toast element:
.mytoast {
width: 100%;
text-align: right;
}
Now toast window spans the page and text shows aligned to right end .

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>')

Customizing Modal Panel size Ui Bootstrap

I'm building an app using Ui bootstrap to integrate some bootstraps components with AngularJs. I need to use a modal panel but concretely the predefined size 'lg' (large) is not big enough for what I need. So I need to customize. Reading the docs, to customize you need to pass a css class when you open the modal using the property 'windowClass'. So I have created a Css class called 'modal-huge' as follows:
.modal-huge .modal-dialog{
width: 80%;
}
.modal-body
{
height: 80%;
}
Then I pass this class as a parameter when I open the modal panel:
var modalInstance = $modal.open({
templateUrl: 'productDetail.html',
controller: 'ProductDetailController',
windowClass: 'modal-huge',
resolve:{
productDetail: function (){
$scope.hideLoader();
return response;
}
}
});
I used percentages for both width and height to have a responsive design, so they adapt to the size of the screen taking in account the size of the parent element.
My problem is that is working fine only for the width, but not for the height. For height is only considering the changes if I give the size in pixeles (px), but not if I give a percentage, which breaks the responsive design. Any idea what can be wrong or some way to fix it? Thank you very much!!
I display the rest of the code in case it helps you.
The modal panel code:
<div>
<script type="text/ng-template" id="productDetail.html">
<div class="modal-header">
<h3 class="modal-title">Product</h3>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-ng-click="ok()">OK</button>
<button class="btn btn-warning" data-ng- click="cancel()">Cancel</button>
</div>
</script>
</div>
And the body where I have included the modal panel called 'productDetailPanel'
<body data-ng-controller="AppController">
<div id="container" class="container">
<toaster-container toaster-options="{'position-class': 'toast-container- custo','time-out': 3000, 'close-button':true}"></toaster-container>
<div id="header" data-ng-include="'partials/header/header.html'" > </div>
<div data-ng-view></div>
<div id="footer" data-ng-include="'partials/footer/footer.html'"> </div>
<!-- This is the div with the overlay css class, so no matter where it is located this div inside the screen, it will cover the whole screen-->
<div id="loader" class="loading overlay" data-ng- if="loader.loading">
<p>{{loader.loadingMessage}}</p>
<img alt="" src="images/ajax-loader.gif">
</div>
</div>
<div id="loginPanel" data-ng- include="'partials/content/panels/login.html'"></div>
<div id="productDetailPanel" data-ng- include="'partials/content/panels/productDetail.html'"></div>
</body>
In order for % height to work you have to set a height to the parent element as well.
In the .modal-body example the parent is .modal-content which in it's place has .modal-dialog as a parent.
Try something like this
.modal-dialog, .modal-content {
height: 100%;
}
.modal-body {
height: 80%;
}
Or check for similar questions Set bootstrap modal body height by percentage

Resources