cjwirth / RichEditorView

RichEditorView is a simple, modular, drop-in UIView subclass for Rich Text Editing.
BSD 3-Clause "New" or "Revised" License
1.9k stars 445 forks source link

Handle click on URL's? #217

Open hansemannn opened 4 years ago

hansemannn commented 4 years ago

Hey there,

does someone know how to handle clicks on links inserted to the editor? There does not seem to be a public API for this right now. Thanks in advance!

YoomamaFTW commented 4 years ago

@hansemannn Take a look at this: https://medium.com/@KentaKodashima/ios-wkwebview-tutorial-b7f8cf1bffe0

I think, with the RichEditorDelegate's shouldInteractWith url: URL function, you can instead 1) add a subview of a navigation controller, 2) use the tutorial from above to add goBack (web view's back button) and add a goForward (don't know its actual name) button, 3) set the AutoLayout constraints for the toolbar (if necessary; I dunno), then 4) add a back to actual app button with navigationController?.backBarButton.

With that function, you should always just return false... I guess?

I'm planning on making this sometime in December or January, but the above is what I have planned so maybe you can get a head start.

YoomamaFTW commented 4 years ago

https://github.com/coffellas-cto/GDWebViewController This might also work since it uses WKWebView rather than UIWebView, but it hasn't been updated to Swift 5 and doesn't seem to be maintained. Worth a try though.

YoomamaFTW commented 4 years ago

WARNING as of 11/23/2019: I did this on my phone, so it is NOT tested.

@hansemannn Finally had the time to rework the RichEditorView to Swift 5 while keeping a little bit of the functionality from cjwirth's repo and getting more, like dark mode and wkwebview, from cbess's repo (dark mode in assets/editor. Check commits). I didn't customize the editing link at all, so it is just a plain UIAlertController. Here's the basics of what I've got:

extension ViewController: RichEditorToolbarDelegate {
    func richEditorToolbarInsertLink(_ toolbar: RichEditorToolbar) {
        let alertController = UIAlertController(title: "Enter link and text", message: "You can leave the text empty to just show a clickable link", preferredStyle: .alert)
        let confirmAction = UIAlertAction(title: "Enter", style: .default) { (_) in
            let link = alertController.textFields?[0].text
            let text = alertController.textFields?[1].text
            toolbar.editor?.insertLink(link!, title: text ?? link!)
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
        alertController.addAction(confirmAction)
        alertController.addAction(cancelAction)
        self.present(alertController, animated: true, completion: nil)
        toolbar.editor?.hasRangeSelection(handler: { r in
            if r == true {
                alertController.addTextField { (textField) in
                    textField.placeholder = "Link"
                    self.editorView.getSelectedHref(handler: {alink in
                        textField.text = alink
                    })
                }
                alertController.addTextField { (textField) in
                    textField.placeholder = "Text (Shows a clickable text that leads to link)"
                    self.editorView.runJS("document.getSelection().getRangeAt(0).toString()") { text in
                        textField.text = text
                    }
                }
            } else {
                alertController.addTextField { (textField) in
                    textField.placeholder = "Link"
                }
                alertController.addTextField { (textField) in
                    textField.placeholder = "Text (Shows a clickable text that leads to link)"
                }
            }
        })
    }
}

I added a method for being able to insert a link without anything selected, unlike the sample. I also added functionality for editing links IF a range was selected.

I also added functionality for the UIMenuController, which is the menu that pops up if you want to press the "Select" or "Select All" button. If you go into your view controller, which we'll call ViewController, add this to the viewDidLoad func:

let editLink = UIMenuItem(title: "Edit Link", action: #selector(menuEditLinkPressed))
UIMenuController.shared.menuItems = [editLink]
UIMenuController.shared.update()

Here's the objc func:

    @objc func menuEditLinkPressed() {
        if editorView.isFocused == false { editorView.focus() }
        richEditorToolbarInsertLink(toolbar)
    }

This is assuming that the content is editable and you already set a property toolbar because you still need some kind of accessory view. You can still hide the toolbar by simply making the frame be zero if you're doing something like Google Docs which has some options in its navigation bar.

Edit 1: I just realized that the getSelectedHref func is not the same for everyone. I'm using cbess's function here. For those still using cjwirth's, you'll be writing: textField.text = self.editorView.getSelectedHref() I think I also changed the runJS functionality, as well. Check the source code for how to properly the runJS function for getting the text. I THINK, not 100% sure, but it could be this: textField.text = self.editorView.runJS("document.getSelection().getRangeAt(0).toSelect()")

fukemy commented 3 years ago

not working to me