ion icons not showing up on ipad / edge - ipad

I have a stenciljs component deployed in an nginx server behind an authentication service. In order to get anything the request must include a cookie containing an access_token. the component is dipslyaed with no preoblem on android devices and on chrome/firfox/IE11/ in desktop devices. the problem is with microsoft edge and on ipad (any navigator) and its due to the browser not sending the cookie to the server. Any hint ?
header.tsx
import { Component, Prop, State, Element } from '#stencil/core';
#Component({
tag: 'pm-header',
styleUrl: 'pm-header.scss',
shadow: true
})
export class PmHeader {
...
render() {
return (
<nav>
<ul>
<li id="menu-icon" class="left menu-icon"
onClick={() => this.toggleFocus('menu-icon')} >
<a>
<ion-icon name="md-apps"></ion-icon>
</a>
</li>
<li id="user-icon" class="right menu-icon"
onClick={() => this.toggleFocus('user-icon')} >
<a>
<ion-icon name="md-contact"></ion-icon>
</a>
</li>
</ul>
</nav>
);
}
}
PS: I'm using stencil/core v0.15.2

So after some digging it turned out that the issue is with ionicons implementation.
They fetch the svgs without sending the credentials which result in an authenticated request. Of course some navigator such as chrome and firefox and even IE11 manages to send the cookies even though it's not explicitly specified that they should.
Anyway, to solve this I had to create a script file that run after the build. This script adds credentials: "include" option to the fetch call so that the cookie get sent.
fix-icons-script.js
/**
* Workaround to fix this ion-icons bug https://github.com/ionic-team/ionicons/issues/640
* To be removed when this bug is fixed
*/
const fs = require('fs');
const workDir = 'dist/component-dir';
fs.readdir(workDir, function(err, items) {
if (err) { return console.log(err); }
for (var i=0; i<items.length; i++) {
if (items[i].endsWith('.entry.js')) {
insertString(workDir + '/' + items[i], '"force-cache"', ',credentials:"include"');
}
}
});
function insertString(file, searchValue, insertValue){
fs.readFile(file, 'utf8', function (err, content) {
if (err) { return console.log(err); }
let newContent = content.substr(0, content.indexOf(searchValue) + searchValue.length);
content = content.substr(newContent.length, content.length);
newContent += insertValue + content;
fs.writeFile(file, newContent, function (err) {
if (err) { return console.log(err); }
console.log('Successfully rewrote ' + file);
});
});
}

Related

Electron: Cannot access dialog before initialization

I have a renderer file that has the sole purpose of opening a dialog box to select files from. I have tried rewriting this so many times, and each time I get a different error. What am I doing wrong?
Exact code:
const { ipcRenderer, shell, remote } = require('electron')
const dialog = remote.dialog;
function openFileBrowser() {
dialog.showOpenDialog(remote.getCurrentWindow(), {
properties: ["openFile", "multiSelections"]
}).then(result => {
if (result.canceled === false) {
console.log("Selected file paths:")
console.log(result.filePaths)
}
}).catch(err => {
console.log(err)
})
}
Related HTML:
<div id="button-container">
<nav>
<ul class="buttons">
<li id="Open" onclick="openFileBrowser()">Proxies</li>
</ul>
</nav>
</div>
Error Code
renderer.js:37 Uncaught ReferenceError: Cannot access 'dialog' before initialization
at openFileBrowser (renderer.js:37)
at HTMLLIElement.onclick (proxies.html:16)
Using Electron:
"7.1.7"
Since Electron 6.0.0, the functions dialog.showMessageBox(), dialog.showOpenDialog() and dialog.showSaveDialog() return Promises and no longer take callback functions.
There are synchronous counterparts dialog.showMessageBoxSync(), dialog.showOpenDialogSync() and dialog.showSaveDialogSync().
Check out the following code examples showing the asynchronous and the synchronous way of displaying an open dialog:
Asynchronous: dialog.showOpenDialog()
const remote = require("electron").remote
const dialog = remote.dialog
dialog.showOpenDialog(remote.getCurrentWindow(), {
properties: ["openFile", "multiSelections"]
}).then(result => {
if (result.canceled === false) {
console.log("Selected file paths:")
console.log(result.filePaths)
}
}).catch(err => {
console.log(err)
})
Synchronous: dialog.showOpenDialogSync()
const remote = require("electron").remote
const dialog = remote.dialog
let result = dialog.showOpenDialogSync(remote.getCurrentWindow(), {
properties: ["openFile", "multiSelections"]
})
if (typeof result === "object") {
console.log("Selected file paths:")
console.log(result)
}
Both versions can optionally take a BrowserWindow as the first element. If one is provided, the dialog is shown as a modal window.
Check the Electron dialog documentation for detailed usage information.

Angular JS custom directive not working on iOS devices

