Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Black background in Safari and Edge #865

Open
St1c opened this issue Jan 25, 2017 · 21 comments
Open

Black background in Safari and Edge #865

St1c opened this issue Jan 25, 2017 · 21 comments
Labels
issue: bug Describes why the code or behaviour is wrong

Comments

@St1c
Copy link

St1c commented Jan 25, 2017

Hi,

I'm building application in Angular 2 and implemented latest version of Blockly into it. Everything works perfectly in Chrome, but in Safari I'm seeing black background on .blocklySvg, and controls sprites are also being displayed wrong (seems like CSS bug). I use untouched blockly_compressed.js in vendors.js bundle and custom blocks implemented as directives, which are being built in separate bundle (app.js).

I tried to force background with CSS but nothing worked. I also tried to move toolbox outside of the injection div, also didn't help. Seems like bug in the source

Safari version 10.0.3 (12602.4.8.)
Chrome Version 55.0.2883.95 (64-bit)

See the enclosed screenshots
chrome
safari
screen shot 2017-01-25 at 17 31 40
screen shot 2017-01-25 at 17 32 19

@picklesrus
Copy link
Contributor

Are you importing other CSS? What does the console tell you it thinks the background color is? Does Chrome's console tell you something different from Safari's?

Note that I have 0 experience with angular :-/

@picklesrus
Copy link
Contributor

It does look like you have 4 copies of the whole sprite sheet, 1 for each control (trash, zoom in, etc.). Another thing to try besides digging around in your css definitions would be to toggle controls on and off and play with your grid to see if that changes anything.
I would play with the following:

trashcan: try setting to false
grid: try removing it
zoom: try removing it

@St1c
Copy link
Author

St1c commented Jan 26, 2017

I tried that. If I look in the developer console, I see the same colours in chrome and safari.
The only thing which I can change from external CSS is this:

.blocklyMainBackground {
// Ugly hack to fix black safari background
opacity: 0 !important;
}

The reason why there are 4 sprites - is that there are actually 4 controls - but in safari the proper background position and size are not applied, that why the whole sprite is displayed, instead of only the correct subpart of it.

It seems that this is definitely related to some CSS which is not loaded correctly - but as all CSS rules are defined in the blockly JS library, I have zero control over it.

@picklesrus
Copy link
Contributor

