6

By implementation of FlutterWebviewPlugin, I want to show a particular website in a widget but without header and footer. is this possible in Flutter? I guess there is a function in FlutterWebviewPlugin class .evalJavascript('some code') but don't know how to use this function. can I add javascript code to this?

import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

String url = "https://flutter.io/";

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Webview Example',
      theme: ThemeData.dark(),
      routes: {
        "/": (_) => Home(),
        "/webview": (_) => WebviewScaffold(
          url: url,
          withJavascript: true,
          withLocalStorage: true,
          withZoom: true,
        )
      },
    );
  }
}

class Home extends StatefulWidget {
  @override
  HomeState createState() => HomeState();
}

class HomeState extends State<Home> {
  final webView = FlutterWebviewPlugin();
  TextEditingController controller = TextEditingController(text: url);

  @override
  void initState() {
    super.initState();
    webView.close();
    controller.addListener(() {
      url = controller.text;
    });
  }
  @override
  void dispose() {
    webView.dispose();
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("WebView"),
        ),
        body: Center(
          child: Column(
            children: <Widget>[
              Container(
                padding: EdgeInsets.all(10.0),
                child: TextField(
                  controller: controller,
                ),
              ),
              RaisedButton(
                child: Text("Open Webview"),
                onPressed: () {

                  Navigator.of(context).pushNamed("/webview");
                },
              )
            ],
          ),
        )
    );
  }
}
2

4 Answers 4

10

I suggest using Flutter's official WebView plugin: webview_flutter

The plugin also has a method that can run Javascript using WebViewController.evaluateJavascript(String). This method is recommended to be run after WebView.onPageFinished callback.

Your WebView widget should look like this.

WebView(
    initialUrl: 'https://flutter.dev',
    javascriptMode: JavascriptMode.unrestricted,
    onWebViewCreated: (WebViewController webViewController) {
      _webViewController = webViewController;
      _controller.complete(webViewController);
    },
    onProgress: (int progress) {
      print("WebView is loading (progress : $progress%)");
    },
    onPageStarted: (String url) {
      print('Page started loading: $url');
    },
    onPageFinished: (String url) {
      print('Page finished loading: $url');

      // Removes header and footer from page
      _webViewController
          .evaluateJavascript("javascript:(function() { " +
              "var head = document.getElementsByTagName('header')[0];" +
              "head.parentNode.removeChild(head);" +
              "var footer = document.getElementsByTagName('footer')[0];" +
              "footer.parentNode.removeChild(footer);" +
              "})()")
          .then((value) => debugPrint('Page finished loading Javascript'))
          .catchError((onError) => debugPrint('$onError'));
      },
);

Here's a complete sample that you can try.

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final Completer<WebViewController> _controller =
      Completer<WebViewController>();

  WebViewController _webViewController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Builder(builder: (BuildContext context) {
        return WebView(
          initialUrl: 'https://flutter.dev',
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (WebViewController webViewController) {
            _webViewController = webViewController;
            _controller.complete(webViewController);
          },
          onProgress: (int progress) {
            print("WebView is loading (progress : $progress%)");
          },
          javascriptChannels: <JavascriptChannel>{
            _toasterJavascriptChannel(context),
          },
          navigationDelegate: (NavigationRequest request) {
            if (request.url.startsWith('https://www.youtube.com/')) {
              print('blocking navigation to $request}');
              return NavigationDecision.prevent;
            }
            print('allowing navigation to $request');
            return NavigationDecision.navigate;
          },
          onPageStarted: (String url) {
            print('Page started loading: $url');
          },
          onPageFinished: (String url) {
            print('Page finished loading: $url');

            _webViewController
                .evaluateJavascript("javascript:(function() { " +
                    "var head = document.getElementsByTagName('header')[0];" +
                    "head.parentNode.removeChild(head);" +
                    "var footer = document.getElementsByTagName('footer')[0];" +
                    "footer.parentNode.removeChild(footer);" +
                    "})()")
                .then((value) => debugPrint('Page finished loading Javascript'))
                .catchError((onError) => debugPrint('$onError'));
          },
          gestureNavigationEnabled: true,
        );
      }),
    );
  }

  JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
    return JavascriptChannel(
        name: 'Toaster',
        onMessageReceived: (JavascriptMessage message) {
          // ignore: deprecated_member_use
          Scaffold.of(context).showSnackBar(
            SnackBar(content: Text(message.message)),
          );
        });
  }
}

How the app looks running

demo

Sign up to request clarification or add additional context in comments.

1 Comment

.evaluateJavascript() has been removed. The recommended way is to use .runJavaScript and .runJavaScriptReturningResult
6
_webViewController.runJavascript(
          "document.getElementsByTagName('header')[0].style.display='none'");
      _webViewController.runJavascript(
          "document.getElementsByTagName('footer')[0].style.display='none'");

Comments

3

You can use the flutter_inappwebview plugin (I'm the author) and inject an UserScript at UserScriptInjectionTime.AT_DOCUMENT_START to hide or remove HTML elements when the web page loads (check JavaScript - User Scripts official docs for User Scripts details).

As I have already answered here for a similar issue, here is a code example using the current latest version 6 (6.0.0-beta.18) with URL https://getmobie.de/impressum that removes the header and footer HTML elements:

import 'dart:collection';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (!kIsWeb &&
      kDebugMode &&
      defaultTargetPlatform == TargetPlatform.android) {
    await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
  }
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("InAppWebView test"),
        ),
        body: Column(children: <Widget>[
          Expanded(
            child: InAppWebView(
              key: webViewKey,
              initialUrlRequest:
                  URLRequest(url: WebUri("https://getmobie.de/impressum")),
              initialUserScripts: UnmodifiableListView([
                UserScript(source: """
                window.addEventListener('DOMContentLoaded', function(event) {
                  var header = document.querySelector('.elementor-location-header'); // use here the correct CSS selector for your use case
                  if (header != null) {
                    header.remove(); // remove the HTML element. Instead, to simply hide the HTML element, use header.style.display = 'none';
                  }
                  var footer = document.querySelector('.elementor-location-footer'); // use here the correct CSS selector for your use case
                  if (footer != null) {
                    footer.remove(); // remove the HTML element. Instead, to simply hide the HTML element, use footer.style.display = 'none';
                  }
                });
                """, injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START)
              ]),
              onWebViewCreated: (controller) {
                webViewController = controller;
              },
            ),
          ),
        ]));
  }
}

For your use case, use the right CSS selector inside the user script js source to correctly get and remove the header and footer HTML elements from your web page!

Android example iOS example

1 Comment

this is not working for me. can you help me
0

Lorenzo's answer answer didn't work for me well. The element always returned null. So here's can be a possible solution:

onLoadStop{
  _webViewController.evaluateJavascript(
  source:"
     var main = document.querySelector('#__next'); 
     var header = main.querySelector('.sc-FTTUS.jnFTCj'); 
     var footer = document.getElementsByTagName('footer')[0];
     header.remove(); 
     footer.remove()"
);
}

using such nested locator,it worked well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.