foliokit 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +17 -0
- data/assets/foliokit.css +2 -0
- data/assets/foliokit.js +18 -0
- data/bin/foliokit +4 -0
- data/lib/foliokit.rb +39 -0
- data/lib/foliokit/article.rb +47 -0
- data/lib/foliokit/asset_rendition.rb +54 -0
- data/lib/foliokit/base.rb +7 -0
- data/lib/foliokit/command.rb +81 -0
- data/lib/foliokit/content_stack.rb +57 -0
- data/lib/foliokit/event.rb +88 -0
- data/lib/foliokit/exporter.rb +106 -0
- data/lib/foliokit/issue.rb +92 -0
- data/lib/foliokit/manifest.rb +72 -0
- data/lib/foliokit/manifest_article.rb +55 -0
- data/lib/foliokit/manifest_folio.rb +9 -0
- data/lib/foliokit/modules/core.rb +9 -0
- data/lib/foliokit/modules/element.rb +99 -0
- data/lib/foliokit/overlay.rb +20 -0
- data/lib/foliokit/overlay/overlay360.rb +50 -0
- data/lib/foliokit/overlay/overlay_audio.rb +29 -0
- data/lib/foliokit/overlay/overlay_base.rb +108 -0
- data/lib/foliokit/overlay/overlay_button.rb +24 -0
- data/lib/foliokit/overlay/overlay_container.rb +10 -0
- data/lib/foliokit/overlay/overlay_hyperlink.rb +87 -0
- data/lib/foliokit/overlay/overlay_image.rb +18 -0
- data/lib/foliokit/overlay/overlay_imagepan.rb +36 -0
- data/lib/foliokit/overlay/overlay_video.rb +42 -0
- data/lib/foliokit/overlay/overlay_webview.rb +57 -0
- data/lib/foliokit/package.rb +123 -0
- data/lib/foliokit/slide.rb +9 -0
- data/lib/foliokit/state.rb +6 -0
- data/lib/foliokit/types/bounds.rb +47 -0
- data/lib/foliokit/types/source.rb +9 -0
- data/lib/foliokit/version.rb +3 -0
- metadata +269 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
module Foliokit
|
2
|
+
class Issue
|
3
|
+
attr_reader :dir, :pages, :slides, :title, :description, :width, :height, :package
|
4
|
+
|
5
|
+
def initialize(file, dir, from: nil, to: nil)
|
6
|
+
@dir = dir
|
7
|
+
|
8
|
+
# Convert article to folio
|
9
|
+
@package = Foliokit::Package.new(file, dir, dir)
|
10
|
+
@title = package.manifest.title
|
11
|
+
@description = package.manifest.description
|
12
|
+
@width = package.manifest.device_width
|
13
|
+
@height = package.manifest.device_height
|
14
|
+
@from = from
|
15
|
+
@to = to
|
16
|
+
@pages = []
|
17
|
+
|
18
|
+
# Add Sub-Folio Content Stacks
|
19
|
+
if @package.manifest.article
|
20
|
+
convert_article!
|
21
|
+
else
|
22
|
+
if package.subfolios(package).any?
|
23
|
+
convert_folio!
|
24
|
+
else
|
25
|
+
convert_sub_folio!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def store_assets(assets_dir)
|
31
|
+
assets_dir.delete
|
32
|
+
dir.dir("assets").copy(assets_dir)
|
33
|
+
end
|
34
|
+
|
35
|
+
def export
|
36
|
+
document = Nokogiri::HTML("<html><head><title>#{title}</title><body></body></html>")
|
37
|
+
body = document.at("body")
|
38
|
+
pages.each do |page|
|
39
|
+
body << page.export(document)
|
40
|
+
end
|
41
|
+
document
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_html
|
45
|
+
export.to_html
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def convert_article!
|
51
|
+
manifest = package.subfolios(package).first.manifest
|
52
|
+
articles = manifest.content_stacks.first.articles[from..to]
|
53
|
+
if manifest.layout == "vertical"
|
54
|
+
@slides = [Slide.new(articles)]
|
55
|
+
else
|
56
|
+
@slides = articles.map do |article|
|
57
|
+
Slide.new([article])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def convert_folio!
|
63
|
+
subpackages = package.subfolios(package)[from..to]
|
64
|
+
@slides = subpackages.map do |subpackage|
|
65
|
+
slide = Slide.new
|
66
|
+
subpackage.manifest.content_stacks.each do |content_stack|
|
67
|
+
slide.articles.push(*content_stack.articles)
|
68
|
+
end
|
69
|
+
slide
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def convert_sub_folio!
|
74
|
+
package.root_package = package
|
75
|
+
manifest = package.manifest
|
76
|
+
articles = manifest.content_stacks.first.articles[from..to]
|
77
|
+
@slides = [Slide.new(articles)]
|
78
|
+
end
|
79
|
+
|
80
|
+
def from
|
81
|
+
@from || 0
|
82
|
+
end
|
83
|
+
|
84
|
+
def to
|
85
|
+
if package.manifest.article
|
86
|
+
@to || (package.subfolios(package).first.manifest.content_stacks.first.articles.count - 1)
|
87
|
+
else
|
88
|
+
@to || (package.subfolios(package).count - 1)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'foliokit/modules/element'
|
2
|
+
|
3
|
+
module Foliokit
|
4
|
+
class Manifest
|
5
|
+
include Modules::Element
|
6
|
+
|
7
|
+
def self.element_base
|
8
|
+
element_reader :id, type: :s
|
9
|
+
element_reader :version, type: :s
|
10
|
+
element_reader :targetViewer, type: :s
|
11
|
+
element_reader :lastUpdated, type: :s
|
12
|
+
element_reader :date, type: :s
|
13
|
+
element_reader :bindingDirection, type: :s
|
14
|
+
element_reader :orientation, type: :s
|
15
|
+
element_reader :title, type: :s, selector: "metadata > magazineTitle", text: true
|
16
|
+
element_reader :description, type: :s, selector: "metadata > description", text: true
|
17
|
+
element_reader :article, type: :bool
|
18
|
+
end
|
19
|
+
|
20
|
+
def target_dimension
|
21
|
+
element.css("targetDimensions targetDimension").first
|
22
|
+
end
|
23
|
+
|
24
|
+
def wide_dimension
|
25
|
+
target_dimension["wideDimension"].to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def narrow_dimension
|
29
|
+
target_dimension["narrowDimension"].to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
def device_height
|
33
|
+
(orientation == "landscape") ? narrow_dimension : wide_dimension
|
34
|
+
end
|
35
|
+
|
36
|
+
def device_width
|
37
|
+
(orientation == "landscape") ? wide_dimension : narrow_dimension
|
38
|
+
end
|
39
|
+
|
40
|
+
def referenced_ids
|
41
|
+
@_referenced_ids ||= begin
|
42
|
+
element.css("action[@target]").map { |action| hashify(action["target"]) } | element.css("action[@state]").map { |action| hashify(action["state"]) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def valid_overlay_id?(id)
|
47
|
+
overlay_ids.include?(id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def valid_referenced_id?(id)
|
51
|
+
referenced_ids.include?(id)
|
52
|
+
end
|
53
|
+
|
54
|
+
def overlay_ids
|
55
|
+
@_overlay_ids ||= begin
|
56
|
+
element.css("overlay[@id]").map { |overlay| hashify(overlay["id"]) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def content_stack_ids
|
61
|
+
element.css("contentStacks contentStack").map { |s| s["id"] }
|
62
|
+
end
|
63
|
+
|
64
|
+
def content_stacks
|
65
|
+
element.css("contentStacks contentStack:not(:empty)").map { |element| ContentStack.new(element, package) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def subfolios
|
69
|
+
element.css("contentStacks contentStack[@subfolio]:empty")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Foliokit
|
2
|
+
class ManifestArticle < Manifest
|
3
|
+
element_base
|
4
|
+
element_reader :layout, type: :s
|
5
|
+
|
6
|
+
def initialize(file, package)
|
7
|
+
article = Nokogiri::XML(file.read).css("article").first
|
8
|
+
# article["smoothScrolling"] = true
|
9
|
+
article.css("content page rendition").each do |rendition|
|
10
|
+
rendition.name = "assetRendition"
|
11
|
+
rendition["source"] = rendition.remove_attribute("href")
|
12
|
+
end
|
13
|
+
article.css("content page").each do |page|
|
14
|
+
page.name = "asset"
|
15
|
+
end
|
16
|
+
|
17
|
+
# build manifest
|
18
|
+
root_manifest = package.root_package.manifest
|
19
|
+
xml = Nokogiri::XML::Builder.new do |b|
|
20
|
+
b.folio(id: file.dir.name, version: root_manifest.version, targetViewer: root_manifest.target_viewer, lastUpdated: root_manifest.last_updated, date: root_manifest.date, bindingDirection: root_manifest.binding_direction, orientation: root_manifest.orientation, layout: article["layout"]) do
|
21
|
+
b.metadata do
|
22
|
+
b.description root_manifest.description
|
23
|
+
b.magazineTitle root_manifest.title
|
24
|
+
b.folioNumber root_manifest.title
|
25
|
+
end
|
26
|
+
b.targetDimensions do
|
27
|
+
b.targetDimension(wideDimension: root_manifest.wide_dimension, narrowDimension: root_manifest.narrow_dimension)
|
28
|
+
end
|
29
|
+
b.contentStacks do
|
30
|
+
b.contentStack(id: file.dir.name, version: article["version"], lastUpdated: article["lastUpdated"], smoothScrolling: article["smoothScrolling"], layout: article["layout"], alwaysDisplayOverlays: article["alwaysDisplayOverlays"], orientation: article["orientation"]) do
|
31
|
+
b.content do
|
32
|
+
b.regions do
|
33
|
+
b.region do
|
34
|
+
b.bounds do
|
35
|
+
b.rectangle(x: 0, y: 0, width: article[:width], height: article[:height])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
b.assets do |assets_node|
|
40
|
+
article.css("content asset").each do |asset|
|
41
|
+
b.parent << asset
|
42
|
+
end
|
43
|
+
end
|
44
|
+
if file.dir.file("Overlays.xml").exists?
|
45
|
+
b.parent << Nokogiri::XML(file.dir.file("Overlays.xml").read).css("overlays").first
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
super(xml.doc.root, package)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Foliokit
|
2
|
+
module Modules
|
3
|
+
module Element
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do |cls|
|
7
|
+
class << cls
|
8
|
+
attr_accessor :element_reader_attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.element_reader(name, options = {})
|
12
|
+
attr_accessor name.to_s.underscore
|
13
|
+
self.element_reader_attributes ||= {}
|
14
|
+
self.element_reader_attributes[name] = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def hashify(value)
|
18
|
+
hashable = "#{package.id}/#{value}"
|
19
|
+
"id_#{Digest::MD5.hexdigest(hashable)}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.element_collection(name, selector, klass = nil)
|
23
|
+
define_method :"#{name}" do
|
24
|
+
(element > selector).map do |el|
|
25
|
+
if klass and klass.class == Module
|
26
|
+
klass.factory(el, package)
|
27
|
+
elsif klass
|
28
|
+
klass.new(el, @package)
|
29
|
+
else
|
30
|
+
el
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.element_xpath(name, selector, klass)
|
37
|
+
define_method :"#{name}" do
|
38
|
+
el = element.xpath(selector).first
|
39
|
+
if klass.class == Module
|
40
|
+
klass.factory(el, package)
|
41
|
+
else
|
42
|
+
klass.new(el, @package)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.element_xpath_collection(name, selector, klass)
|
48
|
+
define_method :"#{name}" do
|
49
|
+
element.xpath(selector).map do |el|
|
50
|
+
if klass.class == Module
|
51
|
+
klass.factory(el, package)
|
52
|
+
else
|
53
|
+
klass.new(el, @package)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
attr_reader :package
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
attr_reader :element
|
64
|
+
end
|
65
|
+
|
66
|
+
def initialize(element, package)
|
67
|
+
@element = element
|
68
|
+
@package = package
|
69
|
+
self.class.element_reader_attributes.each do |name, options|
|
70
|
+
key = name.to_s.underscore
|
71
|
+
value = nil
|
72
|
+
target = element
|
73
|
+
if options[:selector]
|
74
|
+
if options[:selector].respond_to?(:call)
|
75
|
+
target = (target > instance_exec(options, &(options[:selector]))).first
|
76
|
+
else
|
77
|
+
target = (target > options[:selector]).first
|
78
|
+
end
|
79
|
+
end
|
80
|
+
unless target.nil?
|
81
|
+
if options[:type].class == Class
|
82
|
+
value = options[:type].convert(target, name, options)
|
83
|
+
else
|
84
|
+
attribute_name = options[:attribute] || name
|
85
|
+
value = options[:text] ? target.text.strip : target[attribute_name]
|
86
|
+
unless value.nil?
|
87
|
+
value = value.send(:"to_#{options[:type]}") unless options[:type].nil?
|
88
|
+
value.gsub!(/\s/, "_") if options[:clean]
|
89
|
+
value = hashify(value) if options[:hash]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
value = options[:default] if value.nil? and options[:default]
|
94
|
+
instance_variable_set("@#{key}", value)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Foliokit
|
2
|
+
module Overlay
|
3
|
+
extend ActiveSupport::Autoload
|
4
|
+
autoload :OverlayBase
|
5
|
+
autoload :OverlayContainer
|
6
|
+
autoload :OverlayHyperlink
|
7
|
+
autoload :OverlayImage
|
8
|
+
autoload :OverlayButton
|
9
|
+
autoload :Overlay360
|
10
|
+
autoload :OverlayImagepan
|
11
|
+
autoload :OverlayAudio
|
12
|
+
autoload :OverlayVideo
|
13
|
+
autoload :OverlayWebview
|
14
|
+
|
15
|
+
def self.factory(el, package)
|
16
|
+
klass = "Foliokit::Overlay::Overlay#{el[:type].camelcase}".constantize
|
17
|
+
klass.new(el, package)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Foliokit
|
2
|
+
module Overlay
|
3
|
+
class Overlay360 < OverlayBase
|
4
|
+
element_base
|
5
|
+
element_reader :clockwise, type: "bool", selector: "data", attribute: "clockwise"
|
6
|
+
element_reader :loopCount, type: "i", selector: "data > loopCount", text: true
|
7
|
+
element_reader :autoStart, type: "bool", selector: "data > autoStart", text: true
|
8
|
+
element_reader :autoStartDelay, type: "f", selector: "data > autoStartDelay", text: true
|
9
|
+
element_reader :tapEnabled, type: "bool", selector: "data > tapEnabled", text: true
|
10
|
+
element_reader :swipeEnabled, type: "bool", selector: "data > swipeEnabled", text: true
|
11
|
+
element_reader :circularViewEnabled, type: "bool", selector: "data > circularViewEnabled", text: true
|
12
|
+
element_reader :autoPlayStopAtLast, type: "bool", selector: "data > autoPlayStopAtLast", text: true
|
13
|
+
element_reader :framesPerSecond, type: "f", selector: "data > framesPerSecond", text: true
|
14
|
+
element_collection :images, "data > overlayAsset"
|
15
|
+
|
16
|
+
def tagname
|
17
|
+
"div"
|
18
|
+
end
|
19
|
+
|
20
|
+
def export(document, options = {})
|
21
|
+
node = super(document, options)
|
22
|
+
node["clockwise"] = clockwise
|
23
|
+
node["auto-start"] = auto_start
|
24
|
+
node["auto-start-delay"] = auto_start_delay
|
25
|
+
node["tap-enabled"] = tap_enabled
|
26
|
+
node["swipe-enabled"] = swipe_enabled
|
27
|
+
node["circular-view-enabled"] = circular_view_enabled
|
28
|
+
node["auto-play-stop-at-last"] = auto_play_stop_at_last
|
29
|
+
node["frames-per-second"] = frames_per_second
|
30
|
+
|
31
|
+
# build container
|
32
|
+
container = Nokogiri::XML::Node.new("div", document)
|
33
|
+
container["class"] = "circlr-container"
|
34
|
+
if node["swipe-enabled"] == "true"
|
35
|
+
container["class"] += " prevent-swipe-horizontal prevent-swipe-vertical"
|
36
|
+
container["touchable"] = true
|
37
|
+
end
|
38
|
+
node << container
|
39
|
+
|
40
|
+
# build images
|
41
|
+
images.each do |image|
|
42
|
+
img = Nokogiri::XML::Node.new("img", document)
|
43
|
+
img["src"] = package.store_asset(image.text)
|
44
|
+
container << img
|
45
|
+
end
|
46
|
+
node
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Foliokit
|
2
|
+
module Overlay
|
3
|
+
class OverlayAudio < OverlayBase
|
4
|
+
element_base
|
5
|
+
element_reader :audio_url, selector: "data > audioUrl", text: true
|
6
|
+
element_reader :keep_alive, type: "bool", selector: "data > continuePlayingInBackground", text: true
|
7
|
+
element_reader :autoStart, type: "bool", selector: "data > autoStart", text: true
|
8
|
+
element_reader :autoStartDelay, type: "f", selector: "data > autoStartDelay", text: true
|
9
|
+
|
10
|
+
def tagname
|
11
|
+
"audio"
|
12
|
+
end
|
13
|
+
|
14
|
+
def export(document, options = {})
|
15
|
+
node = super(document, options)
|
16
|
+
if audio_url.present?
|
17
|
+
source = Nokogiri::XML::Node.new("source", document)
|
18
|
+
package.apply_asset(source, "src", audio_url)
|
19
|
+
source["type"] = "audio/mpeg"
|
20
|
+
node << source
|
21
|
+
end
|
22
|
+
node["auto-start"] = true if auto_start
|
23
|
+
node["keep-alive"] = true if keep_alive
|
24
|
+
node["data-ignore"] = true
|
25
|
+
node
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Foliokit
|
2
|
+
module Overlay
|
3
|
+
class OverlayBase
|
4
|
+
include Modules::Element
|
5
|
+
attr_reader :state, :section_index
|
6
|
+
|
7
|
+
def self.element_base
|
8
|
+
element_reader :id, hash: true
|
9
|
+
element_reader :type
|
10
|
+
element_reader :lastUpdated, type: :datetime
|
11
|
+
element_reader :bounds, type: Types::Bounds, selector: ->(options) { "#{package.manifest.orientation}Bounds > rectangle" }
|
12
|
+
element_reader :stateTransitionDuration, type: :f, selector: "data > stateTransitionDuration", text: true, default: 0.5
|
13
|
+
element_reader :swipe_event, attribute: "type", selector: "data > eventHandling > event"
|
14
|
+
element_reader :swipe_handler, attribute: "handler", selector: "data > eventHandling > event"
|
15
|
+
element_collection :states, "data > states > state", State
|
16
|
+
element_collection :events, "data > bindings > onevent", Event
|
17
|
+
element_collection :overlays, "data > children > overlay", Overlay
|
18
|
+
end
|
19
|
+
|
20
|
+
def tagname
|
21
|
+
"div"
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(element, package)
|
25
|
+
super(element, package)
|
26
|
+
|
27
|
+
# calculate bounds
|
28
|
+
bounds_target = element.css("#{package.manifest.orientation}Bounds > rectangle")
|
29
|
+
bounds_target = element if bounds_target.empty?
|
30
|
+
bounds_target = bounds_target.first if bounds_target.kind_of?(Nokogiri::XML::NodeSet)
|
31
|
+
@bounds = Types::Bounds.convert(bounds_target, "bounds")
|
32
|
+
|
33
|
+
# set initial state
|
34
|
+
@state = states.first
|
35
|
+
end
|
36
|
+
|
37
|
+
def stateful?
|
38
|
+
!!state
|
39
|
+
end
|
40
|
+
|
41
|
+
def export(document, parent: nil, section_index: nil)
|
42
|
+
@section_index = section_index
|
43
|
+
node = Nokogiri::XML::Node.new(tagname.to_s, document)
|
44
|
+
# node["id"] = id if package.manifest.valid_referenced_id?(id)
|
45
|
+
node["id"] = id
|
46
|
+
node["class"] = "overlay-#{type}" unless tagname.include? "overlay"
|
47
|
+
style = {
|
48
|
+
width: "#{bounds.width}px",
|
49
|
+
height: "#{bounds.height}px",
|
50
|
+
left: "#{bounds.x}px",
|
51
|
+
top: "#{bounds.y}px"
|
52
|
+
}
|
53
|
+
if parent&.stateful?
|
54
|
+
node["name"] = id
|
55
|
+
if state_transition_duration != 0
|
56
|
+
style[:transition] = "opacity #{state_transition_duration}s"
|
57
|
+
elsif parent.state_transition_duration != 0
|
58
|
+
style[:transition] = "opacity #{parent.state_transition_duration}s"
|
59
|
+
else
|
60
|
+
style[:transition] = "opacity 0s"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
node["style"] = style.map { |k, v| "#{k}:#{v}" }.join(";")
|
64
|
+
|
65
|
+
# stateful behaviour
|
66
|
+
node["active-state"] = state.id if state
|
67
|
+
|
68
|
+
# event / action behaviour
|
69
|
+
bindings = {}
|
70
|
+
unless swipe_event.nil?
|
71
|
+
if swipe_event == "verticalSwipe"
|
72
|
+
node["class"] += " prevent-swipe-vertical"
|
73
|
+
elsif swipe_event == "horizontalSwipe"
|
74
|
+
node["class"] += " prevent-swipe-horizontal"
|
75
|
+
else
|
76
|
+
node["class"] += " prevent-swipe-horizontal prevent-swipe-vertical"
|
77
|
+
end
|
78
|
+
node["touchable"] = true
|
79
|
+
if swipe_handler == "changeState"
|
80
|
+
bindings[swipe_event] = { selector: swipe_handler.downcase }
|
81
|
+
elsif swipe_handler == "scroll"
|
82
|
+
node["scroll"] = swipe_event.gsub("Swipe", "")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
if events.any?
|
86
|
+
events.each do |event|
|
87
|
+
actions = event.all_actions
|
88
|
+
if actions.any?
|
89
|
+
bindings[event.name] = event.all_actions.map(&:to_hash)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
if bindings.any?
|
95
|
+
node["bindings"] = JSON.dump(bindings)
|
96
|
+
if bindings["click"] or bindings["horizontalSwipe"] or bindings["verticalSwipe"]
|
97
|
+
node["touchable"] = true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
overlays.each do |overlay|
|
101
|
+
child_node = overlay.export(document, parent: self, section_index: section_index)
|
102
|
+
node << child_node unless child_node.nil?
|
103
|
+
end
|
104
|
+
node
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|