foliokit 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|