PageSourceSearch

https://moccanada.ca/wp-content/themes/u-design-child/text_widget.js

js moccanada.ca collected 2026-10-05 09:39:23 UTC 11,064 bytes, 299 lines download raw bytes

1var Textline = {};
2
3Textline.Widget = function(phone_number, user_opts) {
4    var on_doc_ready,
5        widget;
6
7    this.animating = false;
8    this.visible = false;
9    this.phone_number = phone_number.replace(/[^\d+]/gi, '');
10
11    user_opts = user_opts || {};
12    this.setupWidgetOpts(user_opts);
13    this.createWidget();
14
15    if (location.search == '?textline_debug') {
16        this.generateDebugConsole();
17    }
18    if ((!this.detectPhone() && !user_opts.force_display) && !(location.search == "?force_textline" || this.debug_console)) {
19        return;
20    }
21
22    widget = this;
23    on_doc_ready = function() {
24        document.getElementsByTagName('body')[0].appendChild(widget.widget);
25        widget.position();
26        widget.setupScrollHandling();
27    }
28    if (document.addEventListener) {
29        document.addEventListener('DOMContentLoaded', on_doc_ready, false);
30    }
31};
32
33
34Textline.Widget.prototype.setupWidgetOpts = function(user_opts) {
35    this.opts = {};
36
37    this.opts.background_color = user_opts.background_color || '#0F77BA';
38    this.opts.font_color = user_opts.font_color || '#FFFFFF';
39    this.opts.height = user_opts.height || 50;
40    this.opts.font_family = user_opts.font_family || 'Arial';
41    this.opts.font_size = user_opts.font_size || '18px';
42    this.opts.prefill = user_opts.prefill;
43    this.opts.text = user_opts.text || 'Text Us';
44
45    this.opts.scroll_target = user_opts.scroll_target;
46    this.opts.scroll_threshold = user_opts.scroll_threshold;
47    this.opts.bottom_offset = user_opts.bottom_offset || 30;
48
49    this.opts.widget_id = user_opts.id || 'textline-widget';
50};
51
52
53Textline.Widget.prototype.createWidget = function() {
54    var ref,
55        tail;
56
57    this.widget = document.createElement('a');
58    ref = 'sms:' + this.phone_number
59    if (this.opts.prefill) {
60        ref += ';?&body=' + encodeURIComponent(this.opts.prefill);
61    }
62    this.widget.setAttribute('href', ref);
63    this.widget.setAttribute('target', '_blank');
64    this.widget.setAttribute('id', this.opts.widget_id);
65
66    this.widget.style.textDecoration = 'none'
67    this.widget.style.display = 'block'
68    this.widget.style.backgroundColor = this.opts.background_color;
69    this.widget.style.whiteSpace = 'nowrap';
70    this.widget.style.padding = ((this.opts.height-20)/2)+'px 35px 0px 53px';
71    this.widget.style.borderRadius = '4px';
72
73    this.widget.style.position = 'fixed';
74    this.widget.style.left = '25%';
75    this.widget.style.zIndex = '1000';
76
77    this.widget.style.transition = 'initial';
78
79    this.content = document.createElement('div');
80    this.content.style.height = this.opts.height - (this.opts.height - 20)/2 + 'px';
81    this.content.style.lineHeight = 'normal';
82    this.widget.appendChild(this.content);
83
84    tail = document.createElement('div');
85    tail.style.borderTop = '12px solid ' + this.opts.background_color;
86    tail.style.borderLeft = tail.style.borderRight = '12px solid transparent';
87    tail.style.position = 'absolute';
88    tail.style.bottom = '-12px';
89    tail.style.left = '50%';
90    tail.style.marginLeft = '-12px';
91    this.widget.appendChild(tail);
92
93    this.createIcon();
94    this.createTextNode();
95};
96
97
98Textline.Widget.prototype.createIcon = function() {
99    var button,
100        screen;
101
102    this.icon = document.createElement('i');
103
104    this.icon.style.display = 'inline-block';
105    this.icon.style.border = '2px solid ' + this.opts.font_color;
106    this.icon.style.borderBottomWidth = '5px';
107    this.icon.style.borderRadius = '2px';
108
109    this.icon.style.position = 'absolute';
110    this.icon.style.left = '35px';
111    this.icon.style.top = '50%';
112    this.icon.style.marginTop = '-10px';
113
114    screen = document.createElement('div');
115    screen.style.width = '8px';
116    screen.style.height = '12px';
117    this.icon.appendChild(screen);
118
119    button = document.createElement('div');
120    button.style.backgroundColor = this.opts.background_color;
121    button.style.borderRadius = '2px';
122    button.style.width = '3px';
123    button.style.height = '3px';
124    button.style.position = 'absolute';
125    button.style.bottom = '-4px';
126    button.style.left = '50%';
127    button.style.marginLeft = '-1.5px';
128    this.icon.appendChild(button);
129
130    this.content.appendChild(this.icon);
131};
132
133
134Textline.Widget.prototype.createTextNode = function() {
135    this.text_node = document.createElement('span');
136
137    this.text_node.style.color = this.opts.font_color;
138    this.text_node.style.fontFamily = this.opts.font_family;
139    this.text_node.style.fontSize = this.opts.font_size;
140
141    this.text_node.appendChild(document.createTextNode(this.opts.text));
142
143    this.content.appendChild(this.text_node);
144};
145
146
147Textline.Widget.prototype.position = function() {
148    if (this.animating) {
149        return;
150    }
151
152    this.widget.style.marginLeft = (-1*this.widget.clientWidth/2)+'px';
153
154    if (this.visible) {
155        this.widget.style.bottom = this.visibleBottomOffset() + 'px';
156    } else {
157        this.widget.style.bottom = (-1*this.widget.clientHeight) + 'px';
158    }
159};
160
161
162Textline.Widget.prototype.show = function() {
163    var animate,
164        animation_end_pos,
165        animation_start_pos,
166        curr_pos,
167        direction,
168        final_pos,
169        num_steps,
170        overshoot,
171        step,
172        widget;
173
174    if (this.visible) {
175        return;
176    }
177
178    this.animating = true;
179    this.visible = true;
180
181    curr_pos = parseFloat(this.widget.style.bottom.slice(0,-2));
182    final_pos = this.visibleBottomOffset();
183    num_steps = 64;
184    overshoot = this.visibleBottomOffset();
185    direction = -1;
186    animation_end_pos = curr_pos;
187    widget = this;
188
189    animate = function() {
190        if (isNaN(curr_pos)) {
191            return;
192        }
193        if (animation_end_pos == curr_pos) {
194            overshoot = overshoot/2;
195            if (overshoot <= 0.01) {
196                overshoot = 0;
197            }
198            direction = -1*direction
199            animation_end_pos = final_pos + direction * overshoot;
200            animation_start_pos = curr_pos;
201
202            if (animation_end_pos == final_pos) {
203                widget.animating = false;
204                widget.position();
205                return;
206            }
207
208            num_steps = Math.ceil(num_steps/1.2);
209            step = 0;
210        }
211
212        step += 1;
213        curr_pos = animation_start_pos + widget.easeInOutQuad(step/num_steps) * direction * Math.abs(animation_start_pos - animation_end_pos);
214        widget.widget.style.bottom = curr_pos + 'px';
215
216        setTimeout(animate, 5);
217    };
218
219    animate();
220};
221
222
223Textline.Widget.prototype.setupScrollHandling = function() {
224    var scroll_evt_handler,
225        scroll_offset,
226        widget;
227
228    if (this.opts.scroll_target) {
229        if (typeof(this.opts.scroll_target) == typeof('')) {
230            this._scroll_target = document.getElementById(this.opts.scroll_target)
231        } else {
232            this._scroll_target = this.opts.scroll_target;
233        }
234    } else {
235        this._scroll_target = window;
236    }
237    if (!this._scroll_target) {
238        return;
239    }
240
241    widget = this
242
243    scroll_evt_handler = function() {
244        scroll_offset = widget._scroll_target.scrollY || widget._scroll_target.scrollTop || widget._scroll_target.pageYOffset || 0;
245        if (scroll_offset >= widget.scrollThreshold()) {
246            widget.show();
247        }
248    };
249    this._scroll_target.addEventListener('scroll', scroll_evt_handler, false);
250    scroll_evt_handler();
251};
252
253
254Textline.Widget.prototype.easeInOutQuad = function(t) {
255    return t<.5 ? 2*t*t : -1+(4-2*t)*t
256};
257
258
259Textline.Widget.prototype.visibleBottomOffset = function() {
260    return this.opts.bottom_offset;
261};
262
263
264Textline.Widget.prototype.scrollThreshold = function() {
265    if (typeof(this.opts.scroll_threshold) == typeof(0)) {
266        return this.opts.scroll_threshold;
267    }
268    return 100;
269};
270
271
272Textline.Widget.prototype.detectPhone = function() {
273    var check = false;
274    // http://detectmobilebrowsers.com/
275    (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|
275sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
276    return check;
277};
278
279
280Textline.Widget.prototype.generateDebugConsole = function() {
281    this.debug_console = document.createElement('div');
282    this.debug_console.style.position = 'fixed';
283    this.debug_console.style.top = '0px';
284    this.debug_console.style.left = '0px';
285    this.debug_console.style.zIndex = '1000';
286    this.debug_console.style.fontSize = '12px';
287    this.debug_console.style.color = '#0F0';
288    this.debug_console.style.background = '#000';
289    this.debug_console.style.padding = '0px 8px';
290    this.debug_console.innerHTML = 'debugging...';
291    document.getElementsByTagName('body')[0].appendChild(this.debug_console);
292};
293
294
295Textline.Widget.prototype.log = function(msg) {
296    if (this.debug_console) {
297        this.debug_console.innerHTML = '' + msg;
298    }
299}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.