locatine 0.02637 → 0.02651

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +268 -297
  3. data/bin/locatine-daemon.rb +4 -2
  4. data/lib/locatine/daemon.rb +44 -60
  5. data/lib/locatine/daemon_helpers/methods.rb +85 -0
  6. data/lib/locatine/element.rb +28 -0
  7. data/lib/locatine/results.rb +125 -0
  8. data/lib/locatine/results_helpers/common.rb +68 -0
  9. data/lib/locatine/results_helpers/find_by_magic.rb +106 -0
  10. data/lib/locatine/results_helpers/guess.rb +45 -0
  11. data/lib/locatine/results_helpers/info_generator.rb +79 -0
  12. data/lib/locatine/results_helpers/logger.rb +64 -0
  13. data/lib/locatine/{for_search → results_helpers}/xpath_generator.rb +18 -19
  14. data/lib/locatine/scripts/element.js +40 -0
  15. data/lib/locatine/scripts/page.js +53 -0
  16. data/lib/locatine/scripts/parent.js +6 -0
  17. data/lib/locatine/session.rb +102 -0
  18. data/lib/locatine/version.rb +4 -2
  19. data/lib/locatine.rb +3 -2
  20. metadata +39 -49
  21. data/lib/locatine/app/background.js +0 -8
  22. data/lib/locatine/app/content.css +0 -38
  23. data/lib/locatine/app/content.js +0 -152
  24. data/lib/locatine/app/devtools.html +0 -1
  25. data/lib/locatine/app/devtools.js +0 -3
  26. data/lib/locatine/app/manifest.json +0 -20
  27. data/lib/locatine/app/popup.css +0 -47
  28. data/lib/locatine/app/popup.html +0 -19
  29. data/lib/locatine/app/popup.js +0 -65
  30. data/lib/locatine/daemon_helpers.rb +0 -52
  31. data/lib/locatine/for_search/data_generate.rb +0 -67
  32. data/lib/locatine/for_search/data_logic.rb +0 -98
  33. data/lib/locatine/for_search/defaults.rb +0 -40
  34. data/lib/locatine/for_search/dialog_logic.rb +0 -107
  35. data/lib/locatine/for_search/element_selection.rb +0 -80
  36. data/lib/locatine/for_search/file_work.rb +0 -67
  37. data/lib/locatine/for_search/find_by_guess.rb +0 -67
  38. data/lib/locatine/for_search/find_by_locator.rb +0 -59
  39. data/lib/locatine/for_search/find_by_magic.rb +0 -65
  40. data/lib/locatine/for_search/find_logic.rb +0 -79
  41. data/lib/locatine/for_search/helpers.rb +0 -106
  42. data/lib/locatine/for_search/highlight.rb +0 -41
  43. data/lib/locatine/for_search/listening.rb +0 -48
  44. data/lib/locatine/for_search/merge.rb +0 -40
  45. data/lib/locatine/for_search/name_helper.rb +0 -51
  46. data/lib/locatine/for_search/page_work.rb +0 -126
  47. data/lib/locatine/for_search/public.rb +0 -179
  48. data/lib/locatine/for_search/saying.rb +0 -199
  49. data/lib/locatine/for_search.rb +0 -6
  50. data/lib/locatine/large_scripts/css.js +0 -21
  51. data/lib/locatine/large_scripts/dimensions.js +0 -17
  52. data/lib/locatine/large_scripts/element.js +0 -30
  53. data/lib/locatine/large_scripts/page.js +0 -60
  54. data/lib/locatine/scope.rb +0 -88
  55. data/lib/locatine/search.rb +0 -67
