I am displaying a webview with a remote html content get as a string from a remote server.
I store the html locally for a no connection use of my application.
Moreover I also store a .js script and a .css style file locally. These files can be updated by the server.
I store all these files at the following paths :
context.getFilesDir()+"content.css"
context.getFilesDir()+"content.js"
In the html string, css and js are referenced like this :
<link rel="stylesheet" href="/content.css" type="text/css" media="screen">
<script src="/content.js"></script>
I load the html using
this.webView.loadDataWithBaseURL(getFilesDir().getAbsolutePath(), html, "text/html", "utf-8", "about:blank");
But the style and the js are not taken into account, so I think something is wrong with the path I use to reference them, or to load the webView. So what is the way to do this ? I found many answers that use the "assets" folder but I do not want to use it since I have to update the css and the js from the server.
Finally I have found the solution :
The css (or js) file is saved in local using this method :
public static void writeToFile(Context context, String content, String title) throws IOException
{
OutputStreamWriter osw = new OutputStreamWriter(context.openFileOutput(title,Context.MODE_WORLD_READABLE));
osw.write(content);
osw.close();
}
Then I refer it in the html file using
<link rel="stylesheet" href="content.css" type="text/css" media="screen">
<script src="content.js"></script>
And finally I have opened the webview using :
this.webView = (WebView) findViewById(R.id.webview);
this.webView.getSettings().setJavaScriptEnabled(true);
this.webView.getSettings().setPluginsEnabled(true);
this.webView.setHorizontalScrollBarEnabled(false);
this.webView.setVerticalScrollBarEnabled(true);
this.webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
this.webView.setWebViewClient(this.controller.getWebViewClient());
String basePath = "file://"+getFilesDir().getAbsolutePath()+"/";
this.webView.loadDataWithBaseURL(basePath, data, "text/html", "utf-8", "about:blank");
Related
I'm currently working on a .NET Standard 2.1 Blazor WebAssembly application. I try to include or exclude JavaScript files in my index.html according to an environment variable.
The Blazor WebAssembly App is NOT Asp.NET Core hosted.
In .NET Core there are usually Environment Tag Helpers like in the following example:
<environment include="Development">
<script src="js/app.js"></script>
<script src="js/helpers.js"></script>
</environment>
<environment exclude="Development">
<script src="js/site.min.js"></script>
</environment>
As already discussed in this question Blazor WebAssembly Environment Variables, the Environment Tag Helpers are server side code and thus don't work in Blazor WASm.
Now I try to find a good solution to include/exclude JavaScript files according to the Environment variable in Blazor WebAssembly.
The first idea was, similar like for CSS, to create a component called <Scripts> to load the different script files on the index.html like this:
#using Microsoft.AspNetCore.Components.WebAssembly.Hosting
#inject IWebAssemblyHostEnvironment hostEnv
#*Check the environment value*#
#if (hostEnv.IsDevelopment())
{
<script src="js/app.js"></script>
<script src="js/helpers.js"></script>
}
else
{
<script src="js/site.min.js"></script>
}
#code {}
Unfortunately this doesn't work, because the <script> Element is not allowed to be used in a Blazor component (.razor file).
The following error occurs: The script element allows authors to include dynamic script and data blocks in their documents. The element does not represent content for the user. ... Script tags should not be placed inside components because they cannot be updated dynamically. To fix this, move the script tag to the 'index.html' file or another static location. ... https://go.microsoft.com/fwlink/?linkid=872131
How do you load different scripts according to the Environment Variable i.e. Development, Production or Staging in Blazor Webassembly?
Do you know how to solve this problem?
I wanted to add Tailwind CDN script tag just during development. I ended up using the solution below:
index.html
<script src="_framework/blazor.webassembly.js"></script>
<script>
// If localhost, add tailwind CDN (or any other script that you want)
if (window.location.hostname == 'localhost') {
var customScript = document.createElement('script');
customScript.setAttribute('src', 'https://cdn.tailwindcss.com');
document.head.appendChild(customScript);
}
</script>
Simply copy your index.html code in a .cshtml (named BlazorApp.cshtml in the following sample) in your server project and fallback to this page.
public void Configure(IApplicationBuilder app)
{
...
app.UseEndpoints(endpoints =>
{
...
endpoints.MapFallbackToPage("/BlazorApp");
}
}
And update the code with <environment> tags for your conveniance.
Please check the solution in this answer (same question as you linked above) and that seems to work.
Basically the workaround is to use this in a new component called Head.razor as per the solution:
#inject IWebAssemblyHostEnvironment hostEnv
#if (hostEnv.IsDevelopment())
{
<title>BlazorWasmApp - In Debug</title>
<link href="css/debug.css" rel="stylesheet" />
}
else
{
<title>BlazorWasmApp - Not Debug</title>
<link href="css/live.css" rel="stylesheet" />
}
New Head.razor component:
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
//Add the Head to root components
builder.RootComponents.Add<Head>("head");
builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
}
I followed Summernote-rails official to add rich text editor in my Rails project.
Then in my edit.html.erb I added class place_editor to my text_area:
<%= f.text_area :text, class: "place_editor form-control col-md-7 col-xs-12", rows: "15j ,placeholder: "Text", required: "required"%>
and then JavaScript as:
<script type="text/javascript">
$(function() {
$('.place_editor').summernote();
var edit = function () {
$('.click2edit').summernote({ focus: true });
};
$("#edit").click(function () {
$('.click2edit').summernote({ focus: true });
});
$("#save").click(function () {
var aHTML = $('.click2edit').code(); //save HTML If you need(aHTML: array).
$('.click2edit').destroy();
});
// Adding Css to give border to text editor
$(".note-editor").css("border", "solid 1px #e7eaec");
});
</script>
Everything works fine except ICONS.
It's Simple
Just Download summernote compile zip file click here.
Unzip the file. Copy font folder. Paste it you summernote.css root. Be sure your summernote.css file stay with font folder. Now Refresh your Browser using Ctrl + F5.
Folder Location demo:
Demo Output:
I searched for hours and finally solved it.
Actually, summernote doesn't save icons locally, instead it download it
I added this links in header
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.1/summernote.css" rel="stylesheet">
And it did the job
I 'll welcome if someone can elaborate it further
Import the font files, it will work.
I tried import through CSS #font-face rule. You can import in javascript also.
#font-face {
font-family: summernote;
src : url('/fonts/summernote.ttf');
src : url('/fonts/summernote.eot'),
url('/fonts/summernote.woff');
}
After unzipping the Summernote distribution download, you must copy the Font folder to the same place you put the summernote.css file.
In this example, Elmer is the root folder of the website, and both summernote.css and the Font folder are copied to the /assets/css folder.
Similarly, the summernote.js file is copied to the /assets/js folder. If you're not using plugins or languages, that's all you need to install.
Here's the code to put in the header to load those files as shown:
<!-- include summernote css/js-->
<link rel="stylesheet" type="text/css" charset="utf-8" href="/assets/css/summernote.css">
<script type="text/javascript" charset="utf-8" src="/assets/js/summernote.js"></script>
Note: Including the charset="utf-8" attribute is important.
Though an answer is already accepted, still I would like to post a better answer for people seeking a solution to the problem in question.
Of course this will work:
<link rel="stylesheet" type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.1/summernote.css">
But I prefer to STORE ASSETS LOCALLY. It eliminates the need of CDN which affects the loading time of the page its embedded in.
By default "summernote" looks for font-awesome icons (and some other summernote fonts) in the directory /css/font/:
//=================== The style-sheets stacking
<link type="text/css" rel="stylesheet" href="css/font-awesome.min.css">
<link type="text/css" rel="stylesheet" href="css/summernote.css">
//=================== The font goes here
/css/font/
So what u need to do is:
Download fontawesome,
Take out the fonts folder from the downloaded archive and rename it to font
Place the directory font inside the css directory of the project.
And this should work.
Considering your assets are available like this http://localhost:1337/css/font/summernote.ttf
//summernote.ttf is just an example
I hope this will help.
Thanks
Copy the font folder in your project css.
just like YourProject/css/font
that should work.
It's work with my project.
Do you have font-awesome included in your project? I believe that plugin uses font-awesome. If not, trying including this in your application.html.erb file as the src for a script tag: https://www.bootstrapcdn.com/fontawesome/
Also read this: https://github.com/summernote/summernote/issues/505
For anyone that may be having trouble with icons in MVC, it seems as though summernote looks at the base folder (in my case, Content) and the font folder needs to go in there. Here's a screenshot of my project's layout:
For whatever reason, summernote looks in the /summernote/font/ folder in Content rather than where summernote-lite.css is.
Hope this helps!
I found the same problem. The solution was I deleted the 'toolbar' key from the summernote config:
$(".summernote").summernote({
lang: 'hu-HU',
height: 300,
minHeight: null,
maxHeight: null,
toolbar: [
['font', ['roboto',]],
]
});
version: summernote v.0.8.12.
I'd like to pull in a static HTML file that I'll use as an Underscore template in my front-end JavaScript. I've tried the following with no luck:
<link rel="import" href="${resource(plugin: 'my-app-name', dir: 'tpl', file: 'foo.html')}"/>
<g:external dir="tpl" file="foo.html" type="html" />
The file sits at web-app/tpl/foo.html.
The ultimate goal is to use the new HTML import syntax to access the file's contents via JavaScript.
Why is that file at web-app/tpl?
Here's what you can do to import that template:
Move it to grails-app/views/tpl/.
Change the file name to _foo.gsp.
Use <g:render template="/tpl/foo" /> in your view to pull in that HTML.
Read more about the render tag here.
Also you can use an meta tag.
<meta name="layout" content="main"/>
And in the main.gsp tha must be at the view/layout/main.gsp you can use grails tags:
<g:layoutHead/>
and
<g:layoutBody/>
By the name you can understand that layoutHead insert head of your page to this layout. layout body insert body of page to this layout.
The following worked for me, though I'm not sure if it's the best solution: In UrMappings.groovy: static excludes = ['tpl/foo.html']. This made the link tag work in page.gsp <link rel="import" href="${resource(plugin: 'my-app-name', dir: 'tpl', file: 'foo.html')}"/>.
I've been battling this problem for over 48 hours now and I have been unable to find an answer anywhere on the net. Here's the setup:
My Android application is downloading content during first run (content is over 20MB) and the files are unzipped onto the user's SD card at /mnt/sdcard/{my package}/folder. The content includes HTML files, CSS files, JS files and images. Here's the full structure of what is written to the SD card (where / = /mnt/sdcard/{my package}/folder/):
/content/
a.html
b.html
images/
image1.jpg
/css/
c.css
d.css
/js/
e.js
f.js
Here is my code that loads the html file from the SD card:
webView = (WebView) findViewById(R.id.pageBrowser);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new LinkHandlerInterface(), "Android");
webView.setWebViewClient(new PageWebViewClient());
// contentLocation + url is equal to the full path to the html file
webView.loadUrl("file://" + contentLocation + url);
This code successfully loads the HTML page. No problems yet. Each page has the following head tag:
<link rel="stylesheet" type="text/css" href="../css/screen.css" media="all" />
<link rel="stylesheet" type="text/css" href="../css/inPractice.css" media="all" />
<link rel="stylesheet" type="text/css" href="../css/inPracticeScheme.css" media="all" />
<link rel="stylesheet" type="text/css" href="../css/mobile/iPad.css" media="all" />
<script type="text/javascript" src="../js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="../js/inPractice-utilities.js"></script>
<script type="text/javascript" src="../js/inPractice.js"></script>
<script type="text/javascript" src="../js/mobile/inpractice.ipad.js"></script>
Here is where the problem is. My WebView renders the HTML just fine. It even loads and applies the CSS perfectly. However, it refuses to load and execute the Javascript. If you remember from above, the js folder is, in fact, one leve up from the html file, so it's pointing to the correct place.
Here's a list of what I know:
The CSS I'm using is being applied fine, so I know the issue is not with the file location.
I used this same code before, but was loading the files from my application's assets folder (file:///android_assets/...) and it worked perfectly. Since the content is so large, I can't bundle it with my application, hence the move to the SD card.
If I change the HTML files in such a way that all the Javascript methods are listed inside a script tag, it works fine. I don't have control over the HTML, so I can't apply this change permanently. This tells me that the WebView has no problem executing the Javascript.
Images load fine.
I'm fresh out of ideas now. Does anyone have any clue why my WebView cannot load my Javascript files? Has anyone seen this before?
EDIT: Here are the JS files I'm trying to use can be viewed here:
http://www.automatastudios.com/clients/cco/inpractice/css/inPractice.css
http://www.automatastudios.com/clients/cco/inpractice/css/inPracticeScheme.css
http://www.automatastudios.com/clients/cco/inpractice/css/screen.css
http://www.automatastudios.com/clients/cco/inpractice/css/mobile/iPad.css
NOTE: These CSS files were not authored by me.
Was never able to find a solution to this.
I ended up just editing the HTML files, such that changed the Javascript source files to inline Javascript. That worked (as I expected it would).
The preferred way to to load a html which references js, css is to use
webView.loadDataWithBaseURL()
We need to pass the root directory of the location where the html,js,css are found on the file system as the baseURL. Important thing to note here is that we need to use "file" scheme URL only.
In your case code should be
String html = readFileAsString(
new FileInputStream("file://" + contentLocation + url) );
webView.loadDataWithBaseURL("file://" + contentLocation,html,"text/html","utf-8",null);
public static StringBuffer streamToString(InputStream stream ){
StringBuffer fileContent = new StringBuffer("");
try {
int size = stream.available();
byte[] buffer = new byte[size];
int length;
while ((length = stream.read(buffer)) != -1) {
fileContent.append(new String(buffer));
}
stream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
try {
stream.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return fileContent;
}
Hope the answer helps future visitors
PS:
The above code snippet is not compiled
As described in the title my problem is that qwebview doesn't load a html file correctly if it resides in my resources. It loads it perfectly if I load it from outside of the resources as normal local file. But this is not an option for me. I would like to bundle the file with the application.
EDIT: By the way, I'm talkin' about external resources from the web. (e.g. http://host.org/somejavascript.js)
Thanks for any help
Please take a look at the second parameter of
void QWebView::setHtml ( const QString & html, const QUrl & baseUrl = QUrl() )
According to documentation:
External objects such as stylesheets
or images referenced in the HTML
document are located relative to
baseUrl.
Below is code that works for me.
#include <QtCore/QFile>
#include <QtCore/QUrl>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
#include <QtWebKit/QWebView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
QWebView webview(&window);
QFile source(":/google.com.html");
source.open(QIODevice::ReadOnly);
webview.setHtml(QString::fromUtf8(source.readAll().constData()), QUrl("http://google.com"));
window.setCentralWidget(&webview);
window.show();
return app.exec();
}
External URLs must have a schema to make them external, otherwise "external.org/script.js" looks for "script.js" under the "external.org/" sub-path, "http://external.org/script.js" is an absolute URL.
Edit:
Say you have this HTML file as the resource ":/file.html" and it is coppied from "http://example.com/":
<html>
<head>
<title>My HTML</title>
<script type="text/javascript" src="/code.js"></scipt>
</head>
<body>
<img href="/image.jpg" />
</body>
</html>
Then to display this correctly you would need to do the following:
QFile res(":/file.html");
res.open(QIODevice::ReadOnly|QIODevice::Text);
my_webview.setHtml(res.readAll(), QUrl("http://example.com/");
That way, WebKit knows where to fetch "code.js" and "image.jpg" from. Using QWebView::load() will not work, as the root URL will be some internal URL, the one starting with qrc://, and WebKit will look for "code.js" and "image.jpg" in your applications resources. Basically, you can only use load() when all the relative URLs in the document come from the same place as the URL is pointing to. And if you used load(QUrl("qrc:///file.html")); in the case above, the URL (qrc:///file.html) is pointing to your resource system.
If you want to also include your resources in the HTML, you can use the qrc:// URLs in the HTML file.