ionic-team / ionic-v3

The repo for Ionic 3.x. For the latest version of Ionic, please see https://github.com/ionic-team/ionic
Other
128 stars 85 forks source link

Text highlight on native webviews (iOS & Android) cannot be removed through client side JavaScript Code. #972

Open chiemekailo opened 5 years ago

chiemekailo commented 5 years ago

I'm submitting a ... (check one with "x") [ ] bug report [x] feature request

Text highlight on native webviews (iOS & Android) cannot be removed through client side JavaScript Code.

Need a directive to clear selection on native Webview.

Expected behavior and actual behavior.

Expected Behavior

native_popup

Actual Behavior

residual_webview_layer_selection

Steps to reproduce the problem.

  1. Allow text highlight for intended module, target element is a <div> element with inner text. In app.scss
    .classForDivToBeTextSelectable {
    -webkit-user-select: text;
    -moz-user-select: text;
    -ms-user-select: text;
    user-select: text;   
    }
  2. Zero out (selection's range object) and remove selection object to deselect text. Do this in the “selectionchange” & “touchend” events. In reader-page.ts

    
    // add touch events
    this.favoritesHighlightListenFunc = this.renderer.listen(document, 'selectionchange', (event) => {
    // Do something with 'event'
    
    if(!this.hasCalledSelectListenFunction){
    this.hasCalledSelectListenFunction = true;
    
    event.preventDefault();
    event.stopPropagation();
    
    var sel = window.getSelection();
    console.log('sel: (press) '+ sel.toString());
    
    if(this.platform.is('android')){
      this.d1350 = true;  //for Android
      this.shunTap = false;
    
      var range = document.createRange();
      range.setStart(sel.anchorNode,sel.anchorOffset);
      range.setEnd(sel.focusNode,sel.focusOffset);
      range.collapse(true);
      sel.removeAllRanges();
      sel.addRange(range);
    }else{
      sel.empty();
    }
    }

}); this.favoritesTouchupListenFunc = this.renderer.listen(document, 'touchend', (event) => { // Do something with 'event' var duration: number = 50; duration = (this.platform.is('android')) ? 0 : duration;

setTimeout(() => {
  console.log('sel: (my precious selection) '+ window.getSelection().toString());

  if(this.platform.is('android')){
    if(this.d1350 && !this.shunTap){
      this.d1350 = false;
      this.shunTap = true;
      this.tapEvent(event, window.getSelection());
    }
  }else{
    this.tapEvent(event, window.getSelection());
  }

  this.hasCalledSelectListenFunction = false;
}, duration);

});


3. Run the app, and then touch and hold text on the target view/element, then lift touch. _Observe the webview is still highlighted even though the underlying html DOM selection Object has been removed._

## Solution Suggestion
1. A Cordova bridge update to the necessary *.m and *.java files to clear the native side highlights on the UIWebview/Webview layer, using a JavaScript client call.
2. A suggestion as to how to “hack” the necessary native files currently to produce desired result in the interim.

## Ionic Project & NodeJS platform Specifications.
npm: 6.5.0-next.0
node: 11.6.0
angular: 5.2.9
ionic (Ionic CLI): 4.6.0
Ionic Framework: ionic-angular 3.9.2
@ionic/app-scripts: 3.2.1
cordova (Cordova CLI): 8.1.2 (cordova-lib@8.1.1)
Cordova Platforms: android 6.4.0, browser 5.0.3, ios 4.5.4
Android SDK Tools: 26.1.1 (/Users/chiemekailo/Library/Android/sdk)
ios-deploy: 1.9.4
heidji commented 5 years ago

I'm curious, what's your endgame? you want to make a custom bubble? that's probably impossible because creating a text highlighter with JS seems either very hard or impossible. ionic can't help you either because as you said it, it's a webview native function and cannot be manipulated unless you can create your own webview somehow, and a bridge isn't possible either because cordova can't access the content of the webview..

chiemekailo commented 5 years ago

Hi @heidji thanks for your contribution. I actually want to present action options to the user using the ActionSheetController after a long tap. That is why I don't want the callouts showing.

ionic can't help you either because as you said it, it's a webview native function and cannot be manipulated unless you can create your own webview somehow

Actually, this is in ionic's purview as I am not referencing an independent Cordova plugin or its equivalent ionic wrapper, but the closely integrated web view . They actually stated (Ionic maintains a Web View plugin for apps integrated with Cordova. https://ionicframework.com/docs/building/webview)

, and a bridge isn't possible either because cordova can't access the content of the webview..

If you look at this code here, you'll see that it can be approached natively (Properties 'webkitTouchCallout' & 'KhtmlUserSelect' do not exist on type 'CSSStyleDeclaration'). And that is for iOS, to be run from the Objective-C/Swift context. Android's will be similar. This is where Cordova could come in.

gmontielarvas commented 3 years ago

@chiemekailo Hi, I'm trying to do exactly what you are saying, i want to select some text and not to see the default context menu on android and iOS. Im using epubjs, when i select a range, i show an Action Sheet and works ok, but its inconvenient that the default menu shows before my custom action sheet. Did you find a workaround for this?