I have deployed my app on Azure, I have a C# backend and AngularJS front end.
I am using a custom directive (called bgSrc) which sets the image source based on the given url (either a background-image or a src) depending on which element the directive is used.
Here is the directive:
app.directive('bgSrc', ['preloadService', function (preloadService) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.hide();
preloadService(attrs.bgSrc).then(function (url) {
if (element[0].tagName === 'DIV' || element[0].tagName === 'MD-CONTENT' || element[0].tagName === 'MAIN' || element[0].tagName === 'FORM') {
element.css({
"background-image": "url('" + url + "')"
});
element.fadeIn();
}
else if (element[0].tagName === 'IMG') {
attrs.$set('src', url);
element.css({
'display': 'block'
});
element.fadeIn();
}
});
}
};
}]);
Here is my preloadService:
app.factory('preloadService', ['$q', '$rootScope', function ($q, $rootScope) {
return function preload(url) {
var deffered = $q.defer(),
image = new Image();
image.src = url;
if (image.complete) {
deffered.resolve(image.src);
$rootScope.loading = false;
} else {
$rootScope.loading = true;
image.addEventListener('load', function () {
deffered.resolve(image.src);
$rootScope.loading = false;
});
image.addEventListener('error', function () {
deffered.reject();
$rootScope.loading = true;
});
}
return deffered.promise;
};
}]);
Here is an example of how I use it on html.
<div ng-if="!loading" bg-src="assets/build/img/ocean_bg.png">
<form name="model.form" ng-submit="login()" bg-src="assets/build/img/scroll.png">
<h1>Log In</h1>
...
</form>
</div>
It works perfectly well on Chrome and Android but keeps failing on iOS devices. I have pinpointed the issue to be my custom directive, if I remove it the page loads fine, if I include it the page is caught in an endless loop not loading my images and stick in the "$rootScope.loading" state which simply displays a circular progress bar.
Any help on the matter is much appreciated
The issue was in my preloadeService, where the loading of the image was stuck in an infinite loop.

React Bootstrap OverlayTrigger with trigger="focus" bug work around

In iOS safari, OverlayTrigger with trigger="focus" isn't able to dismiss when tapping outside. Here is my code:
<OverlayTrigger
trigger="focus"
placement="right"
overlay={ <Popover id="popoverID" title="Popover Title">
What a popover...
</Popover> } >
<a bsStyle="default" className="btn btn-default btn-circle" role="Button" tabIndex={18}>
<div className="btn-circle-text">?</div>
</a>
</OverlayTrigger>
I know that this is a known bug for Bootstrap cuz this doesn't even work on their own website in iOS, but does anyone know any method to go around it? It would be the best if it is something that doesn't require jQuery, but jQuery solution is welcome. Thanks.
OK, since no one else gives me a work around, I worked on this problem with my co-worker together for 3 days, and we came up with this heavy solution:
THE PROBLEM:
With trigger="focus", Bootstrap Popover/Tooltip can be dismissed when CLICKING outside the Popover/Tooltip, but not TOUCHING. Android browsers apparently changes touches to clicks automatically, so things are fine on Android. But iOS safari and browsers that is based on iOS safari (iOS chrome, iOS firefox, etc...) don't do that.
THE FIX:
We found out that in React Bootstrap, the Overlay component actually lets you customize when to show the Popover/Tooltip, so we built this component InfoOverlay based on Overlay. And to handle clicking outside the component, we need to add event listeners for both the Popover/Tooltip and window to handle both 'mousedown' and 'touchstart'. Also, this method would make the Popover have its smallest width all the time because of the padding-right of the component is initially 0px, and we make based on the width of some parent component so that it is responsive based on the parent component. And the code looks like this:
import React, { Component, PropTypes as PT } from 'react';
import {Popover, Overlay} from 'react-bootstrap';
export default class InfoOverlay extends Component {
static propTypes = {
PopoverId: PT.string,
PopoverTitle: PT.string,
PopoverContent: PT.node,
// You need to add this prop and pass it some numbers
// if you need to customize the arrowOffsetTop, it's sketchy...
arrowOffsetTop: PT.number,
// This is to be able to select the parent component
componentId: PT.string
}
constructor(props) {
super(props);
this.state = {
showPopover: false,
popoverClicked: false
};
}
componentDidMount() {
// Here are the event listeners and an algorithm
// so that clicking popover would not dismiss itself
const popover = document.getElementById('popoverTrigger');
if (popover) {
popover.addEventListener('mousedown', () => {
this.setState({
popoverClicked: true
});
});
popover.addEventListener('touchstart', () => {
this.setState({
popoverClicked: true
});
});
}
window.addEventListener('mousedown', () => {
if (!this.state.popoverClicked) {
this.setState({
showPopover: false
});
} else {
this.setState({
popoverClicked: false
});
}
});
window.addEventListener('touchstart', () => {
if (!this.state.popoverClicked) {
this.setState({
showPopover: false
});
} else {
this.setState({
popoverClicked: false
});
}
});
// this is to resize padding-right when window resizes
window.onresize = ()=>{
this.setState({});
};
}
// This function sets the style and more importantly, padding-right
getStyle() {
if (document.getElementById(this.props.componentId) && document.getElementById('popoverTrigger')) {
const offsetRight = document.getElementById(this.props.componentId).offsetWidth - document.getElementById('popoverTrigger').offsetLeft - 15;
return (
{display: 'inline-block', position: 'absolute', 'paddingRight': offsetRight + 'px'}
);
}
return (
{display: 'inline-block', position: 'absolute'}
);
}
overlayOnClick() {
this.setState({
showPopover: !(this.state.showPopover)
});
}
render() {
const customPopover = (props) => {
return (
{/* The reason why Popover is wrapped by another
invisible Popover is so that we can customize
the arrowOffsetTop, it's sketchy... */}
<div id="customPopover">
<Popover style={{'visibility': 'hidden', 'width': '100%'}}>
<Popover {...props} arrowOffsetTop={props.arrowOffsetTop + 30} id={this.props.PopoverId} title={this.props.PopoverTitle} style={{'marginLeft': '25px', 'marginTop': '-25px', 'visibility': 'visible'}}>
{this.props.PopoverContent}
</Popover>
</Popover>
</div>
);
};
return (
<div id="popoverTrigger" style={this.getStyle()}>
<a bsStyle="default" className="btn btn-default btn-circle" onClick={this.overlayOnClick.bind(this)} role="Button" tabIndex={13}>
<div id="info-button" className="btn-circle-text">?</div>
</a>
<Overlay
show={this.state.showPopover}
placement="right"
onHide={()=>{this.setState({showPopover: false});}}
container={this}>
{customPopover(this.props)}
</Overlay>
</div>
);
}
}
In the end, this is a heavy work around because it is a big amount of code for a fix, and you can probably feel your site is slowed down by a tiny bit because of the 4 event listeners. And the best solution is just tell Bootstrap to fix this problem...

