PluginProbe ʕ •ᴥ•ʔ
Custom Twitter Feeds – A Tweets Widget or X Feed Widget / 2.8.0
Custom Twitter Feeds – A Tweets Widget or X Feed Widget v2.8.0
2.8.0 2.7.0 2.6.1 2.6.0 1.0 1.0.1 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.2 1.2.1 1.2.10 1.2.11 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3 1.4 1.4.1 1.5 1.5.1 1.6 1.6.1 1.7 1.8 1.8.1 1.8.2 1.8.3 1.8.4 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1 2.1.1 2.1.2 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.5.4 2.5.5 trunk
custom-twitter-feeds / js / ctf-scripts.js
custom-twitter-feeds / js Last commit date
admin-notifications.js 3 weeks ago ctf-admin-scripts.js 3 weeks ago ctf-blocks.js 3 weeks ago ctf-scripts.js 3 weeks ago ctf-scripts.min.js 3 weeks ago jquery.matchHeight-min.js 3 weeks ago
ctf-scripts.js
669 lines
1 var ctf_js_exists = (typeof ctf_js_exists !== 'undefined') ? true : false;
2 if(!ctf_js_exists){
3
4 (function ($) {
5
6 window.ctf_init = function() {
7 window.ctfObject = {};
8 if ($('.ctf').length
9 && typeof $('.ctf').first().attr('data-ctf-flags') !== 'undefined') {
10 var flags = $('.ctf').first().attr('data-ctf-flags').split(',');
11
12 if (flags.indexOf('gdpr') > -1) {
13 window.ctfObject.consentGiven = false;
14 window.ctfObject.gdpr = true;
15 } else {
16 window.ctfObject.consentGiven = true;
17 window.ctfObject.gdpr = false;
18 }
19
20 if (flags.indexOf('locator') > -1) {
21 var random = Math.floor(Math.random() * $('.ctf').length);
22 window.ctfObject.locator = $('.ctf').length === 1 || (random === 1);
23 } else {
24 window.ctfObject.locator = false;
25 }
26
27 } else {
28 window.ctfObject.consentGiven = true;
29 window.ctfObject.gdpr = false;
30 window.ctfObject.locator = false;
31 }
32
33 if ($('.ctf').length <= $('.ctf_is_initialized').length) {
34 return;
35 }
36 if (window.ctfObject.consentGiven) {
37 ctfMaybeAddIntents();
38 }
39 //Runs every time new tweets are loaded
40 function ctfScripts($ctf) {
41 $ctf.addClass('ctf_is_initialized');
42
43 if (window.ctfObject.locator) {
44 var feedID = typeof $ctf.attr('data-feed-id') ? $ctf.attr('data-feed-id') : 'ctf-single',
45 postID = typeof $ctf.attr('data-postid') ? $ctf.attr('data-postid') : '';
46
47 jQuery.ajax({
48 url: ctf.ajax_url,
49 type: 'post',
50 data: {
51 action: 'ctf_do_locator',
52 atts: $ctf.attr('data-ctfshortcode'),
53 feed_id: feedID,
54 location: ctfLocationGuess($ctf),
55 post_id: postID,
56 },
57 success: function (data) {
58 }
59 }); // ajax call
60 }
61
62 if (ctfCheckConsent()) {
63 ctfRemovePrivacyFeatures($ctf);
64 } else {
65 ctfApplyPrivacyFeatures($ctf);
66 }
67 //Loop through each newly loaded tweet
68 $ctf.find('.ctf-item.ctf-new').each(function () {
69
70 var $ctfItem = $(this),
71 $ctfTextMedia = $ctfItem.find('.ctf-tweet-text-media-wrap'),
72 $ctfText = $ctfItem.find('.ctf-tweet-text').remove('.ctf-tweet-text-media-wrap'),
73 ctfTextStr = ' ' + $ctfText.html();
74
75 if ($ctf.attr('data-ctfdisablelinks') != 'true' && typeof ctfTextStr !== 'undefined' && !$ctf.find('.ctf-tweet-text-link').length) {
76
77 var ctfLinkColor = $ctf.attr('data-ctflinktextcolor'),
78 ctfLinkColorHex = '';
79 if (ctfLinkColor) ctfLinkColorHex = ctfLinkColor.replace(';', '').split("#")[1];
80
81 //Link URLs
82 window.ctfLinkify = (function () {
83 var k = "[a-z\\d.-]+://",
84 h = "(?:(?:[0-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.){3}(?:[0-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])",
85 c = "(?:(?:[^\\s!@#$%^&*()_=+[\\]{}\\\\|;:'\",.<>/?]+)\\.)+",
86 n = "(?:ac|ad|aero|ae|af|ag|ai|al|am|an|ao|aq|arpa|ar|asia|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|biz|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|cat|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|coop|com|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|info|int|in|io|iq|ir|is|it|je|jm|jobs|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mobi|mo|mp|mq|mr|ms|mt|museum|mu|mv|mw|mx|my|mz|name|na|nc|net|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|pro|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tp|travel|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|xn--0zwm56d|xn--11b5bs3a9aj6g|xn--80akhbyknj4f|xn--9t4b11yi5a|xn--deba0ad|xn--g6w251d|xn--hgbk6aj7f53bba|xn--hlcj6aya9esc7a|xn--jxalpdlp|xn--kgbechtv|xn--zckzah|ye|yt|yu|za|zm|zw)",
87 f = "(?:" + c + n + "|" + h + ")", o = "(?:[;/][^#?<>\\s]*)?",
88 e = "(?:\\?[^#<>\\s]*)?(?:#[^<>\\s]*)?", d = "\\b" + k + "[^<>\"'\\s]+",
89 a = "\\b" + f + o + e + "(?!\\w)", m = "mailto:",
90 j = "(?:" + m + ")?[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@" + f + e + "(?!\\w)",
91 l = new RegExp("(?:" + d + "|" + a + "|" + j + ")", "ig"), g = new RegExp("^" + k, "i"),
92 b = {"'": "`", ">": "<", ")": "(", "]": "[", "}": "{", "B;": "B+", "b:": "b9"}, i = {
93 callback: function (q, p) {
94 // The matched URL is interpolated into two quoted attributes and the
95 // result is assigned with .html(), so it must be escaped here and
96 // restricted to http(s) (SMASH-1796).
97 if (!p) { return q; }
98 if (!/^https?:\/\//i.test(p)) { return q; }
99 // The matched text comes from .html() serialization, so any "&" in it
100 // is already the start of an entity (&amp; etc.) — re-encoding those
101 // corrupts query strings, so only bare ampersands are encoded.
102 var ctfSafeUrl = String(p).replace(/&(?!(?:[a-zA-Z][a-zA-Z0-9]*|#\d+|#x[0-9a-fA-F]+);)/g, '&amp;').replace(/"/g, '&quot;')
103 .replace(/</g, '&lt;').replace(/>/g, '&gt;');
104 return '<a href="' + ctfSafeUrl + '" title="' + ctfSafeUrl + '" target="_blank">' + q + "</a>";
105 },
106 punct_regexp: /(?:[!?.,:;'"]|(?:&|&amp;)(?:lt|gt|quot|apos|raquo|laquo|rsaquo|lsaquo);)$/
107 };
108 return function (u, z) {
109 z = z || {};
110 var w, v, A, p, x = "", t = [], s, E, C, y, q, D, B, r;
111 for (v in i) {
112 if (z[v] === undefined) {
113 z[v] = i[v]
114 }
115 }
116 while (w = l.exec(u)) {
117 A = w[0];
118 E = l.lastIndex;
119 C = E - A.length;
120 if (/[\/:]/.test(u.charAt(C - 1))) {
121 continue
122 }
123 do {
124 y = A;
125 r = A.substr(-1);
126 B = b[r];
127 if (B) {
128 q = A.match(new RegExp("\\" + B + "(?!$)", "g"));
129 D = A.match(new RegExp("\\" + r, "g"));
130 if ((q ? q.length : 0) < (D ? D.length : 0)) {
131 A = A.substr(0, A.length - 1);
132 E--
133 }
134 }
135 if (z.punct_regexp) {
136 A = A.replace(z.punct_regexp, function (F) {
137 E -= F.length;
138 return ""
139 })
140 }
141 } while (A.length && A !== y);
142 p = A;
143 if (!g.test(p)) {
144 p = (p.indexOf("@") !== -1 ? (!p.indexOf(m) ? "" : m) : !p.indexOf("irc.") ? "irc://" : !p.indexOf("ftp.") ? "ftp://" : "http://") + p
145 }
146 if (s != C) {
147 t.push([u.slice(s, C)]);
148 s = E
149 }
150 t.push([A, p])
151 }
152 t.push([u.substr(s)]);
153 for (v = 0; v < t.length; v++) {
154 x += z.callback.apply(window, t[v])
155 }
156 return x || u
157 }
158 })();
159 if (!$ctfText.find('a').length) {
160 $ctfText.find('.emoji').each(function() {
161 // .attr() returns the value the HTML parser already decoded and
162 // .replaceWith(string) parses it as HTML, which voids the
163 // wp_kses_post() applied server-side (SMASH-1796).
164 $(this).replaceWith(document.createTextNode($(this).attr('alt') || ''));
165 });
166 ctfTextStr = ' ' +$ctfText.html();
167 ctfTextStr = ctfLinkify(ctfTextStr);
168 }
169 //Link hashtags
170 var ctfHashRegex = /(^|\s)#(\w*[\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]+\w*)/gi;
171
172 function ctfHashReplacer(hash) {
173 //Remove white space at beginning of hash
174 var replacementString = hash.trim();
175 //If the hash is a hex code then don't replace it with a link as it's likely in the style attr, eg: "color: #ff0000"
176 if (/^#[0-9A-F]{6}$/i.test(replacementString)) {
177 return replacementString;
178 } else {
179 return ' <a href="https://twitter.com/hashtag/' + replacementString.substring(1) + '" target="_blank" rel="nofollow noopener">' + replacementString + '</a>';
180 }
181 }
182
183 //Replace hashtags in text
184 if (ctfTextStr.length > 0) {
185 //Add a space after all <br> tags so that #hashtags immediately after them are also converted to hashtag links. Without the space they aren't captured by the regex.
186 ctfTextStr = ctfTextStr.replace(/<br>/g, "<br> ");
187 ctfTextStr = ctfTextStr.replace(ctfHashRegex, ctfHashReplacer);
188 }
189
190 //Link @tags
191 function ctfReplaceTags(tag) {
192 var replacementString = tag.trim();
193 return ' <a href="https://twitter.com/' + replacementString.substring(1) + '" target="_blank" rel="nofollow noopener">' + replacementString + '</a>';
194 }
195
196 var tagRegex = /[\s][@]+[A-Za-z0-9-_]+/g;
197 ctfTextStr = ctfTextStr.replace(tagRegex, ctfReplaceTags);
198
199
200 //Replace text with linked version
201 $ctfText.html(ctfTextStr.trim());
202 $ctfText.append($ctfTextMedia);
203
204 //Add link color
205 $ctfText.find('a').css('color', '#' + ctfLinkColorHex);
206 $ctfTextMedia.css('color', '#' + ctfLinkColorHex);
207
208 } // End "ctfdata-disablelinks" check
209
210 // shorten long urls in tweets
211 $ctfItem.find('.ctf-tweet-text a').each(function () {
212 if (jQuery(this).text().indexOf('http') > -1 && jQuery(this).text().length > 63) {
213 jQuery(this).text(jQuery(this).text().substring(0, 60) + '...');
214 }
215 });
216
217 }); // End .ctfItem loop
218
219 //Change color of retweet icon to match text
220 // $ctf.find('.ctf-retweet-icon').css({'background' : $ctf.find('.ctf-tweet-text a').css('color')}); //This doesn't work well if the link color is set to white as the default color of the icon text is also white
221
222 //Change colors of some items to match tweet text
223 $ctf.find('.ctf-author-name, .ctf-tweet-date, .ctf-author-screenname, .ctf-twitterlink, .ctf-author-box-link, .ctf-retweet-text, .ctf-quoted-tweet').css('color', $ctf.find('.ctf-tweet-text').css('color'));
224
225 $ctf.find('.ctf_more').off('click').on('click', function (e) {
226 e.preventDefault();
227 var $ctfRemaining = $(this).next('.ctf_remaining');
228 $(this).attr('aria-expanded', 'true').hide();
229 // Focus the revealed text so keyboard users aren't dropped to <body> (WCAG 2.4.3)
230 $ctfRemaining.show().attr('tabindex', '-1').focus();
231 });
232
233 // Call Custom JS if it exists
234 if (typeof ctf_custom_js == 'function') ctf_custom_js($);
235
236 $ctf.find('.ctf-author-box-link p:empty').remove();
237 } // end ctfScripts()
238
239 function ctfLoadTweets(lastIDData, shortcodeData, $ctf, $ctfMore, numNeeded, persistentIndex) {
240
241 //Display loader
242 $ctfMore.addClass('ctf-loading').append('<div class="ctf-loader"></div>');
243 $ctfMore.find('.ctf-loader').css('background-color', $ctfMore.css('color'));
244
245 var feedID = typeof $ctf.attr('data-feedid') ? $ctf.attr('data-feedid') : 'ctf-single',
246 postID = typeof $ctf.attr('data-postid') ? $ctf.attr('data-postid') : '',
247 v2feed = typeof $ctf.attr('data-feed') ? $ctf.attr('data-feed') : '';
248
249
250 jQuery.ajax({
251 url: ctf.ajax_url,
252 type: 'post',
253 data: {
254 action: 'ctf_get_more_posts',
255 last_id_data: lastIDData,
256 shortcode_data: shortcodeData,
257 num_needed: numNeeded,
258 persistent_index: persistentIndex,
259 feed_id: feedID,
260 location: ctfLocationGuess($ctf),
261 post_id: postID,
262 v2feed: v2feed,
263 },
264 success: function (data) {
265 var ctfPrevCount = $ctf.find('.ctf-item').length;
266 var ctfEndOfFeedText = '';
267 // Localized live-region strings (wp_localize_script), with English fallbacks
268 var ctfI18n = (typeof ctf !== 'undefined' && ctf.i18n) ? ctf.i18n : {};
269 if (lastIDData !== '') {
270 // appends the html echoed out in ctf_get_new_posts() to the last post element
271 if (data.indexOf('<meta charset') == -1) {
272 $ctf.find('.ctf-item').removeClass('ctf-new').last().after(data);
273 }
274
275 if ($ctf.find('.ctf-out-of-tweets').length) {
276 var ctfMoreFocused = $ctfMore.is(':focus');
277 $ctfMore.hide();
278 //Fade in the no more tweets message
279 $ctf.find('.ctf-out-of-tweets p').eq(0).fadeIn().end().eq(1).delay(500).fadeIn();
280 // End of the feed: announce the visible message via the live region (WCAG 4.1.3)
281 ctfEndOfFeedText = $ctf.find('.ctf-out-of-tweets p').eq(0).text() || ctfI18n.noMoreTweets || "That's all! No more Tweets to load";
282 // Load More just disappeared from under the user's focus; move
283 // focus to the first new item so it is not dropped to <body>
284 if (ctfMoreFocused) {
285 var $ctfFirstNew = $ctf.find('.ctf-item.ctf-new').first();
286 if ($ctfFirstNew.length) {
287 $ctfFirstNew.attr('tabindex', '-1').focus();
288 } else {
289 // Zero new items on the last page; keep focus in the feed (WCAG 2.4.3)
290 var $ctfNoMore = $ctf.find('.ctf-out-of-tweets').first();
291 if ($ctfNoMore.length) {
292 $ctfNoMore.attr('tabindex', '-1').focus();
293 } else {
294 $ctf.attr('tabindex', '-1').focus();
295 }
296 }
297 }
298 }
299 } else {
300 $ctf.find('.ctf-tweets').append(data);
301 }
302
303 // Announce newly loaded tweets and/or the end of the feed to assistive technology (WCAG 4.1.3)
304 var ctfNewCount = $ctf.find('.ctf-item').length - ctfPrevCount;
305 var ctfStatusText = '';
306 if (ctfNewCount > 0) {
307 ctfStatusText = (ctfI18n.newTweetsLoaded || '%s new tweets loaded').replace('%s', ctfNewCount);
308 }
309 if (ctfEndOfFeedText !== '') {
310 ctfStatusText = ctfStatusText === '' ? ctfEndOfFeedText : ctfStatusText + '. ' + ctfEndOfFeedText;
311 }
312 if (ctfStatusText !== '') {
313 var ctfStatusEl = $ctf.find('[data-ctf-feed-status]');
314 if (ctfStatusEl.length) {
315 ctfStatusEl.text(ctfStatusText);
316 }
317 }
318
319
320 //Remove loader
321 $ctfMore.removeClass('ctf-loading').find('.ctf-loader').remove();
322
323 //Re-run JS code
324 ctfScripts($ctf);
325
326 }
327 }); // ajax call
328 }
329
330 $('.ctf').each(function () {
331
332 var $ctf = $(this),
333 numNeeded = parseInt($ctf.attr('data-ctfneeded'));
334
335 //Adds a class if the feed is in a narrow column or on mobile so we can make styling adjustments
336 if ($ctf.width() <= 480) $ctf.addClass('ctf-narrow');
337 if ($ctf.width() <= 320) $ctf.addClass('ctf-super-narrow');
338
339 if (!$(this).hasClass('ctf_is_initialized')) {
340 ctfScripts($ctf);
341 }
342
343 // delay added to prevent strange issue with ajax themes returning the entire page
344 setTimeout(function () {
345 if (numNeeded > 0) {
346 var $ctfMore = $ctf.find('.ctf-more'),
347 lastIDData = $ctf.find('.ctf-item').last().attr('id'),
348 persistentIndex = $ctf.find('.ctf-item').length,
349 shortcodeData = $ctf.attr('data-ctfshortcode');
350
351 ctfLoadTweets(lastIDData, shortcodeData, $ctf, $ctfMore, numNeeded, persistentIndex);
352 }
353 }, 500);
354
355 // add the load more button and input to simulate a dynamic json file call
356 $ctf.find('.ctf-more').on('click', function () {
357 // read the json that is in the ctf-shortcode-data that contains all of the shortcode arguments
358 var $ctfMore = $(this),
359 lastIDData = $ctf.find('.ctf-item').last().attr('id'),
360 persistentIndex = $ctf.find('.ctf-item').length,
361 shortcodeData = $ctf.attr('data-ctfshortcode');
362
363 ctfLoadTweets(lastIDData, shortcodeData, $ctf, $ctfMore, 0, persistentIndex);
364
365 });
366
367 $ctf.find('.ctf-author-box-link p:empty').remove();
368 setTimeout(function () {
369 if (ctfCheckConsent()) {
370 ctfRemovePrivacyFeatures($ctf);
371 } else {
372 ctfApplyPrivacyFeatures($ctf);
373 }
374 }, 500);
375 }); // end .cff each loop
376
377
378 }
379
380 jQuery(document).ready(function($) {
381 ctf_init();
382
383 // Cookie Notice by dFactory
384 $('#cookie-notice a').on('click',function() {
385 setTimeout(function() {
386 ctfAterConsentToggled();
387 },1000);
388 });
389
390 // Cookie Notice by dFactory
391 $('#cookie-law-info-bar a').on('click',function() {
392 setTimeout(function() {
393 ctfAterConsentToggled();
394 },1000);
395 });
396
397 // GDPR Cookie Consent by WebToffee
398 $('.cli-user-preference-checkbox').on('click',function(){
399 ctfAterConsentToggled();
400 });
401
402 // Cookiebot
403 $(window).on('CookiebotOnAccept', function (event) {
404 ctfAterConsentToggled();
405 });
406
407 // Complianz by Really Simple Plugins
408 $(document).on('cmplzEnableScripts', function (event) {
409 if ( event.detail === 'marketing' ) {
410 $('.ctf').each(function () {
411 window.ctfObject.consentGiven = true;
412 ctfAterConsentToggled();
413 });
414 }
415 });
416
417 // Complianz by Really Simple Plugins
418 $(document).on('cmplzFireCategories', function (event) {
419 if ( event.detail.category === 'marketing' ) {
420 $('.ctf').each(function () {
421 window.ctfObject.consentGiven = true;
422 ctfAterConsentToggled();
423 });
424 }
425 });
426
427 // Borlabs Cookie by Borlabs
428 $(document).on('borlabs-cookie-consent-saved', function (event) {
429 ctfAterConsentToggled();
430 });
431
432 // devowl.io
433 if (typeof window.consentApi !== 'undefined') {
434 window.consentApi.consent("custom-twitter-feed").then(() => {
435 try {
436 // applies full features to feed
437 setTimeout(function() {
438 $('.ctf').each(function () {
439 window.ctfObject.consentGiven = true;
440 ctfAterConsentToggled();
441 });
442 },1000);
443 }
444 catch (error) {
445 // do nothing
446 }
447 });
448 }
449
450 // Moove Agency
451 $('.moove-gdpr-infobar-allow-all').on('click',function() {
452 setTimeout(function() {
453 $('.ctf').each(function () {
454 window.ctfObject.consentGiven = true;
455 ctfAterConsentToggled();
456 });
457 },1000);
458 });
459
460 // WPConsent
461 window.addEventListener('wpconsent_consent_saved', function(event) {
462 setTimeout(function() {
463 $('.ctf').each(function () {
464 ctfAterConsentToggled();
465 });
466 },1000);
467 });
468
469 window.addEventListener('wpconsent_consent_updated', function(event) {
470 setTimeout(function() {
471 $('.ctf').each(function () {
472 ctfAterConsentToggled();
473 });
474 },1000);
475 });
476 });
477
478 function ctfCheckConsent() {
479 if (window.ctfObject.consentGiven || !window.ctfObject.gdpr) {
480 return true;
481 }
482 if (typeof window.WPConsent !== 'undefined') {
483 window.ctfObject.consentGiven = window.WPConsent.hasConsent('marketing');
484 } else if (typeof CLI_Cookie !== "undefined") { // GDPR Cookie Consent by WebToffee
485 if (CLI_Cookie.read(CLI_ACCEPT_COOKIE_NAME) !== null) {
486
487 // WebToffee no longer uses this cookie but being left here to maintain backwards compatibility
488 if (CLI_Cookie.read('cookielawinfo-checkbox-non-necessary') !== null) {
489 window.ctfObject.consentGiven = CLI_Cookie.read('cookielawinfo-checkbox-non-necessary') === 'yes';
490 }
491
492 if (CLI_Cookie.read('cookielawinfo-checkbox-necessary') !== null) {
493 window.ctfObject.consentGiven = CLI_Cookie.read('cookielawinfo-checkbox-necessary') === 'yes';
494 }
495 }
496
497 } else if (typeof window.cnArgs !== "undefined") { // Cookie Notice by dFactory
498 var value = "; " + document.cookie,
499 parts = value.split( '; cookie_notice_accepted=' );
500
501 if ( parts.length === 2 ) {
502 var val = parts.pop().split( ';' ).shift();
503
504 window.ctfObject.consentGiven = (val === 'true');
505 }
506 } else if (typeof window.cookieconsent !== 'undefined') { // Complianz by Really Simple Plugins
507 window.ctfObject.consentGiven = ( ctfCmplzGetCookie('cmplz_consent_status') === 'allow' || jQuery('body').hasClass('cmplz-status-marketing') );
508 } else if (typeof window.Cookiebot !== "undefined") { // Cookiebot by Cybot A/S
509 window.ctfObject.consentGiven = Cookiebot.consented;
510 } else if (typeof window.BorlabsCookie !== 'undefined') { // Borlabs Cookie by Borlabs
511 window.ctfObject.consentGiven = typeof window.BorlabsCookie.Consents !== 'undefined' ? window.BorlabsCookie.Consents.hasConsent('twitter') : window.BorlabsCookie.checkCookieConsent('twitter');
512 } else if (cffCmplzGetCookie('moove_gdpr_popup')) { // Moove GDPR Popup
513 var moove_gdpr_popup = JSON.parse(decodeURIComponent(ctfCmplzGetCookie('moove_gdpr_popup')));
514 window.ctfObject.consentGiven = typeof moove_gdpr_popup.thirdparty !== "undefined" && moove_gdpr_popup.thirdparty === "1";
515 }
516
517 var evt = jQuery.Event('ctfcheckconsent');
518 evt.feed = this;
519 jQuery(window).trigger(evt);
520
521 return window.ctfObject.consentGiven; // GDPR not enabled
522 }
523
524 function ctfApplyPrivacyFeatures($ctf) {
525 if (!$ctf.find('.ctf-hide-avatar').length || $ctf.find('.ctf-hide-avatar.ctf-no-consent').length) {
526 $ctf.find('.ctf-item').addClass('ctf-hide-avatar ctf-no-consent');
527 }
528 if ($('.ctf-header-img span').length) {
529 $('.ctf-header-img').addClass('ctf-no-consent');
530 }
531 }
532
533 function ctfRemovePrivacyFeatures($ctf) {
534 ctfMaybeAddIntents();
535 $ctf.find('.ctf-item.ctf-no-consent').removeClass('ctf-hide-avatar');
536 $ctf.find('.ctf-author-avatar').each(function() {
537 var $ctfSpan = $(this).find('span');
538 // Built as an element rather than spliced into an HTML string: both
539 // data-* values are attacker-reachable and .attr() hands them back
540 // decoded (SMASH-1796).
541 $ctfSpan.replaceWith($('<img>', {
542 src: $ctfSpan.attr('data-avatar') || '',
543 alt: $ctfSpan.attr('data-alt') || '',
544 width: 48,
545 height: 48
546 }));
547 });
548 $ctf.find('.ctf-header-img').each(function() {
549 var $ctfSpan = $(this).find('span');
550 // Built as an element rather than spliced into an HTML string: both
551 // data-* values are attacker-reachable and .attr() hands them back
552 // decoded (SMASH-1796).
553 $ctfSpan.replaceWith($('<img>', {
554 src: $ctfSpan.attr('data-avatar') || '',
555 alt: $ctfSpan.attr('data-alt') || '',
556 width: 48,
557 height: 48
558 }));
559 });
560 $ctf.find('.ctf-no-consent').removeClass('ctf-no-consent');
561 //Header profile pic hover
562 $ctf.find('.ctf-header .ctf-header-link').on('mouseenter mouseleave', function(e) {
563 switch(e.type) {
564 case 'mouseenter':
565 $ctf.find('.ctf-header .ctf-header-img-hover').fadeIn(200);
566 break;
567 case 'mouseleave':
568 $ctf.find('.ctf-header .ctf-header-img-hover').stop().fadeOut(600);
569 break;
570 }
571 });
572 }
573
574 function ctfAterConsentToggled() {
575 if (ctfCheckConsent()) {
576 $('.ctf').each(function () {
577 ctfRemovePrivacyFeatures($(this));
578 });
579 }
580 }
581
582 function ctfMaybeAddIntents() {
583 if (typeof window.ctfObject.intentsIncluded === undefined) {
584 window.ctfObject.intentsIncluded = false;
585 }
586
587 $('.ctf').each(function () {
588 if (!window.ctfObject.intentsIncluded && typeof $(this).attr('data-ctfintents') !== undefined) {
589 window.ctfObject.intentsIncluded = true;
590 (function() {
591 if (window.__twitterIntentHandler) return;
592 var intentRegex = /twitter\.com\/intent\/(\w+)/,
593 windowOptions = 'scrollbars=yes,resizable=yes,toolbar=no,location=yes',
594 width = 550,
595 height = 420,
596 winHeight = screen.height,
597 winWidth = screen.width;
598
599 function handleIntent(e) {
600 e = e || window.event;
601 var target = e.target || e.srcElement,
602 m, left, top;
603
604 while (target && target.nodeName.toLowerCase() !== 'a') {
605 target = target.parentNode;
606 }
607
608 if (target && target.nodeName.toLowerCase() === 'a' && target.href) {
609 m = target.href.match(intentRegex);
610 if (m) {
611 left = Math.round((winWidth / 2) - (width / 2));
612 top = 0;
613
614 if (winHeight > height) {
615 top = Math.round((winHeight / 2) - (height / 2));
616 }
617
618 window.open(target.href, 'intent', windowOptions + ',width=' + width +
619 ',height=' + height + ',left=' + left + ',top=' + top);
620 e.returnValue = false;
621 e.preventDefault && e.preventDefault();
622 }
623 }
624 }
625
626 if (document.addEventListener) {
627 document.addEventListener('click', handleIntent, false);
628 } else if (document.attachEvent) {
629 document.attachEvent('onclick', handleIntent);
630 }
631 window.__twitterIntentHandler = true;
632 }());
633 }
634 });
635 }
636
637 function ctfCmplzGetCookie(cname) {
638 var name = cname + "="; //Create the cookie name variable with cookie name concatenate with = sign
639 var cArr = window.document.cookie.split(';'); //Create cookie array by split the cookie by ';'
640
641 //Loop through the cookies and return the cookie value if it find the cookie name
642 for (var i = 0; i < cArr.length; i++) {
643 var c = cArr[i].trim();
644 //If the name is the cookie string at position 0, we found the cookie and return the cookie value
645 if (c.indexOf(name) == 0)
646 return c.substring(name.length, c.length);
647 }
648
649 return "";
650 }
651 function ctfLocationGuess($feed) {
652 var location = 'content';
653
654 if ($feed.closest('footer').length) {
655 location = 'footer';
656 } else if ($feed.closest('.header').length
657 || $feed.closest('header').length) {
658 location = 'header';
659 } else if ($feed.closest('.sidebar').length
660 || $feed.closest('aside').length) {
661 location = 'sidebar';
662 }
663
664 return location;
665 }
666 })(jQuery);
667
668
669 } //End ctf_js_exists check