@@ -1,51 +0,0 @@
1
- module Locatine
2
- module ForSearch
3
- ##
4
- # We have a module that helps name elements
5
- module NameHelper
6
- private
7
-
8
- def good_name(main, vars)
9
- good = %w[name title id role text]
10
- tmp = main.select { |i| good.any? { |k| i['name'].include?(k) } }
11
- words = (tmp.map { |i| process_string(i['value'], vars) }).uniq
12
- words.sample
13
- end
14
-
15
- def so_so_name(main, vars)
16
- all = main.select { |i| i['type'] == 'attribute' }
17
- words = all.map { |i| process_string(i['value'], vars) }
18
- words.sample
19
- end
20
-
21
- def some_name(main, vars)
22
- result = good_name(main, vars)
23
- result = so_so_name(main, vars) if result.nil?
24
- result = "undescribed #{generate_word}" if result.nil?
25
- result
26
- end
27
-
28
- def suggest_name(name, attrs, vars)
29
- if name.to_s.empty?
30
- tag = attrs['0'].select { |i| i['type'] == 'tag' }
31
- tag = process_string(tag[0]['value'], vars)
32
- name = "#{some_name(attrs['0'], vars)} #{tag}"
33
- end
34
- suggest = name
35
- send_to_app('locatine_name', suggest)
36
- send_to_app('locatine_name_mark', 'true')
37
- suggest
38
- end
39
-
40
- def generate_word(pairs = 3)
41
- ss = 'qwrtpsdfghjklzxcvbnm'.split('')
42
- sa = 'eyuioa'.split('')
43
- str = ''
44
- pairs.times do
45
- str += ss.sample + sa.sample
46
- end
47
- str
48
- end
49
- end
50
- end
51
- end
@@ -1,126 +0,0 @@
1
- module Locatine
2
- module ForSearch
3
- ##
4
- # Methods about getting full information about opened page>
5
- # And methods for stalkibg around the page in oreder to find something.
6
- module PageWork
7
- private
8
-
9
- def matcher
10
- { 'tag' => ->(data) { take_by_tag(*data) },
11
- 'text' => ->(data) { take_by_text(*data) },
12
- 'attribute' => ->(data) { take_by_attribute(*data) },
13
- 'css' => ->(data) { take_by_css(*data) } }
14
- end
15
-
16
- def take_dom
17
- script = File.read("#{HOME}/large_scripts/page.js")
18
- engine.execute_script(script)
19
- end
20
-
21
- def select_from_page(page, data, vars)
22
- all = [] # No result is a valid result too
23
- data.each_pair do |depth, array|
24
- get_trusted(array).each do |hash|
25
- all += catch(page, hash, vars, depth)
26
- end
27
- end
28
- all
29
- end
30
-
31
- def catch(page, hash, vars, depth)
32
- all = []
33
- hash['value'] = process_string(hash['value'], vars)
34
- page.each do |element|
35
- all += take_match(element, depth, hash, vars)
36
- all += catch(element['children'], hash, vars, depth)
37
- end
38
- all.uniq
39
- end
40
-
41
- def take_match(element, depth, hash, vars)
42
- if hash['type'] == 'dimensions'
43
- return take_by_dimensions(hash, element, depth, vars)
44
- end
45
-
46
- matcher.fetch(hash['type']).call([hash, element, depth])
47
- end
48
-
49
- def take_by_tag(hash, elt, depth)
50
- return kids([elt], depth) if elt['tag'].downcase.include?(hash['value'])
51
-
52
- []
53
- end
54
-
55
- def take_by_text(hash, elt, depth)
56
- return kids([elt], depth) if elt['text'].include?(hash['value'])
57
-
58
- []
59
- end
60
-
61
- def take_attribute_check(hash, elt)
62
- if !hash['name'].to_s.empty? && !hash['value'].to_s.empty?
63
- return elt['attrs'][hash['name']].to_s
64
- end
65
-
66
- elt['attrs'].to_s
67
- end
68
-
69
- def take_by_attribute(hash, elt, depth)
70
- str = hash['value'].to_s.empty? ? hash['name'].to_s : hash['value'].to_s
71
- ok = take_attribute_check(hash, elt).include?(str)
72
- return kids([elt], depth) if ok
73
-
74
- []
75
- end
76
-
77
- def dimensions_for_search(hash, vars)
78
- values = hash['value'].split('*').map(&:to_i)
79
- values[0] = vars[:x].to_i if vars[:x]
80
- values[1] = vars[:y].to_i if vars[:y]
81
- values
82
- end
83
-
84
- def dimensions_from_page(elt)
85
- [elt['coordinates']['top'].to_i, elt['coordinates']['bottom'].to_i,
86
- elt['coordinates']['left'].to_i, elt['coordinates']['right'].to_i]
87
- end
88
-
89
- def take_by_dimensions(hash, elt, depth, vars)
90
- return [] if !visual? || hash['name'] != window_size
91
-
92
- return kids([elt], depth) if in_recatngle?(hash, elt, vars)
93
-
94
- []
95
- end
96
-
97
- def in_recatngle?(hash, elt, vars)
98
- cleft, ctop, cwidth, cheight = dimensions_for_search(hash, vars)
99
- top, bottom, left, right = dimensions_from_page(elt)
100
- (cleft >= left) && (cleft + cwidth <= right) &&
101
- (ctop >= top) && (ctop + cheight <= bottom)
102
- end
103
-
104
- def take_by_css(hash, elt, depth)
105
- return [] unless visual?
106
-
107
- string = "#{hash['name']}: #{hash['value']}"
108
- return kids([elt], depth) if elt['style'].include?(string)
109
-
110
- []
111
- end
112
-
113
- # If depth != 0 we should return all children subchildren.
114
- def kids(array, depth)
115
- answer = []
116
- return array if depth.to_i.zero?
117
-
118
- array.each do |one|
119
- answer += one['children']
120
- answer += kids(one['children'], depth)
121
- end
122
- answer
123
- end
124
- end
125
- end
126
- end
@@ -1,179 +0,0 @@
1
- module Locatine
2
- module ForSearch
3
- ##
4
- # Public methods of the Search class
5
- module Public
6
- ##
7
- # Creates a new instance of Search
8
- #
9
- # Params:
10
- #
11
- # +json+ is the name of file to store//read data. Default =>
12
- # "./Locatine_files/default.json"
13
- #
14
- # +depth+ shows how many data will be stored for element.
15
- #
16
- # +browser+ is the instance of Watir::Browser. Unless provided it gonna
17
- # be created with locatine-app onboard.
18
- #
19
- # +learn+ shows will locatine ask for assistance from user or will fail
20
- # on error. learn is true when LEARN parameter is set in environment.
21
- #
22
- # +stability_limit+ shows max times attribute should be present and
23
- # checked to consider it trusted.
24
- #
25
- # +scope+ will be used in search (if not provided) defaulkt is "Default"
26
- #
27
- # +tolerance+ Shows how similar must be an element found as alternative
28
- # to the lost one. Default is 67 which means that if less than 33% of
29
- # metrics of alternative elements are the same as of the lost element
30
- # will not be returned
31
- #
32
- # +visual_search+ locatine will use position and style if true
33
- #
34
- # +no_fail+ if true locatine is not producing errors on element loss.
35
- #
36
- # +trusted+ array of names of attributes and element params to use
37
- # in search always.
38
- #
39
- # +untrusted+ array of names of attributes and element params to use
40
- # in search never.
41
- #
42
- # +autolearn+ determines will locatine study an element or not. true means
43
- # locatine will always study it (slow). false means it won't study it
44
- # unless it was lost and found. If not stated locatine will turn set it
45
- # true if at least one element was lost.
46
- def initialize(config = {})
47
- init_config = default_init_config.merge(config)
48
- import_browser init_config.delete :browser
49
- import_file init_config.delete :json
50
- import_config init_config
51
- end
52
-
53
- ##
54
- # Looking for the element
55
- #
56
- # Params:
57
- #
58
- # +scope+ is a parameter that is used to get information about the
59
- # element from @data. Default is "Default"
60
- #
61
- # +name+ is a parameter that is used to get information about the
62
- # element from @data. Must not be nil.
63
- #
64
- # +exact+ if true locatine will be forced to use only basic search.
65
- # Default is false
66
- #
67
- # +locator+ if not empty it is used for the first attempt to find the
68
- # element. Default is {}
69
- #
70
- # +vars+ hash of variables that will be used for dynamic attributes.
71
- # See readme for example
72
- #
73
- # +look_in+ only elements of that kind will be used. Use Watir::Browser
74
- # methods returning collections (:text_fields, :links, :divs, etc.)
75
- #
76
- # +iframe+ if provided locatine will look for elements inside of it
77
- #
78
- # +return_locator+ is to return a valid locator of the result
79
- #
80
- # +collection+ when true an array will be returned. When false - a
81
- # single element
82
- #
83
- # +tolerance+ It is possible to set a custom tolerance for every find. See
84
- # examples in README
85
- #
86
- # +no_fail+ if true locatine is not producing errors on element loss.
87
- #
88
- # +trusted+ array of names of attributes and element params to use
89
- # in search always.
90
- #
91
- # +untrusted+ array of names of attributes and element params to use
92
- # in search never.
93
- def find(simple_name = nil,
94
- name: nil,
95
- scope: nil,
96
- exact: false,
97
- locator: {},
98
- vars: {},
99
- look_in: nil,
100
- iframe: nil,
101
- return_locator: false,
102
- collection: false,
103
- tolerance: nil,
104
- no_fail: nil,
105
- trusted: nil,
106
- untrusted: nil)
107
- name = set_name(simple_name, name)
108
- set_env_for_search(look_in, iframe, tolerance,
109
- no_fail, trusted, untrusted)
110
- scope ||= @scope.nil? ? 'Default' : @scope
111
- result, attributes = full_search(name, scope, vars, locator, exact)
112
- return { xpath: generate_xpath(attributes, vars) } if result &&
113
- return_locator
114
-
115
- to_subtype(result, collection)
116
- end
117
-
118
- ##
119
- # Find alias with return_locator option enforced
120
- def lctr(*args)
121
- enforce({ return_locator: true }, *args)
122
- end
123
-
124
- ##
125
- # Find alias with collection option enforced
126
- def collect(*args)
127
- enforce({ collection: true }, *args)
128
- end
129
-
130
- def json=(value)
131
- import_file(value)
132
- end
133
-
134
- def browser=(value)
135
- import_browser(value)
136
- end
137
-
138
- ##
139
- # Returns an instance of the Scope class. Starts define if learn == true
140
- #
141
- # Params:
142
- #
143
- # +name+ is a parameter that stores name of the scope.
144
- # Default is "Default"
145
- #
146
- # +vars+ is a hash which will be used to generate dynamic attributes.
147
- # See readme for explanation.
148
- def get_scope(name: 'Default', vars: {})
149
- answer = Scope.new(name, self)
150
- answer.define(vars) if @learn
151
- answer
152
- end
153
-
154
- ##
155
- # Find alias with zero tolerance option enforced
156
- def check(*args)
157
- enforce({ tolerance: 0 }, *args)
158
- end
159
-
160
- ##
161
- # Collection alias with zero tolerance option enforced
162
- def check_collection(*args)
163
- enforce({ tolerance: 0, collection: true }, *args)
164
- end
165
-
166
- ##
167
- # Collection alias with exact option on
168
- def exact_collection(*args)
169
- enforce({ exact: true, collection: true }, *args)
170
- end
171
-
172
- ##
173
- # Find alias with exact option on
174
- def exact(*args)
175
- enforce({ exact: true }, *args)
176
- end
177
- end
178
- end
179
- end
@@ -1,199 +0,0 @@
1
- module Locatine
2
- module ForSearch
3
- ##
4
- # texts, errors
5
- # rubocop:disable Metrics/ModuleLength
6
- module Saying
7
- private
8
-
9
- def send_info(message)
10
- puts "#{time}: #{message}"
11
- end
12
-
13
- def send_warn(message)
14
- warn "#{time}: WARNING: #{message}"
15
- end
16
-
17
- def verb(length)
18
- length > 1 ? 'elements were' : 'element was'
19
- end
20
-
21
- ##
22
- # Setting attribute of locatine div (way to communicate)
23
- def send_to_app(what, value, bro = engine)
24
- fix_iframe
25
- bro.wd.execute_script(
26
- %[if (document.getElementById('locatine_magic_div')){
27
- const magic_div = document.getElementById('locatine_magic_div');
28
- return magic_div.setAttribute("#{what}", "#{value}")}]
29
- )
30
- fix_iframe
31
- end
32
-
33
- def push_title(text)
34
- send_info text
35
- send_to_app('locatinetitle', text)
36
- end
37
-
38
- def send_found(name, scope, length)
39
- push_title("#{length} #{verb(length)} found as #{name} in #{scope}"\
40
- ' using previously saved information')
41
- end
42
-
43
- def send_guessing(name, scope)
44
- push_title("Locatine is trying to guess what is #{name} in #{scope}.")
45
- end
46
-
47
- def send_selected(length, name, scope)
48
- push_title "#{length} #{verb(length)} selected as #{name} in "\
49
- "#{scope}. If it is correct - confirm the selection."
50
- end
51
-
52
- def send_working(tag, index)
53
- push_title "You've selected //#{tag}[#{index}]."\
54
- ' Wait while Locatine works'
55
- end
56
-
57
- def send_lost
58
- push_title 'Selected element was lost before locatine locate it. '\
59
- 'Consider choosing it from devtools or write your own locator'
60
- end
61
-
62
- def send_clear(name, scope)
63
- name = 'some element' if name.to_s.empty?
64
- push_title "Now nothing is selected as #{name} in #{scope}"
65
- end
66
-
67
- def send_no_guess(name, scope)
68
- push_title "Locatine has no good guess for #{name} in #{scope}."
69
- end
70
-
71
- def send_has_guess(name, scope)
72
- push_title "Something is guessed as #{name} in #{scope}."
73
- end
74
-
75
- def send_selecting(name, scope)
76
- name = 'some element' if name.to_s.empty?
77
- push_title "You are selecting #{name} in #{scope}"
78
- send_to_app('locatinehint', 'Toggle single//collection mode button if '\
79
- 'you need. If you want to do some actions on the page toggle'\
80
- ' Locatine waiting button. You also can select element on devtools '\
81
- '-> Elements. Do not forget to confirm your selection.')
82
- end
83
-
84
- def send_has_response
85
- push_title 'Right now you are defining nothing. So no button will work'
86
- send_to_app('locatinehint', 'Your previous selection is confirmed. '\
87
- 'Locatine is waiting for new find request')
88
- end
89
-
90
- def send_same_entry(length, name, scope, found)
91
- push_title "#{length} #{verb(length)} selected as #{name} in #{scope}."\
92
- " But it was already defined #{found.length} times."
93
- example = found.sample
94
- same = found.select { |i| (i[:name] == name) && (i[:scope] == scope) }
95
- if same.empty?
96
- send_same_entry_example(example)
97
- else
98
- send_fully_similar
99
- end
100
- end
101
-
102
- def send_same_entry_example(example)
103
- send_to_app('locatinehint', "For example like #{example[:name]} in"\
104
- " #{example[:scope]}")
105
- end
106
-
107
- def send_fully_similar
108
- send_to_app('locatinehint', 'And it was defined with the same name'\
109
- ' and in the same scope. So saving your selection will cause'\
110
- ' deleting of all previously stored data about the element')
111
- end
112
-
113
- def warn_dropping(tag, index)
114
- send_warn('For some reason locatine cannot proceed with'\
115
- " //#{tag}[#{index}] element. You've selected. Maybe element was"\
116
- ' changed somewhere in the middle of locatine work. If this error is'\
117
- 'repeating you can try to select element via devtools or you can'\
118
- ' provide a locator')
119
- end
120
-
121
- def warn_type
122
- send_warn("Check also. Maybe #{tag} element cannot be found as @type?")
123
- end
124
-
125
- def warn_acceptable_type(method)
126
- send_warn "#{method} works for :look_in. But it is better to use a"\
127
- ' method of Watir::Browser that returns a collection (like :divs,'\
128
- ' :links, etc.)'
129
- end
130
-
131
- def warn_element_lost(name, scope, data, vars)
132
- xpath = generate_xpath(data, vars)
133
- send_warn "#{name} in #{scope} by xpath: ```#{xpath}``` is//are lost."\
134
- ' Locatine is trying to find it anyway.'
135
- end
136
-
137
- def warn_cannot_highlight(data)
138
- send_warn "Something was found as #{data} but we cannot highlight it"
139
- end
140
-
141
- def warn_broken_locator(locator)
142
- send_warn "Can find nothing using #{locator}"
143
- end
144
-
145
- def warn_unstable
146
- send_warn 'It seems that page is unstable. It may lead to problems '\
147
- 'with resolving elements'
148
- end
149
-
150
- def warn_highly_unstable
151
- send_warn 'It seems that page is HIGHLY unstable. No guaranties now.'
152
- end
153
-
154
- def warn_much_highlight(size)
155
- send_warn "Only the first 50 elements of #{size} were highlighted."
156
- end
157
-
158
- def warn_lost_found(name, scope, data, vars)
159
- xpath = generate_xpath(data, vars)
160
- send_warn "Something was found as #{name} in #{scope} by xpath:"\
161
- "```#{xpath}```"
162
- end
163
-
164
- def warn_not_found(name, scope)
165
- send_warn "Locatine cannot find element #{name} in #{scope}"
166
- end
167
-
168
- def warn_totally_same(how_deep)
169
- send_warn('There are more than one elements with totally similar'\
170
- " attributes. Custom depth for element is set to #{how_deep}.")
171
- end
172
-
173
- def warn_no_negatives
174
- send_warn 'The only way to find the selected element is to use'\
175
- " negative expression like //*[not(@id='something')]. Locatine does"\
176
- ' not support it. So you must to provide for element a custom locator.'\
177
- ' Or find it as a part of collection and than return it by index'
178
- end
179
-
180
- def raise_not_found(name, scope)
181
- raise "Locatine cannot find element #{name} in #{scope}"
182
- end
183
-
184
- def raise_not_similar(name, scope)
185
- raise "Locatine cannot find element similar to #{name} in #{scope}"
186
- end
187
-
188
- def raise_no_name
189
- raise ArgumentError, ':name is not provided.'
190
- end
191
-
192
- def raise_no_var(thevar)
193
- raise ArgumentError, ":#{thevar} must be "\
194
- 'provided in vars since element was defined with it'
195
- end
196
- end
197
- end
198
- end
199
- # rubocop:enable Metrics/ModuleLength
@@ -1,6 +0,0 @@
1
- module Locatine
2
- ##
3
- # One module to collect all parts of search
4
- module ForSearch
5
- end
6
- end
@@ -1,21 +0,0 @@
1
- function walk(elm, result) {
2
- let node;
3
-
4
- const tagName = elm.tagName;
5
- const array = Array.prototype.slice.call( document.getElementsByTagName(tagName) );
6
- const index = array.indexOf(elm);
7
-
8
- const item = [tagName, index, getComputedStyle(elm).cssText]
9
- result.push(item)
10
-
11
- // Handle child elements
12
- for (node = elm.firstChild; node; node = node.nextSibling) {
13
- if (node.nodeType === 1) { // 1 == Element
14
- result = walk(node, result);
15
- }
16
- }
17
- return result
18
- }
19
- let array = walk(document.body,[]);
20
- array.shift();
21
- return array;
@@ -1,17 +0,0 @@
1
- function walk(xmi, xma, ymi, yma){
2
- let x;
3
- let y;
4
- let array =[];
5
- let one;
6
- for (x = xmi; x <= xma; x++) {
7
- for (y = ymi; y <= yma; y++) {
8
- one = document.elementFromPoint(x, y);
9
- if ((one != document.documentElement) && (one != document.body)){
10
- array.push(document.elementFromPoint(x, y));
11
- }
12
- }
13
- }
14
- return [...new Set(array)];
15
- }
16
-
17
- return walk(parseInt(arguments[0]), parseInt(arguments[1]), parseInt(arguments[2]), parseInt(arguments[3]))
@@ -1,30 +0,0 @@
1
-
2
- function one_element(target){
3
-
4
- let element = {};
5
- let attribute = {};
6
-
7
- element = {attrs: [], text: "", tag: ""};
8
- if (target.childNodes){
9
- for (let i = 0; i < target.childNodes.length; ++i){
10
- if (target.childNodes[i].nodeType === 3){
11
- element.text += target.childNodes[i].textContent;
12
- }
13
- }
14
- } else {
15
- element.text = target.textContent
16
- }
17
- element.tag = target.tagName.toLowerCase();
18
- let atts = target.attributes;
19
- if (atts) {
20
- for (var k = 0, n = atts.length; k < n; k++){
21
- att = atts[k];
22
- attribute = {};
23
- attribute[att.nodeName] = att.nodeValue;
24
- element.attrs.push(attribute);
25
- }
26
- }
27
- return element;
28
- }
29
- let x = one_element(arguments[0]);
30
- return x;
@@ -1,60 +0,0 @@
1
-
2
- function walk(elm) {
3
- let node;
4
-
5
- const tagName = elm.tagName.toLowerCase();
6
- const array = Array.prototype.slice.call( document.getElementsByTagName(tagName) );
7
- const index = array.indexOf(elm);
8
- const relative = elm.getBoundingClientRect();
9
-
10
- // init item
11
- const item = {tag: tagName,
12
- index: index,
13
- style: getComputedStyle(elm).cssText,
14
- text: "",
15
- attrs: {},
16
- coordinates: {top:0, bottom:0, left:0, right:0},
17
- children: []};
18
-
19
- // text for item
20
- if (elm.childNodes) {
21
- for (let z = 0; z < elm.childNodes.length; ++z){
22
- if (elm.childNodes[z].nodeType === 3){
23
- item.text += elm.childNodes[z].textContent;
24
- }
25
- }
26
- } else {
27
- item.text = elm.textContent
28
- }
29
-
30
- // attributes for item
31
- atts = elm.attributes;
32
- if (atts) {
33
- for (var att, k = 0, n = atts.length; k < n; k++){
34
- att = atts[k];
35
- item.attrs[att.nodeName] = att.nodeValue;
36
- }
37
- }
38
-
39
- item.coordinates.top = relative["top"] + window.scrollY;
40
- item.coordinates.bottom = relative["bottom"] + window.scrollY;
41
- item.coordinates.left = relative["left"] + window.scrollX;
42
- item.coordinates.right = relative["right"] + window.scrollX;
43
-
44
- // Handle child elements (not magic ones)
45
- for (node = elm.firstChild; node; node = node.nextSibling) {
46
- if (node.nodeType === 1) { // 1 == Element
47
- if (node.attributes['id']) {
48
- if (node.attributes['id'].value !== 'locatine_magic_div') {
49
- item.children.push(walk(node))
50
- }
51
- } else {
52
- item.children.push(walk(node))
53
- }
54
- }
55
- }
56
-
57
- return item;
58
- }
59
- let result = walk(document.body);
60
- return [result];