Jquery data-role collapsible events aren't being captured in Jquery Mobile

Could anybody please let me know why the following code isn't working when i am using with Jquery mobile JS
http://jsfiddle.net/znz17ctm/7/
This is my code
<div role="main" class="ui-content oms-content" id="dd">
<div class="myactivelabelsWrap" id="result"></div>
</div>
var response = {
"Restaurants": [{
"RestrntArea": "Haii",
"cust_loc_id": "374"
}, {
"RestrntArea": "rerrrwe",
"cust_loc_id": "373"
}]
}
showLabels();
function showLabels() {
//$("#result").html("");
var favoriteresultag = '';
for (var i = 0; i < response.Restaurants.length; i++) {
var name = response.Restaurants[i].RestrntArea;
if (name) {
favoriteresultag +=
'<div data-role="collapsible" data-inset="false" class="my-collaspible"><h3>' +
name +
' <a class="icon-pencil-1 labelEditIcon "></a></h3></div>';
}
}
$("#result").append(favoriteresultag).trigger("create");
}
$(document).ready(function() {
$('.my-collaspible').bind('expand', function() {
alert('Expanded');
});
$('.my-collaspible').bind('collapse', function() {
alert('Collapsed');
});
});
Why the collapse and expand even'ts are being captured ??
Instead of document ready i tried with al the page events of mobile . But no luck .
From your fiddle I can't tell which version of jQM you are using. You have checked version 1.3 but then added the 1.4 css. Assumin version 1.4, I have updated your fiddle:
FIDDLE
Basically, you need to use event delegation to attach the events because the collapsibles do not exist at the time of the bind. Also the event names are actually collapsibleexpand and collapsiblecollapse.
So use on() instead of bind() by handling the event on the parent div and delegating it to all items with class my-collapsible that exist now or added dynamically:
$("#result").on('collapsibleexpand', '.my-collaspible', function () {
alert('Expanded');
});
$("#result").on('collapsiblecollapse', '.my-collaspible', function () {
alert('Collapsed');
});

How do I test an angular dart decorator?

I am trying to unit test an angular dart decorator but cannot pass the component compile phase.
I am trying to follow this example : https://github.com/vsavkin/angulardart-sample-app/blob/master/test/unit/agenda_item_component_test.dart
The problem is that karma doesn't seem to wait for the compile phase to finish and just skips the test.
part of webpuzzle_spec;
digest() {
inject((TestBed tb) {
tb.rootScope.apply();
});
}
compileComponent(String html, Map scope, callback) {
print("This logs");
return async(() {
inject((TestBed tb) {
print("this should log but doesn't");
final s = tb.rootScope.createChild(scope);
final el = tb.compile(html, scope: s);
microLeap();
digest();
callback(el.shadowRoot);
});
});
}
testWpDropdownMenu() {
group("[WpDropdownMenu]", () {
setUp(setUpInjector);
tearDown(tearDownInjector);
setUp((){
module((Module _) => _..type(TestBed)..type(WpDropdownMenu));
});
html() => '''<span class="dropdown-toggle">
<button type="button" class="btn btn-default">menu to click</button>
<ul class="dropdown-menu">
<li>menu item</li>
</ul>
</span>''';
test("should open menu on click", compileComponent(html(), {}, (shadowRoot) {
print("this never logs :(");
shadowRoot.click();
digest();
var toggleableMenu = shadowRoot.querySelector('.dropdown-menu');
expect(toggleableMenu.style.display, equals('none'));
expect(true, equals(false)); // this should make the test fail
}));
});
}
What is the problem with this code ? Is there a nice example somewhere that explains how to test a component/decorator, only using angular.dart and karma ?

Resources