Skip to content
This repository has been archived by the owner on Nov 26, 2020. It is now read-only.

Custom click listener - closes #132 #137

Merged
merged 14 commits into from
Sep 15, 2016
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion Source/FolioReaderConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import UIKit

// MARK: - FolioReaderScrollDirection

/**
Defines the Reader scrolling direction
*/
Expand Down Expand Up @@ -37,12 +39,54 @@ public enum FolioReaderScrollDirection: Int {
}
}

// MARK: - ClassBasedOnCLickListener

/**
A `ClassBasedOnCLickListener` takes a closure which is performed if a given html `class` is clicked. The closure will reveice the content of the specified parameter.

Eg. A ClassBasedOnCLickListener with the className "quote" and parameterName "id" with the given epub html content "<section class="quote" id="12345">" would call the given closure on a click on this section with the String "12345" as parameter.

*/
public struct ClassBasedOnCLickListener {
Copy link
Member

@hebertialmeida hebertialmeida Sep 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could simplify this name, it is a little confused for me, what do you think?

Also there is a typo ClassBasedOnCLickListener should be ClassBasedOnClickListener

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will fix it to ClassBasedOnClickListener. I'm don't have a better naming yet as the current one describes the function really good. To just use OnClickListener or sth. similiar wouln't be clear about it's function and usage.

What name do you have in mind?


/// The name of the URL scheme which should be used. Note: Make sure that the given `String` is a valid as scheme name.
public var schemeName : String

/// The HTML class name to which the listener should be added.
public var className : String

/// The name of the parameter whose content should be passed to the `onClickAction` action
public var parameterName : String

/// The closure which will be called if the specified class was clicked.
public var onClickAction : ((parameterContent: String?) -> Void)

/// Initializes a `ClassBasedOnCLickListener` instance. Append it to the `classBasedOnClickListeners` property from the `FolioReaderConfig` to receive on click events.
public init(schemeName: String, className: String, parameterName: String, onClickAction: ((parameterContent: String?) -> Void)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition we would change the className to querySelector and maybe add a new Bool attribute selectAll with true by default, so I can choose to select only first element or all elements. What do you think?

self.schemeName = schemeName.lowercaseString
self.className = className
self.parameterName = parameterName
self.onClickAction = onClickAction
}
}

// MARK: - FolioReaderConfig

/**
Defines the Reader custom configuration
*/
public class FolioReaderConfig: NSObject {


// MARK: ClassBasedOnCLickListener

/**
Array of `ClassBasedOnCLickListener` objects. A `ClassBasedOnCLickListener` takes a closure which is performed if a given html `class` is clicked. The closure will reveice the content of the specified parameter.

Eg. A ClassBasedOnCLickListener with the className "quote" and parameterName "id" with the given epub html content "<section class="quote" id="12345">" would call the given closure on a click on this section with the String "12345" as parameter.

*/
public var classBasedOnClickListeners = [ClassBasedOnCLickListener]()

// MARK: Colors

/// Base header custom TintColor
Expand Down
40 changes: 35 additions & 5 deletions Source/FolioReaderPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ public class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGesture
// MARK: - UIWebView Delegate

public func webViewDidFinishLoad(webView: UIWebView) {

// Add the custom class based onClick listener
self.setupClassBasedOnClickListeners()

refreshPageMode()

if readerConfig.enableTTS && !book.hasAudio() {
Expand Down Expand Up @@ -231,11 +235,28 @@ public class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGesture
FolioReader.sharedInstance.readerCenter.presentViewController(nav, animated: true, completion: nil)
}
return false
} else if UIApplication.sharedApplication().canOpenURL(url) {
UIApplication.sharedApplication().openURL(url)
return false
}

} else {
// Check if the url is a custom class based onClick listerner
var isClassBasedOnClickListenerScheme = false
for listener in readerConfig.classBasedOnClickListeners {
if url.scheme == listener.schemeName {
let parameterContentString = (request.URL?.absoluteString.stringByReplacingOccurrencesOfString("\(url.scheme)://", withString: "").stringByRemovingPercentEncoding)
listener.onClickAction(parameterContent: parameterContentString)
isClassBasedOnClickListenerScheme = true
}
}

if isClassBasedOnClickListenerScheme == false {
// Try to open the url with the system if it wasn't a custom class based click listener
if UIApplication.sharedApplication().canOpenURL(url) {
UIApplication.sharedApplication().openURL(url)
return false
}
} else {
return false
}
}

return true
}

Expand Down Expand Up @@ -391,6 +412,15 @@ public class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGesture
colorView.frame = CGRectZero
}
}

// MARK: - Class based click listener

private func setupClassBasedOnClickListeners() {

for listener in readerConfig.classBasedOnClickListeners {
self.webView.js("addClassBasedOnClickListener(\"\(listener.schemeName)\", \"\(listener.className)\", \"\(listener.parameterName)\")");
}
}
}

// MARK: - WebView Highlight and share implementation
Expand Down
19 changes: 18 additions & 1 deletion Source/Resources/Bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ var callHighlightURL = function(elm) {
window.location = URLBase + encodeURIComponent(currentHighlightRect);
}


// Reading time
function getReadingTime() {
var text = document.body.innerText;
Expand Down Expand Up @@ -579,4 +578,22 @@ function wrappingSentencesWithinPTags(){
}

guessSenetences();
}

// Class based onClick listener

function addClassBasedOnClickListener(schemeName, className, parameterName) {
// Get all elements with the given className
var elements = document.getElementsByClassName(className);
Copy link
Member

@hebertialmeida hebertialmeida Sep 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about it, maybe we could use the JavaScript querySelector or querySelectorAll, instead of just getElementsByClassName. The querySelector is like jQuery, so we can do like "#someID", ".someclass", "h1" or any kind of complex selection.

Reference:
https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector

Complex query:

var el = document.querySelector("div.user-panel.main input[name=login]");

Copy link
Member Author

@tschob tschob Sep 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More option sound good, I'll give it a try.

for (elementIndex = 0; elementIndex < elements.length; elementIndex++) {
var element = elements[elementIndex];
// Get the content from the given parameterName
var parameterContent = element.getAttribute(parameterName);
// Add the on click logic
element.setAttribute("onclick", "onClassBasedListenerClick(\"" + schemeName + "\", \"" + parameterContent + "\");");
}
}

var onClassBasedListenerClick = function(schemeName, parameterContent) {
window.location = schemeName + "://" + encodeURIComponent(parameterContent);
}