Does changing the .blocklyMainBackground rule like that actually fix the background?
The .blocklySvg class on the inside the injection div is relevant ( Blockly's default css specifies a background-color: #fff. ) The fill on the rect with class .blocklyMainBackground is another relevant thing that comes to mind. Did you try turning off the grid to see if the background is still black?

Yes, it does seem like the CSS is loading in an odd way or there are some rule conflicts with a file outside of blockly. I'm debugging blind though since I don't see this problem in safari on our demos (e.g. https://blockly-demo.appspot.com/static/demos/code/index.html). If this page is hosted somewhere, I can take a look at the html and see if I spot anything.

@St1c
Copy link
Author

St1c commented Jan 26, 2017

It only hides the black colour (makes it transparent - hence white).
The demos works OK in Safari:

I created working version on my server, so here is the link:

http://blockly.dataworkers.eu/parser/classifiers

@rachel-fenichel rachel-fenichel added the issue: bug Describes why the code or behaviour is wrong label Feb 2, 2017
@tahagoal
Copy link

tahagoal commented Jul 3, 2017

I faced the same problems in Safari and Edge:
The grid is black and the sprite duplicates 4 times.
Did you find any solutions ?

@St1c
Copy link
Author

St1c commented Aug 9, 2017

Hi,

I also face the same problem in Edge, even in newest version of angular. I reported this issue also in angular repo (angular/angular#14843)

It has been updated with tag core&compiler bug, but no updates whatsoever after that :)

@St1c St1c changed the title Black background in Safari Black background in Safari and Edge Aug 9, 2017
@tahagoal
Copy link

Thank You

@Bohdan-Tereta
Copy link

Bohdan-Tereta commented Dec 15, 2017

This happens because you have 'base href="/"' tag in your AppComponent.html.

That tag influences how svg processes some style urls (which is normal behavior), but urls generated by GoogleBlockly do not need that tag, it is needed only for angular to work, and so some svg style urls become invalid.

In Angular 2+, you can inject the base path in your app module instead of using the tag.

import { APP_BASE_HREF } from '@angular/common';

@NgModule({
providers: [{
provide: APP_BASE_HREF,
useValue: '/'
}]
})
export class AppModule { }

Don't forget to remove 'base href="/"' tag from your AppComponent.html.

https://angular.io/docs/ts/latest/api/common/index/APP_BASE_HREF-let.html

That solves the problem. But creates another one with deep routing in Angular (deep direct links like www.somesite.com/entity/2 stop working)

@Bohdan-Tereta
Copy link

Bohdan-Tereta commented Jun 22, 2018

Proper solution would be (finally):

  1. Add this function to Blockly sources
/**
 * Convert local uri to global uri, required for svg to work correctly when page contains <base> tag
 * Fixes Safari svg rendering issues (black background, misplaced zoom/trash controls etc)
 * @param {string} localUri local uri string
 * local uri example: "url(#blocklyTrashBodyClipPath837493)"
 * @return {!string} global uri
 */
Blockly.convertToGlobalUri = function (localUri) {
  var baseUrl = window.location.href.replace(window.location.hash, "");
  var idx = localUri.indexOf("url(");
  return localUri.slice(0, idx + 4) + baseUrl + localUri.slice(idx + 4);
};
  1. In all places where you see 'url(#' inside blockly sources, use Blockly.convertToGlobalUri() to convert local uri to global one

Source of the issue: blockly generates local uris even when tag is present which is incorrect (svg should react to tag), most browsers are 'smart enough' to convert local uris to global in that case (that browser behaviour is not part of specs though), but that doesn't happen in Safari
So I assume that isn't a safari bug and should be fixed in blockly

Solution was implemented and tested by me and works in Safari. Noticed no side effects in Chrome/Firefox/Edge/IE too.
Steps to reproduce:

  1. Take any blockly example
  2. Add tag to page
  3. Open the page in Safari
    Expected: white backround, correctly placed zoom/trash controls
    Actual: black backround, zoom/trash controls are visually multiplied (see screenshot at the beginning of this thread)

@profgarrett
Copy link

It would be great to see the code from Bohdan implemented. I experienced a similar issue after embedding Blockly into a React application. I narrowed down the root cause to a similar tag in my html document. Upon removing this tag, the black background in Safari was fixed.

@Bohdan-Tereta
Copy link

Here's the better fix implementation in case somebody from the team wants to merge that and fix this issue:
angular/angular#14843 (comment)

@zeropool
Copy link

zeropool commented Oct 8, 2018

JUST HOOK

Blockly.svgResize_raw = Blockly.svgResize;
Blockly.svgResize = function(obj) {
    Blockly.svgResize_raw(obj);
    if (obj.svgBackground_.style.fill.indexOf('#') != -1 && obj.svgBackground_.style.fill.indexOf('://') == -1) {
        var baseUri = window.location.hash ? window.location.href.replace(window.location.hash, "") : window.location.href;
        obj.svgBackground_.style.fill=obj.svgBackground_.style.fill.replace('#', baseUri+'#');
    }
};
// blocklyWorkspace.svgBackground_.style.fill=blocklyWorkspace.svgBackground_.style.fill.replace('#', 'http://127.0.0.1:9000/m/add-strategy#');
Blockly.utils.createSvgElement_raw = Blockly.utils.createSvgElement;
Blockly.utils.createSvgElement = function(name, attr, group) {
    var baseUri = window.location.hash ? window.location.href.replace(window.location.hash, "") : window.location.href;
    if (typeof(attr) !== 'undefined' && typeof(attr['clip-path']) == 'string') {
        var s = attr['clip-path'];
        if (s.indexOf('#') != -1 && s.indexOf('://') == -1) {
            var arr = s.split('#');
            arr[1] = baseUri + '#' + arr[1];
            attr['clip-path'] = arr.join('');
        }
    }
    return Blockly.utils.createSvgElement_raw(name, attr,group);
}

@amish-thaker
Copy link

This looks like a life saver. But where exactly should I write this function? Not sure what you mean by Blockly Sources. :-/

Proper solution would be (finally):

  1. Add this function to Blockly sources
/**
 * Convert local uri to global uri, required for svg to work correctly when page contains <base> tag
 * Fixes Safari svg rendering issues (black background, misplaced zoom/trash controls etc)
 * @param {string} localUri local uri string
 * local uri example: "url(#blocklyTrashBodyClipPath837493)"
 * @return {!string} global uri
 */
Blockly.convertToGlobalUri = function (localUri) {
  var baseUrl = window.location.href.replace(window.location.hash, "");
  var idx = localUri.indexOf("url(");
  return localUri.slice(0, idx + 4) + baseUrl + localUri.slice(idx + 4);
};
  1. In all places where you see 'url(#' inside blockly sources, use Blockly.convertToGlobalUri() to convert local uri to global one

Source of the issue: blockly generates local uris even when tag is present which is incorrect (svg should react to tag), most browsers are 'smart enough' to convert local uris to global in that case (that browser behaviour is not part of specs though), but that doesn't happen in Safari
So I assume that isn't a safari bug and should be fixed in blockly

Solution was implemented and tested by me and works in Safari. Noticed no side effects in Chrome/Firefox/Edge/IE too.
Steps to reproduce:

  1. Take any blockly example
  2. Add tag to page
  3. Open the page in Safari
    Expected: white backround, correctly placed zoom/trash controls
    Actual: black backround, zoom/trash controls are visually multiplied (see screenshot at the beginning of this thread)

@RoboErikG RoboErikG added this to the Bug Bash Backlog milestone Oct 25, 2019
@RoboErikG
Copy link
Contributor

@samelhusseini do you have some time to check if this is still an issue for Angular on Safari?

@samelhusseini
Copy link
Contributor

This isn't an Angular specific thing. Our samples wouldn't repro because they don't use a router. In any framework that makes use of a router, the router would add a <base /> tag to figure out where it is.

You can repro something like this by adding <base href="/" /> in the playground.html and running a http-server. I'll look into this further to figure out what the right fix is.

@samelhusseini samelhusseini self-assigned this Oct 25, 2019
@samelhusseini
Copy link
Contributor

samelhusseini commented Oct 25, 2019

According to https://stackoverflow.com/questions/18259032/using-base-tag-on-a-page-that-contains-svg-marker-elements-fails-to-render-marke/18265336#18265336 it seems the right fix is to include an absolute url when referencing the SVG filters, but I'm not sure how I feel about that as someone else could have the base point to some other URL and that would break things for them.

@RoboErikG
Copy link
Contributor

Maybe I'm missing something, but using absolute urls doesn't seem like something we can easily do generally in the Blockly library. Given that the base isn't necessarily where these resources are located would we need to add another API for a resource base url for these resources similar to the media path option?

@samelhusseini
Copy link
Contributor

Yeah I'm still learning about the tag to see what the fix should be, but my understanding so far is the tag basically says reference all relative paths using this new path instead of the document's URL path.
SVG urls like url(#blocklyZoomClipPath) that worked when they were referencing a relative id would no longer work since they now reference this new relative path based on the tag. More info on that here angular/angular.js#8934

Couple of options, we could call into a utility method similar to what we do with Blockly.utils.xml.textToDomDocument making it easier for developers to return a url that works with the base tag.
Or we could add the absolute url ourselves. My concern there is I don't know how that would affect other developers not using the tag.

@Bohdan-Tereta
Copy link

Bohdan-Tereta commented Oct 26, 2019

Hi, @samelhusseini, hope it's time to finally fix this in Blockly.

I've investigated this issue some time ago, and just refreshed my findings recently as I see some activity in the thread again. It seems Safari doesn't comply with to w3c specs for "(fill: url("#" - base should be combined with hash part (as other browsers do).

So let's just use absolute urls here.

https://html.spec.whatwg.org/multipage/semantics.html#the-base-element https://www.w3.org/2015/08/25-svg-minutes.html#item08.

There will be no side issues for developers which aren't using tag because absolute urls parsing isn't affected by base href.

@Bohdan-Tereta
Copy link

Bohdan-Tereta commented Oct 26, 2019

@amish-thaker, here's a summary of my response to you, will put it here, in case anybody else needs it:

By blockly sources I mean the code here https://github.com/google/blockly.

I do not use the out-of -the-box compiled blockly library but build my own heavily modified version from those sources + my patches using google closure plovr.jar tool https://github.com/bolinfest/plovr.

In case you don't want to recompile, you can override appropriate methods after Blockly lib is loaded
Namely, add Blockly.convertToGlobalUri and override Blockly.WorkspaceSvg.prototype.createDom to call Blockly.convertToGlobalUri

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
issue: bug Describes why the code or behaviour is wrong
Projects
None yet
Development

No branches or pull requests

10 participants