Custom Twitter Feeds - Version 1.1

Version Description

  • New: Added a setting to translate the "Retweeted" text
  • Tweak: If there aren't enough Tweets to populate the feed them Ajax in more automatically
  • Fix: Custom JavaScript is now rerun every time the Load More button is used
  • Fix: CSS display tweaks
Download this release

Release Info

Developer smashballoon
Plugin Icon 128x128 Custom Twitter Feeds
Version 1.1
Comparing to
See all releases

Code changes from version 1.0.1 to 1.1

README.txt CHANGED
@@ -5,7 +5,7 @@ Support Website: http://smashballoon/custom-twitter-feeds/
5
  Tags: Twitter, Twitter feed, Custom Twitter Feed, Twitter feeds, Custom Twitter Feeds, Tweets, Custom Tweets, Tweets feed, Twitter widget, Custom Twitter widget, Twitter plugin, Twitter API, Twitter tweets
6
  Requires at least: 3.0
7
  Tested up to: 4.5.2
8
- Stable tag: 1.0.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -134,6 +134,12 @@ If you're still having trouble displaying your Tweets after trying the common is
134
  2. Custom Twitter Feeds plugin Settings pages
135
 
136
  == Changelog ==
 
 
 
 
 
 
137
  = 1.0.1 =
138
  * Bug fixes
139
 
5
  Tags: Twitter, Twitter feed, Custom Twitter Feed, Twitter feeds, Custom Twitter Feeds, Tweets, Custom Tweets, Tweets feed, Twitter widget, Custom Twitter widget, Twitter plugin, Twitter API, Twitter tweets
6
  Requires at least: 3.0
7
  Tested up to: 4.5.2
8
+ Stable tag: 1.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
134
  2. Custom Twitter Feeds plugin Settings pages
135
 
136
  == Changelog ==
137
+ = 1.1 =
138
+ * New: Added a setting to translate the "Retweeted" text
139
+ * Tweak: If there aren't enough Tweets to populate the feed them Ajax in more automatically
140
+ * Fix: Custom JavaScript is now rerun every time the Load More button is used
141
+ * Fix: CSS display tweaks
142
+
143
  = 1.0.1 =
144
  * Bug fixes
145
 
css/ctf-styles.css CHANGED
@@ -205,8 +205,7 @@
205
  display: inline-block;
206
  font-size: inherit;
207
  background: #19cf86;
208
- /*background: rgba(0,0,0,0);*/
209
- color: #fff;
210
  padding: 1px 3px 3px 3px;
211
  line-height: 1;
212
  margin: 0 5px 0 0;
@@ -242,9 +241,11 @@
242
  #ctf .ctf-tweet-meta{
243
  margin-left: 4px;
244
  margin-right: 4px;
 
245
  }
246
  #ctf .ctf-screename-sep{
247
  margin: 0 2px;
 
248
  }
249
  #ctf .ctf-author-name{
250
  font-weight: bold !important;
@@ -368,15 +369,15 @@
368
  }
369
  #ctf .ctf-tweet-actions .ctf-reply:hover,
370
  #ctf .ctf-tweet-actions .ctf-reply:focus{
371
- color: #E34F0E;
372
  }
373
  #ctf .ctf-tweet-actions .ctf-retweet:hover,
374
  #ctf .ctf-tweet-actions .ctf-retweet:focus{
375
- color: #19cf86;
376
  }
377
  #ctf .ctf-tweet-actions .ctf-like:hover,
378
  #ctf .ctf-tweet-actions .ctf-like:focus{
379
- color: #e81c4f;
380
  }
381
  #ctf .ctf-action-count {
382
  display: none;
205
  display: inline-block;
206
  font-size: inherit;
207
  background: #19cf86;
208
+ color: #fff !important;
 
209
  padding: 1px 3px 3px 3px;
210
  line-height: 1;
211
  margin: 0 5px 0 0;
241
  #ctf .ctf-tweet-meta{
242
  margin-left: 4px;
243
  margin-right: 4px;
244
+ display: inline-block;
245
  }
246
  #ctf .ctf-screename-sep{
247
  margin: 0 2px;
248
+ display: inline-block;
249
  }
250
  #ctf .ctf-author-name{
251
  font-weight: bold !important;
369
  }
370
  #ctf .ctf-tweet-actions .ctf-reply:hover,
371
  #ctf .ctf-tweet-actions .ctf-reply:focus{
372
+ color: #E34F0E !important;
373
  }
374
  #ctf .ctf-tweet-actions .ctf-retweet:hover,
375
  #ctf .ctf-tweet-actions .ctf-retweet:focus{
376
+ color: #19cf86 !important;
377
  }
378
  #ctf .ctf-tweet-actions .ctf-like:hover,
379
  #ctf .ctf-tweet-actions .ctf-like:focus{
380
+ color: #e81c4f !important;
381
  }
382
  #ctf .ctf-action-count {
383
  display: none;
custom-twitter-feed.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Custom Twitter Feeds
4
  Plugin URI: http://smashballoon.com/custom-twitter-feeds
5
  Description: Customizable Twitter feeds for your website
6
- Version: 1.0.1
7
  Author: Smash Balloon
8
  Author URI: http://smashballoon.com/
9
  Text Domain: custom-twitter-feeds
@@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
  */
25
 
26
  define( 'CTF_URL', plugin_dir_path( __FILE__ ) );
27
- define( 'CTF_VERSION', '1.0.1' );
28
  define( 'CTF_TITLE', 'Custom Twitter Feeds' );
29
  define( 'CTF_JS_URL', plugins_url( '/js/ctf-scripts.js?ver=' . CTF_VERSION , __FILE__ ) );
30
  define( 'OAUTH_PROCESSOR_URL', 'https://smashballoon.com/ctf-at-retriever/?return_uri=' );
@@ -60,7 +60,12 @@ function ctf_init( $atts ) {
60
  return $twitter_feed->getErrorHtml();
61
  } else {
62
  $twitter_feed->maybeCacheTweets();
63
- return $twitter_feed->getFeedHtml();
 
 
 
 
 
64
  }
65
  }
66
  add_shortcode( 'custom-twitter-feed', 'ctf_init' );
@@ -71,15 +76,17 @@ add_shortcode( 'custom-twitter-feeds', 'ctf_init' );
71
  */
72
  function ctf_get_more_posts() {
73
  $shortcode_data = json_decode( str_replace( '\"', '"', sanitize_text_field( $_POST['shortcode_data'] ) ), true ); // necessary to unescape quotes
74
- $last_id_data = sanitize_text_field( $_POST['last_id_data'] );
 
 
75
 
76
  include_once( CTF_URL . '/inc/CtfFeed.php' );
77
 
78
- $twitter_feed = CtfFeed::init( $shortcode_data, $last_id_data );
79
 
80
  $twitter_feed->maybeCacheTweets();
81
-
82
- echo $twitter_feed->getTweetSetHtml( 1 );
83
 
84
  die();
85
  }
@@ -264,9 +271,7 @@ function ctf_custom_js() {
264
  ?>
265
  <!-- Custom Twitter Feeds JS -->
266
  <script type="text/javascript">
267
- jQuery(document).ready(function($) {
268
- <?php echo stripslashes( $ctf_custom_js ) . "\r\n"; ?>
269
- });
270
  </script>
271
  <?php
272
  }
3
  Plugin Name: Custom Twitter Feeds
4
  Plugin URI: http://smashballoon.com/custom-twitter-feeds
5
  Description: Customizable Twitter feeds for your website
6
+ Version: 1.1
7
  Author: Smash Balloon
8
  Author URI: http://smashballoon.com/
9
  Text Domain: custom-twitter-feeds
24
  */
25
 
26
  define( 'CTF_URL', plugin_dir_path( __FILE__ ) );
27
+ define( 'CTF_VERSION', '1.1' );
28
  define( 'CTF_TITLE', 'Custom Twitter Feeds' );
29
  define( 'CTF_JS_URL', plugins_url( '/js/ctf-scripts.js?ver=' . CTF_VERSION , __FILE__ ) );
30
  define( 'OAUTH_PROCESSOR_URL', 'https://smashballoon.com/ctf-at-retriever/?return_uri=' );
60
  return $twitter_feed->getErrorHtml();
61
  } else {
62
  $twitter_feed->maybeCacheTweets();
63
+
64
+ $feed_html = $twitter_feed->getFeedOpeningHtml();
65
+ $feed_html .= $twitter_feed->getTweetSetHtml();
66
+ $feed_html .= $twitter_feed->getFeedClosingHtml();
67
+
68
+ return $feed_html;
69
  }
70
  }
71
  add_shortcode( 'custom-twitter-feed', 'ctf_init' );
76
  */
77
  function ctf_get_more_posts() {
78
  $shortcode_data = json_decode( str_replace( '\"', '"', sanitize_text_field( $_POST['shortcode_data'] ) ), true ); // necessary to unescape quotes
79
+ $last_id_data = isset( $_POST['last_id_data'] ) ? sanitize_text_field( $_POST['last_id_data'] ) : '';
80
+ $num_needed = isset( $_POST['num_needed'] ) ? (int)$_POST['num_needed'] : 0;
81
+ $is_pagination = empty( $last_id_data ) ? 0 : 1;
82
 
83
  include_once( CTF_URL . '/inc/CtfFeed.php' );
84
 
85
+ $twitter_feed = CtfFeed::init( $shortcode_data, $last_id_data, $num_needed );
86
 
87
  $twitter_feed->maybeCacheTweets();
88
+
89
+ echo $twitter_feed->getTweetSetHtml( $is_pagination );
90
 
91
  die();
92
  }
271
  ?>
272
  <!-- Custom Twitter Feeds JS -->
273
  <script type="text/javascript">
274
+ <?php echo "window.ctf_custom_js = function($){" . stripslashes( $ctf_custom_js ) . "}\r\n"; ?>
 
 
275
  </script>
276
  <?php
277
  }
inc/CtfAdmin.php CHANGED
@@ -372,6 +372,20 @@ class CtfAdmin
372
  'whatis' => 'This will replace the default text displayed inside the optional header of the feed' // "what is this?" text
373
  ));
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  add_settings_section(
376
  'ctf_customize_showandhide', // matches the section name
377
  'Show/Hide',
372
  'whatis' => 'This will replace the default text displayed inside the optional header of the feed' // "what is this?" text
373
  ));
374
 
375
+ // custom header text
376
+ $this->create_settings_field( array(
377
+ 'name' => 'retweetedtext',
378
+ 'title' => '<label for="ctf_retweetedtext">Translation for "Retweeted"</label><code class="ctf_shortcode">retweetedtext
379
+ Eg: retweetedtext="retuiteó"</code>', // label for the input field
380
+ 'callback' => 'default_text', // name of the function that outputs the html
381
+ 'page' => 'ctf_customize_general', // matches the section name
382
+ 'section' => 'ctf_customize_general', // matches the section name
383
+ 'option' => 'ctf_customize', // matches the options name
384
+ 'class' => 'default-text', // class for the wrapper and input field
385
+ 'whatis' => 'This will replace the default text displayed for retweeted texts',
386
+ 'default' => 'Retweeted'// "what is this?" text
387
+ ));
388
+
389
  add_settings_section(
390
  'ctf_customize_showandhide', // matches the section name
391
  'Show/Hide',
inc/CtfFeed.php CHANGED
@@ -27,6 +27,8 @@ class CtfFeed
27
  */
28
  protected $last_id_data;
29
 
 
 
30
  /**
31
  * @var mixed|void
32
  */
@@ -62,6 +64,11 @@ class CtfFeed
62
  */
63
  protected $transient_data = false;
64
 
 
 
 
 
 
65
  /**
66
  * @var array
67
  */
@@ -82,11 +89,13 @@ class CtfFeed
82
  *
83
  * @param array $atts data from the shortcode
84
  * @param string $last_id_data the last visible tweet on the feed, empty string if first set
 
85
  */
86
- public function __construct( $atts, $last_id_data )
87
  {
88
  $this->atts = $atts;
89
  $this->last_id_data = $last_id_data;
 
90
  $this->db_configure = get_option( 'ctf_configure', array() );
91
  $this->db_customize = get_option( 'ctf_customize', array() );
92
  $this->db_style = get_option( 'ctf_style', array() );
@@ -97,11 +106,12 @@ class CtfFeed
97
  *
98
  * @param array $atts data from the shortcode
99
  * @param string $last_id_data the last visible tweet on the feed, empty string if first set
 
100
  * @return CtfFeed the complete object for the feed
101
  */
102
- public static function init( $atts, $last_id_data = '' )
103
  {
104
- $feed = new CtfFeed( $atts, $last_id_data );
105
  $feed->setFeedOptions();
106
  $feed->setTweetSet();
107
  return $feed;
@@ -141,9 +151,11 @@ class CtfFeed
141
  'nowtime'
142
  );
143
  $this->setStandardTextOptions( $standard_text_custom, 'customize' );
144
- $this->setStandardTextOptions( 'multiplier', 'customize', 1.25 );
145
 
 
146
  $this->setStandardTextOptions( 'twitterlinktext', 'customize', 'Twitter' );
 
147
  $this->setStandardTextOptions( 'buttontext', 'style', 'Load More...' );
148
 
149
  $text_size = array(
@@ -209,10 +221,12 @@ class CtfFeed
209
  {
210
  $this->setTransientName();
211
  $success = $this->maybeSetTweetsFromCache();
212
-
213
  if ( ! $success ) {
214
  $this->maybeSetTweetsFromTwitter();
215
  }
 
 
216
  }
217
 
218
  /**
@@ -223,7 +237,7 @@ class CtfFeed
223
  {
224
  $this->feed_options['access_token'] = isset( $this->db_configure['access_token'] ) && strlen( $this->db_configure['access_token'] ) > 30 ? $this->db_configure['access_token'] : 'missing';
225
  $this->feed_options['access_token_secret'] = isset( $this->db_configure['access_token_secret'] ) && strlen( $this->db_configure['access_token_secret'] ) > 30 ? $this->db_configure['access_token_secret'] : 'missing';
226
-
227
  // verify that access token and secret have been entered
228
  $this->setMissingCredentials();
229
  }
@@ -442,17 +456,24 @@ class CtfFeed
442
  public function setTweetsToRetrieve()
443
  {
444
  $min_tweets_to_retrieve = 10;
445
- if( $this->feed_options['include_replies'] ) {
446
- $this->feed_options['count'] = $this->feed_options['num'];
447
- } else {
448
- if ( $this->feed_options['num'] < 10 ) {
449
- $this->feed_options['count'] = max( round( $this->feed_options['num'] * $this->feed_options['multiplier'] * 1.6 ), $min_tweets_to_retrieve );
450
- } elseif ( $this->feed_options['num'] < 30 ) {
451
- $this->feed_options['count'] = round( $this->feed_options['num'] * $this->feed_options['multiplier'] * 1.2 );
452
  } else {
453
- $this->feed_options['count'] = round( $this->feed_options['num'] * $this->feed_options['multiplier'] );
 
 
 
 
 
 
454
  }
 
 
 
455
  }
 
456
  }
457
 
458
  /**
@@ -477,7 +498,7 @@ class CtfFeed
477
  $this->working_term = isset( $this->atts['hashtag'] ) ? $this->atts['hashtag'] : ( isset( $this->atts['search'] ) ? $this->atts['search'] : '' );
478
  $this->feed_options['feed_term'] = isset( $this->working_term ) ? ctf_validate_search_text( $this->working_term ) : ( ( isset( $this->db_configure['search_text'] ) ) ? $this->db_configure['search_text'] : '' );
479
  }
480
-
481
  if ( $this->feed_options['type'] == '' ) {
482
  $this->feed_options['type'] = isset( $this->db_configure['type'] ) ? $this->db_configure['type'] : 'usertimeline';
483
  switch ( $this->feed_options['type'] ) {
@@ -547,18 +568,10 @@ class CtfFeed
547
  */
548
  private function validateCache()
549
  {
550
- if ( $this->feed_options['type'] == 'search' ) {
551
- if ( isset( $this->transient_data['search_metadata'] ) ) {
552
- return false;
553
- } else {
554
- return 'invalid cache';
555
- }
556
  } else {
557
- if ( isset( $this->transient_data[0] ) ) {
558
- return false;
559
- } else {
560
- return 'invalid cache';
561
- }
562
  }
563
  }
564
 
@@ -598,11 +611,31 @@ class CtfFeed
598
  $this->api_obj = $this->apiConnect( $this->feed_options['type'], $this->feed_options['feed_term'] );
599
  $this->tweet_set = json_decode( $this->api_obj->json , $assoc = true );
600
 
 
601
  if ( isset( $this->tweet_set['errors'][0] ) ) {
602
  $this->api_obj->api_error_no = $this->tweet_set['errors'][0]['code'];
603
  $this->api_obj->api_error_message = $this->tweet_set['errors'][0]['message'];
604
  $this->tweet_set = false;
605
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606
  }
607
 
608
  /**
@@ -663,6 +696,13 @@ class CtfFeed
663
  $this->tweet_set = $trimmed_tweets;
664
  }
665
 
 
 
 
 
 
 
 
666
  protected function filterTrimmedTweets( $trimmed, $tweet )
667
  {
668
  return $trimmed;
@@ -703,8 +743,15 @@ class CtfFeed
703
 
704
  return $json_data;
705
  }
706
-
707
- protected function setGetFieldsArray( $end_point, $feed_term )
 
 
 
 
 
 
 
708
  {
709
  $get_fields = array();
710
  if ( $end_point === 'usertimeline' ) {
@@ -719,7 +766,7 @@ class CtfFeed
719
  if ( $end_point === 'search' ) {
720
  $get_fields['q'] = $feed_term;
721
  }
722
-
723
  return $get_fields;
724
  }
725
 
@@ -768,29 +815,42 @@ class CtfFeed
768
  return $twitter_connect->performRequest();
769
  }
770
 
 
 
 
 
 
 
 
771
  protected function getOutOfTweetsHtml( $feed_options )
772
  {
773
  $html = '';
774
 
775
  $html .= '<div class="ctf-out-of-tweets">';
776
- $html .= '<p>That\'s all! No more Tweets to load</p>';
777
- $html .= '<p>';
778
- $html .= '<a class="twitter-share-button" href="https://twitter.com/share" target="_blank" data-size="large" data-url="<?php echo get_home_url(); ?>">Share</a>';
779
- if ( isset( $feed_options['screenname'] ) ) {
780
- $html .= '<a class="twitter-follow-button" href="https://twitter.com/' . $feed_options['screenname'] . '" target="_blank" data-show-count="false" data-size="large" data-dnt="true">Follow</a>';
781
- }
782
- $html .= '</p>';
783
- $html .= "<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>";
784
  $html .= '</div>';
785
-
786
  return $html;
787
  }
788
 
789
- public function getFeedHtml()
 
 
 
 
 
790
  {
791
  $feed_options = $this->feed_options;
792
  $ctf_data_disablelinks = ($feed_options['disablelinks'] == 'true') ? ' data-ctfdisablelinks="true"' : '';
793
  $ctf_data_linktextcolor = $feed_options['linktextcolor'] != '' ? ' data-ctflinktextcolor="'.$feed_options['linktextcolor'].'"' : '';
 
794
  $ctf_feed_type = ! empty ( $feed_options['type'] ) ? esc_attr( $feed_options['type'] ) : 'multiple';
795
  $ctf_feed_classes = 'ctf ctf-type-' . $ctf_feed_type;
796
  $ctf_feed_classes .= ' ' . $feed_options['class'] . ' ctf-styles';
@@ -799,35 +859,55 @@ class CtfFeed
799
  $ctf_feed_html = '';
800
 
801
  $ctf_feed_html .= '<!-- Custom Twitter Feeds by Smash Balloon -->';
802
- $ctf_feed_html .= '<div id="ctf" class="' . $ctf_feed_classes . '" style="' . $feed_options['width'] . $feed_options['height'] . $feed_options['bgcolor'] . '" data-ctfshortcode="' . $this->getShortCodeJSON() . '"' .$ctf_data_disablelinks . $ctf_data_linktextcolor . '>';
803
  $tweet_set = $this->tweet_set;
804
-
805
  // dynamically include header
806
  if ( $feed_options['showheader'] ) {
807
  $ctf_feed_html .= $this->getFeedHeaderHtml( $tweet_set, $this->feed_options );
808
  }
809
 
810
- $ctf_feed_html .= '<div class="ctf-tweets">';
811
- $ctf_feed_html .= $this->getTweetSetHtml( 0 );
812
- $ctf_feed_html .= '</div>';
813
 
814
- if ( $feed_options['showbutton'] ) {
815
- $ctf_feed_html .= '<a href="javascript:void(0);" id="ctf-more" class="ctf-more" style="' . $feed_options['buttoncolor'] . $feed_options['buttontextcolor'] . '"><span>' . $feed_options['buttontext'] . '</span></a>';
816
- }
817
 
818
- if ( $feed_options['creditctf'] ) {
819
- $ctf_feed_html .= '<div class="ctf-credit-link"><a href="https://smashballoon.com/custom-twitter-feeds" target="_blank"><iclass="fa fa-twitter" aria-hidden="true"></i>Custom Twitter Feeds Plugin</a></div>';
820
- }
 
 
 
 
 
 
821
 
822
- $ctf_feed_html .= '</div>';
823
 
824
- if ( $feed_options['ajax_theme'] ) {
825
- $ctf_feed_html .= '<script type="text/javascript" src="' . CTF_JS_URL . '"></script>';
826
- }
 
 
 
 
 
 
 
 
 
 
827
 
828
  return $ctf_feed_html;
829
  }
830
 
 
 
 
 
 
 
 
831
  protected function getFeedHeaderHtml( $tweet_set, $feed_options )
832
  {
833
  $ctf_header_html = '';
@@ -835,36 +915,36 @@ class CtfFeed
835
 
836
  if ( $feed_options['type'] === 'usertimeline' ) {
837
  $ctf_header_html .= '<div class="ctf-header' . $ctf_no_bio . '" style="' . $feed_options['headerbgcolor'] . '">';
838
- $ctf_header_html .= '<a href="http://twitter.com/' . $tweet_set[0]['user']['screen_name'] . '" target="_blank" title="@' . $tweet_set[0]['user']['screen_name'] . '" class="ctf-header-link">';
839
- $ctf_header_html .= '<div class="ctf-header-text">';
840
- $ctf_header_html .= '<p class="ctf-header-user" style="' . $feed_options['headertextcolor'] . '">';
841
- $ctf_header_html .= '<span class="ctf-header-name">';
842
 
843
- if ( $feed_options['headertext'] != '' ) {
844
- $ctf_header_html .= esc_html( $feed_options['headertext'] );
845
- } else {
846
- $ctf_header_html .= esc_html( $tweet_set[0]['user']['name'] );
847
- }
848
 
849
- $ctf_header_html .= '</span>';
850
 
851
- if ( $tweet_set[0]['user']['verified'] == 1 ) {
852
- $ctf_header_html .= '<span class="ctf-verified"><i class="fa fa-check-circle"></i></span>';
853
- }
854
 
855
- $ctf_header_html .= '<span class="ctf-header-follow"><i class="fa fa-twitter" aria-hidden="true"></i>Follow</span>';
856
- $ctf_header_html .= '</p>';
857
 
858
- if ( $feed_options['showbio'] ) {
859
- $ctf_header_html .= '<p class="ctf-header-bio" style="' . $feed_options['headertextcolor'] . '">' . $tweet_set[0]['user']['description'] . '</p>';
860
- }
861
 
862
- $ctf_header_html .= '</div>';
863
- $ctf_header_html .= '<div class="ctf-header-img">';
864
- $ctf_header_html .= '<div class="ctf-header-img-hover"><i class="fa fa-twitter"></i></div>';
865
- $ctf_header_html .= '<img src="' . $tweet_set[0]['user']['profile_image_url'] . '" alt="' . $tweet_set[0]['user']['name'] . '" width="48" height="48">';
866
- $ctf_header_html .= '</div>';
867
- $ctf_header_html .= '</a>';
868
  $ctf_header_html .= '</div>';
869
  } else {
870
 
@@ -877,16 +957,16 @@ class CtfFeed
877
  }
878
 
879
  $ctf_header_html .= '<div class="ctf-header ctf-header-type-generic" style="' . $feed_options['headerbgcolor'] . '">';
880
- $ctf_header_html .= '<a href="https://twitter.com/' . $url_part . '" target="_blank" class="ctf-header-link">';
881
- $ctf_header_html .= '<div class="ctf-header-text">';
882
- $ctf_header_html .= '<p class="ctf-header-no-bio" style="' . $feed_options['headertextcolor'] . '">' . $default_header_text . '</p>';
883
- $ctf_header_html .= '</div>';
884
- $ctf_header_html .= '<div class="ctf-header-img">';
885
- $ctf_header_html .= '<div class="ctf-header-generic-icon">';
886
- $ctf_header_html .= '<i class="fa fa-twitter"></i>';
887
- $ctf_header_html .= '</div>';
888
- $ctf_header_html .= '</div>';
889
- $ctf_header_html .= '</a>';
890
  $ctf_header_html .= '</div>';
891
  }
892
 
@@ -947,65 +1027,65 @@ class CtfFeed
947
 
948
  // include tweet view
949
  $tweet_html .= '<div class="'. $tweet_classes . '" id="' . $post_id . '" style="' . $feed_options['tweetbgcolor'] .'">';
950
-
951
  if ( isset( $retweeter ) && ctf_show( 'retweeter', $feed_options ) ) {
952
  $tweet_html .= '<div class="ctf-context">';
953
- $tweet_html .= '<a href="https://twitter.com/intent/user?screen_name=' . $retweeter['screen_name'] . '" target="_blank" class="ctf-retweet-icon"><i class="fa fa-retweet"></i></a>';
954
- $tweet_html .= '<a href="https://twitter.com/' . $retweeter['screen_name'] . '" target="_blank" class="ctf-retweet-text" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">' . $retweeter['name'] . ' Retweeted</a>';
955
  $tweet_html .= '</div>';
956
  }
957
 
958
- $tweet_html .= '<div class="ctf-author-box">';
959
- $tweet_html .= '<div class="ctf-author-box-link" target="_blank" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">';
960
- if ( ctf_show( 'avatar', $feed_options ) ) {
961
- $tweet_html .= '<a href="https://twitter.com/' . $post['user']['screen_name'] .'" class="ctf-author-avatar" target="_blank" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">';
962
- $tweet_html .= '<img src="' . $post['user']['profile_image_url'] . '" width="48" height="48">';
963
- $tweet_html .= '</a>';
964
- }
965
 
966
- if ( ctf_show( 'author', $feed_options ) ) {
967
- $tweet_html .= '<a href="https://twitter.com/' . $post['user']['screen_name'] . '" target="_blank" class="ctf-author-name" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">' . $post['user']['name'] . '</a>';
968
- if ( $post['user']['verified'] == 1 ) {
969
- $tweet_html .= '<span class="ctf-verified" ><i class="fa fa-check-circle" ></i ></span>';
970
- }
971
- $tweet_html .= '<a href="https://twitter.com/' . $post['user']['screen_name'] . '" class="ctf-author-screenname" target="_blank" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">@' . $post['user']['screen_name'] . '</a>';
972
- $tweet_html .= '<span class="ctf-screename-sep">&middot;</span>';
973
  }
 
 
 
974
 
975
- if ( ctf_show( 'date', $feed_options ) ) {
976
- $tweet_html .= '<div class="ctf-tweet-meta">';
977
- $tweet_html .= '<a href="https://twitter.com/statuses/' . $post['id_str'] . '" class="ctf-tweet-date" target="_blank" style="' . $feed_options['datetextsize'] . $feed_options['datetextweight'] . $feed_options['textcolor'] . '">' . ctf_get_formatted_date( $post['created_at'] , $feed_options, $post['user']['utc_offset'] ) . '</a>';
978
- $tweet_html .= '</div>';
979
- } // show date
980
- $tweet_html .= '</div> <!-- end .ctf-author-box-link -->';
981
  $tweet_html .= '</div>';
982
 
983
  if ( ctf_show( 'text', $feed_options ) ) {
984
  $tweet_html .= '<div class="ctf-tweet-content">';
985
-
986
  if ( $feed_options['linktexttotwitter'] ) {
987
  $tweet_html .= '<a href="https://twitter.com/statuses/' . $post['id_str'] . '" target="_blank">';
988
- $tweet_html .= '<p class="ctf-tweet-text" style="' . $feed_options['tweettextsize'] . $feed_options['tweettextweight'] . $feed_options['textcolor'] . '">' . $post['text'] . '</p>';
989
  $tweet_html .= '</a>';
990
  } else {
991
  $tweet_html .= '<p class="ctf-tweet-text" style="' . $feed_options['tweettextsize'] . $feed_options['tweettextweight'] . $feed_options['textcolor'] . '">' . $post['text'] . '</p>';
992
  } // link text to twitter option is selected
993
 
994
  $tweet_html .= '</div>';
995
- } // show tweet text
996
 
997
  if ( ctf_show( 'linkbox', $feed_options ) && isset( $quoted ) ) {
998
  $tweet_html .= '<a href="https://twitter.com/statuses/' . $quoted['id_str'] . '" class="ctf-quoted-tweet" style="' . $feed_options['quotedauthorsize'] . $feed_options['quotedauthorweight'] . $feed_options['textcolor'] . '" target="_blank">';
999
- $tweet_html .= '<span class="ctf-quoted-author-name">' . $quoted['user']['name'] . '</span>';
1000
-
1001
  if ($quoted['user']['verified'] == 1) {
1002
  $tweet_html .= '<span class="ctf-quoted-verified"><i class="fa fa-check-circle" ></i></span>';
1003
- } // user is verified
1004
-
1005
- $tweet_html .= '<span class="ctf-quoted-author-screenname">@' . $quoted['user']['screen_name'] . '</span>';
1006
- $tweet_html .= '<p class="ctf-quoted-tweet-text" style="' . $feed_options['tweettextsize'] . $feed_options['tweettextweight'] . $feed_options['textcolor'] . '">' . $quoted['text'] . '</p>';
1007
  $tweet_html .= '</a>';
1008
- }// show link box
1009
 
1010
  $tweet_html .= '<div class="ctf-tweet-actions">';
1011
  if ( ctf_show( 'actions', $feed_options ) ) {
@@ -1023,7 +1103,7 @@ class CtfFeed
1023
  }
1024
  if ( ctf_show( 'twitterlink', $feed_options ) ) {
1025
  $tweet_html .= '<a href="https://twitter.com/statuses/' . $post['id_str'] . '" class="ctf-twitterlink" style="' . $feed_options['textcolor'] . '" target="_blank">' . $feed_options['twitterlinktext'] . '</a>';
1026
- } // show twitter link or actions
1027
  $tweet_html .= '</div>';
1028
  $tweet_html .= '</div>';
1029
 
@@ -1033,49 +1113,57 @@ class CtfFeed
1033
  return $tweet_html;
1034
  }
1035
 
 
 
 
 
 
1036
  public function getErrorHtml()
1037
  {
1038
  $error_html = '';
1039
  $error_html .= '<div id="ctf" class="ctf">';
1040
- $error_html .= '<div class="ctf-error">';
1041
- $error_html .= '<div class="ctf-error-user">';
1042
- $error_html .= '<p>Unable to load Tweets</p>';
1043
- $error_html .= '<a class="twitter-share-button"';
1044
- $error_html .= 'href="https://twitter.com/share"';
1045
- $error_html .= 'data-size="large"';
1046
- $error_html .= 'data-url="' . get_the_permalink() . '"';
1047
- $error_html .= 'data-text="Check out this website">';
1048
- $error_html .= '</a>';
1049
-
1050
- if ( isset( $this->feed_options['screenname'] ) ) {
1051
- $error_html .= '<a class="twitter-follow-button"';
1052
- $error_html .= 'href="https://twitter.com/' . $this->feed_options['screenname'] . '"';
1053
- $error_html .= 'data-show-count="false"';
1054
- $error_html .= 'data-size="large"';
1055
- $error_html .= 'data-dnt="true">Follow</a>';
1056
- }
1057
- $error_html .= '</div>';
1058
 
1059
- if ( current_user_can( 'manage_options' ) ) {
1060
- $error_html .= '<div class="ctf-error-admin">';
1061
 
1062
- $error_html .= '<p><b>This message is only visible to admins:</b><br />';
1063
- $error_html .= 'An error has occurred with your feed.<br />';
1064
- if ( $this->missing_credentials ) {
1065
- $error_html .= 'There is a problem with your access token, access token secret, consumer token, or consumer secret<br />';
1066
- }
1067
- if( ! empty( $this->api_obj->api_error_no ) ) {
1068
- $error_html .= 'The error response from the Twitter API is the following:<br />';
1069
- $error_html .= '<code>Error number: ' . $this->api_obj->api_error_no . '<br />';
1070
- $error_html .= 'Message: ' . $this->api_obj->api_error_message . '</code>';
1071
- $error_html .= '<a href="https://smashballoon.com/custom-twitter-feeds/support" target="_blank">Click here to troubleshoot</a></p>';
1072
- }
1073
-
1074
- $error_html .= '</div>';
1075
  }
1076
- $error_html .= '</div>'; // end .ctf-error
1077
- $error_html .= '</div>'; // end #ctf
1078
-
 
 
 
1079
  return $error_html;
1080
  }
1081
  }
27
  */
28
  protected $last_id_data;
29
 
30
+ private $num_needed_input;
31
+
32
  /**
33
  * @var mixed|void
34
  */
64
  */
65
  protected $transient_data = false;
66
 
67
+ /**
68
+ * @var int
69
+ */
70
+ private $num_tweets_needed;
71
+
72
  /**
73
  * @var array
74
  */
89
  *
90
  * @param array $atts data from the shortcode
91
  * @param string $last_id_data the last visible tweet on the feed, empty string if first set
92
+ * @param int $num_needed_input this number represents the number left to retrieve after the first set
93
  */
94
+ public function __construct( $atts, $last_id_data, $num_needed_input )
95
  {
96
  $this->atts = $atts;
97
  $this->last_id_data = $last_id_data;
98
+ $this->num_needed_input = $num_needed_input;
99
  $this->db_configure = get_option( 'ctf_configure', array() );
100
  $this->db_customize = get_option( 'ctf_customize', array() );
101
  $this->db_style = get_option( 'ctf_style', array() );
106
  *
107
  * @param array $atts data from the shortcode
108
  * @param string $last_id_data the last visible tweet on the feed, empty string if first set
109
+ * @param int $num_needed_input this number represents the number left to retrieve after the first set
110
  * @return CtfFeed the complete object for the feed
111
  */
112
+ public static function init( $atts, $last_id_data = '', $num_needed_input = 0 )
113
  {
114
+ $feed = new CtfFeed( $atts, $last_id_data, $num_needed_input );
115
  $feed->setFeedOptions();
116
  $feed->setTweetSet();
117
  return $feed;
151
  'nowtime'
152
  );
153
  $this->setStandardTextOptions( $standard_text_custom, 'customize' );
154
+ $this->setStandardTextOptions( 'retweetedtext', 'customize', 'Retweeted' );
155
 
156
+ $this->setStandardTextOptions( 'multiplier', 'customize', 1.25 );
157
  $this->setStandardTextOptions( 'twitterlinktext', 'customize', 'Twitter' );
158
+
159
  $this->setStandardTextOptions( 'buttontext', 'style', 'Load More...' );
160
 
161
  $text_size = array(
221
  {
222
  $this->setTransientName();
223
  $success = $this->maybeSetTweetsFromCache();
224
+
225
  if ( ! $success ) {
226
  $this->maybeSetTweetsFromTwitter();
227
  }
228
+
229
+ $this->num_tweets_needed = $this->numTweetsNeeded();
230
  }
231
 
232
  /**
237
  {
238
  $this->feed_options['access_token'] = isset( $this->db_configure['access_token'] ) && strlen( $this->db_configure['access_token'] ) > 30 ? $this->db_configure['access_token'] : 'missing';
239
  $this->feed_options['access_token_secret'] = isset( $this->db_configure['access_token_secret'] ) && strlen( $this->db_configure['access_token_secret'] ) > 30 ? $this->db_configure['access_token_secret'] : 'missing';
240
+
241
  // verify that access token and secret have been entered
242
  $this->setMissingCredentials();
243
  }
456
  public function setTweetsToRetrieve()
457
  {
458
  $min_tweets_to_retrieve = 10;
459
+
460
+ if ( $this->num_needed_input < 1 ) {
461
+ if ( $this->feed_options['include_replies'] ) {
462
+ $this->feed_options['count'] = $this->feed_options['num'];
 
 
 
463
  } else {
464
+ if ( $this->feed_options['num'] < 10 ) {
465
+ $this->feed_options['count'] = max( round( $this->feed_options['num'] * $this->feed_options['multiplier'] * 1.6 ), $min_tweets_to_retrieve );
466
+ } elseif ( $this->feed_options['num'] < 30 ) {
467
+ $this->feed_options['count'] = round( $this->feed_options['num'] * $this->feed_options['multiplier'] * 1.2 );
468
+ } else {
469
+ $this->feed_options['count'] = round( $this->feed_options['num'] * $this->feed_options['multiplier'] );
470
+ }
471
  }
472
+ } else {
473
+ $this->feed_options['count'] = max( $this->num_needed_input, 50 );
474
+ $this->feed_options['num'] = $this->num_needed_input;
475
  }
476
+
477
  }
478
 
479
  /**
498
  $this->working_term = isset( $this->atts['hashtag'] ) ? $this->atts['hashtag'] : ( isset( $this->atts['search'] ) ? $this->atts['search'] : '' );
499
  $this->feed_options['feed_term'] = isset( $this->working_term ) ? ctf_validate_search_text( $this->working_term ) : ( ( isset( $this->db_configure['search_text'] ) ) ? $this->db_configure['search_text'] : '' );
500
  }
501
+
502
  if ( $this->feed_options['type'] == '' ) {
503
  $this->feed_options['type'] = isset( $this->db_configure['type'] ) ? $this->db_configure['type'] : 'usertimeline';
504
  switch ( $this->feed_options['type'] ) {
568
  */
569
  private function validateCache()
570
  {
571
+ if ( isset( $this->transient_data[0] ) ) {
572
+ return false;
 
 
 
 
573
  } else {
574
+ return 'invalid cache';
 
 
 
 
575
  }
576
  }
577
 
611
  $this->api_obj = $this->apiConnect( $this->feed_options['type'], $this->feed_options['feed_term'] );
612
  $this->tweet_set = json_decode( $this->api_obj->json , $assoc = true );
613
 
614
+ // check for errors/tweets present
615
  if ( isset( $this->tweet_set['errors'][0] ) ) {
616
  $this->api_obj->api_error_no = $this->tweet_set['errors'][0]['code'];
617
  $this->api_obj->api_error_message = $this->tweet_set['errors'][0]['message'];
618
  $this->tweet_set = false;
619
  }
620
+
621
+ $tweets = isset( $this->tweet_set['statuses'] ) ? $this->tweet_set['statuses'] : $this->tweet_set;
622
+
623
+ if ( empty( $tweets ) ) {
624
+ $this->errors['error_message'] = 'No Tweets returned';
625
+ $this->tweet_set = false;
626
+ }
627
+ }
628
+
629
+
630
+ /**
631
+ * calculates how many tweets short the feed is so more can be retrieved via ajax
632
+ *
633
+ * @return int number of tweets needed
634
+ */
635
+ protected function numTweetsNeeded() {
636
+ $tweet_count = isset( $this->tweet_set['statuses'] ) ? count( $this->tweet_set['statuses'] ) : count( $this->tweet_set );
637
+
638
+ return $this->feed_options['num'] - $tweet_count;
639
  }
640
 
641
  /**
696
  $this->tweet_set = $trimmed_tweets;
697
  }
698
 
699
+ /**
700
+ * method to be overridden by pro
701
+ *
702
+ * @param $trimmed current trimmed tweet araray
703
+ * @param $tweet current tweet data to be trimmed
704
+ * @return mixed final trimmed tweet
705
+ */
706
  protected function filterTrimmedTweets( $trimmed, $tweet )
707
  {
708
  return $trimmed;
743
 
744
  return $json_data;
745
  }
746
+
747
+ /**
748
+ * uses the endpoint to determing what get fields need to be set
749
+ *
750
+ * @param $end_point api endpoint needed
751
+ * @param $feed_term term associated with the endpoint, user name or search term
752
+ * @return array the get fields for the request
753
+ */
754
+ protected function setGetFieldsArray( $end_point, $feed_term )
755
  {
756
  $get_fields = array();
757
  if ( $end_point === 'usertimeline' ) {
766
  if ( $end_point === 'search' ) {
767
  $get_fields['q'] = $feed_term;
768
  }
769
+
770
  return $get_fields;
771
  }
772
 
815
  return $twitter_connect->performRequest();
816
  }
817
 
818
+ /**
819
+ * If the feed runs out of tweets to display for some reason,
820
+ * this function creates a graceful failure message
821
+ *
822
+ * @param $feed_options
823
+ * @return string html for "out of tweets" message
824
+ */
825
  protected function getOutOfTweetsHtml( $feed_options )
826
  {
827
  $html = '';
828
 
829
  $html .= '<div class="ctf-out-of-tweets">';
830
+ $html .= '<p>That\'s all! No more Tweets to load</p>';
831
+ $html .= '<p>';
832
+ $html .= '<a class="twitter-share-button" href="https://twitter.com/share" target="_blank" data-size="large" data-url="<?php echo get_home_url(); ?>">Share</a>';
833
+ if ( isset( $feed_options['screenname'] ) ) {
834
+ $html .= '<a class="twitter-follow-button" href="https://twitter.com/' . $feed_options['screenname'] . '" target="_blank" data-show-count="false" data-size="large" data-dnt="true">Follow</a>';
835
+ }
836
+ $html .= '</p>';
837
+ $html .= "<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>";
838
  $html .= '</div>';
839
+
840
  return $html;
841
  }
842
 
843
+ /**
844
+ * creates opening html for the feed
845
+ *
846
+ * @return string opening html that creates the feed
847
+ */
848
+ public function getFeedOpeningHtml()
849
  {
850
  $feed_options = $this->feed_options;
851
  $ctf_data_disablelinks = ($feed_options['disablelinks'] == 'true') ? ' data-ctfdisablelinks="true"' : '';
852
  $ctf_data_linktextcolor = $feed_options['linktextcolor'] != '' ? ' data-ctflinktextcolor="'.$feed_options['linktextcolor'].'"' : '';
853
+ $ctf_data_needed = $this->num_tweets_needed;
854
  $ctf_feed_type = ! empty ( $feed_options['type'] ) ? esc_attr( $feed_options['type'] ) : 'multiple';
855
  $ctf_feed_classes = 'ctf ctf-type-' . $ctf_feed_type;
856
  $ctf_feed_classes .= ' ' . $feed_options['class'] . ' ctf-styles';
859
  $ctf_feed_html = '';
860
 
861
  $ctf_feed_html .= '<!-- Custom Twitter Feeds by Smash Balloon -->';
862
+ $ctf_feed_html .= '<div id="ctf" class="' . $ctf_feed_classes . '" style="' . $feed_options['width'] . $feed_options['height'] . $feed_options['bgcolor'] . '" data-ctfshortcode="' . $this->getShortCodeJSON() . '"' .$ctf_data_disablelinks . $ctf_data_linktextcolor . ' data-ctfneeded="'. $ctf_data_needed .'">';
863
  $tweet_set = $this->tweet_set;
864
+
865
  // dynamically include header
866
  if ( $feed_options['showheader'] ) {
867
  $ctf_feed_html .= $this->getFeedHeaderHtml( $tweet_set, $this->feed_options );
868
  }
869
 
870
+ $ctf_feed_html .= '<div class="ctf-tweets">';
 
 
871
 
872
+ return $ctf_feed_html;
873
+ }
 
874
 
875
+ /**
876
+ * creates opening html for the feed
877
+ *
878
+ * @return string opening html that creates the feed
879
+ */
880
+ public function getFeedClosingHtml()
881
+ {
882
+ $feed_options = $this->feed_options;
883
+ $ctf_feed_html = '';
884
 
885
+ $ctf_feed_html .= '</div>'; // closing div for ctf-tweets
886
 
887
+ if ( $feed_options['showbutton'] ) {
888
+ $ctf_feed_html .= '<a href="javascript:void(0);" id="ctf-more" class="ctf-more" style="' . $feed_options['buttoncolor'] . $feed_options['buttontextcolor'] . '"><span>' . $feed_options['buttontext'] . '</span></a>';
889
+ }
890
+
891
+ if ( $feed_options['creditctf'] ) {
892
+ $ctf_feed_html .= '<div class="ctf-credit-link"><a href="https://smashballoon.com/custom-twitter-feeds" target="_blank"><i class="fa fa-twitter" aria-hidden="true"></i>Custom Twitter Feeds Plugin</a></div>';
893
+ }
894
+
895
+ $ctf_feed_html .= '</div>'; // closing div tag for #ctf
896
+
897
+ if ( $feed_options['ajax_theme'] ) {
898
+ $ctf_feed_html .= '<script type="text/javascript" src="' . CTF_JS_URL . '"></script>';
899
+ }
900
 
901
  return $ctf_feed_html;
902
  }
903
 
904
+ /**
905
+ * creates html for header of the feed
906
+ *
907
+ * @param $tweet_set string trimmed tweets to be added to the feed
908
+ * @param $feed_options options for the feed
909
+ * @return string html that creates the header of the feed
910
+ */
911
  protected function getFeedHeaderHtml( $tweet_set, $feed_options )
912
  {
913
  $ctf_header_html = '';
915
 
916
  if ( $feed_options['type'] === 'usertimeline' ) {
917
  $ctf_header_html .= '<div class="ctf-header' . $ctf_no_bio . '" style="' . $feed_options['headerbgcolor'] . '">';
918
+ $ctf_header_html .= '<a href="http://twitter.com/' . $tweet_set[0]['user']['screen_name'] . '" target="_blank" title="@' . $tweet_set[0]['user']['screen_name'] . '" class="ctf-header-link">';
919
+ $ctf_header_html .= '<div class="ctf-header-text">';
920
+ $ctf_header_html .= '<p class="ctf-header-user" style="' . $feed_options['headertextcolor'] . '">';
921
+ $ctf_header_html .= '<span class="ctf-header-name">';
922
 
923
+ if ( $feed_options['headertext'] != '' ) {
924
+ $ctf_header_html .= esc_html( $feed_options['headertext'] );
925
+ } else {
926
+ $ctf_header_html .= esc_html( $tweet_set[0]['user']['name'] );
927
+ }
928
 
929
+ $ctf_header_html .= '</span>';
930
 
931
+ if ( $tweet_set[0]['user']['verified'] == 1 ) {
932
+ $ctf_header_html .= '<span class="ctf-verified"><i class="fa fa-check-circle"></i></span>';
933
+ }
934
 
935
+ $ctf_header_html .= '<span class="ctf-header-follow"><i class="fa fa-twitter" aria-hidden="true"></i>Follow</span>';
936
+ $ctf_header_html .= '</p>';
937
 
938
+ if ( $feed_options['showbio'] ) {
939
+ $ctf_header_html .= '<p class="ctf-header-bio" style="' . $feed_options['headertextcolor'] . '">' . $tweet_set[0]['user']['description'] . '</p>';
940
+ }
941
 
942
+ $ctf_header_html .= '</div>';
943
+ $ctf_header_html .= '<div class="ctf-header-img">';
944
+ $ctf_header_html .= '<div class="ctf-header-img-hover"><i class="fa fa-twitter"></i></div>';
945
+ $ctf_header_html .= '<img src="' . $tweet_set[0]['user']['profile_image_url'] . '" alt="' . $tweet_set[0]['user']['name'] . '" width="48" height="48">';
946
+ $ctf_header_html .= '</div>';
947
+ $ctf_header_html .= '</a>';
948
  $ctf_header_html .= '</div>';
949
  } else {
950
 
957
  }
958
 
959
  $ctf_header_html .= '<div class="ctf-header ctf-header-type-generic" style="' . $feed_options['headerbgcolor'] . '">';
960
+ $ctf_header_html .= '<a href="https://twitter.com/' . $url_part . '" target="_blank" class="ctf-header-link">';
961
+ $ctf_header_html .= '<div class="ctf-header-text">';
962
+ $ctf_header_html .= '<p class="ctf-header-no-bio" style="' . $feed_options['headertextcolor'] . '">' . $default_header_text . '</p>';
963
+ $ctf_header_html .= '</div>';
964
+ $ctf_header_html .= '<div class="ctf-header-img">';
965
+ $ctf_header_html .= '<div class="ctf-header-generic-icon">';
966
+ $ctf_header_html .= '<i class="fa fa-twitter"></i>';
967
+ $ctf_header_html .= '</div>';
968
+ $ctf_header_html .= '</div>';
969
+ $ctf_header_html .= '</a>';
970
  $ctf_header_html .= '</div>';
971
  }
972
 
1027
 
1028
  // include tweet view
1029
  $tweet_html .= '<div class="'. $tweet_classes . '" id="' . $post_id . '" style="' . $feed_options['tweetbgcolor'] .'">';
1030
+
1031
  if ( isset( $retweeter ) && ctf_show( 'retweeter', $feed_options ) ) {
1032
  $tweet_html .= '<div class="ctf-context">';
1033
+ $tweet_html .= '<a href="https://twitter.com/intent/user?screen_name=' . $retweeter['screen_name'] . '" target="_blank" class="ctf-retweet-icon"><i class="fa fa-retweet"></i></a>';
1034
+ $tweet_html .= '<a href="https://twitter.com/' . $retweeter['screen_name'] . '" target="_blank" class="ctf-retweet-text" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">' . $retweeter['name'] . ' ' . $feed_options['retweetedtext'] . '</a>';
1035
  $tweet_html .= '</div>';
1036
  }
1037
 
1038
+ $tweet_html .= '<div class="ctf-author-box">';
1039
+ $tweet_html .= '<div class="ctf-author-box-link" target="_blank" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">';
1040
+ if ( ctf_show( 'avatar', $feed_options ) ) {
1041
+ $tweet_html .= '<a href="https://twitter.com/' . $post['user']['screen_name'] .'" class="ctf-author-avatar" target="_blank" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">';
1042
+ $tweet_html .= '<img src="' . $post['user']['profile_image_url'] . '" width="48" height="48">';
1043
+ $tweet_html .= '</a>';
1044
+ }
1045
 
1046
+ if ( ctf_show( 'author', $feed_options ) ) {
1047
+ $tweet_html .= '<a href="https://twitter.com/' . $post['user']['screen_name'] . '" target="_blank" class="ctf-author-name" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">' . $post['user']['name'] . '</a>';
1048
+ if ( $post['user']['verified'] == 1 ) {
1049
+ $tweet_html .= '<span class="ctf-verified" ><i class="fa fa-check-circle" ></i ></span>';
 
 
 
1050
  }
1051
+ $tweet_html .= '<a href="https://twitter.com/' . $post['user']['screen_name'] . '" class="ctf-author-screenname" target="_blank" style="' . $feed_options['authortextsize'] . $feed_options['authortextweight'] . $feed_options['textcolor'] . '">@' . $post['user']['screen_name'] . '</a>';
1052
+ $tweet_html .= '<span class="ctf-screename-sep" style="' . $feed_options['datetextsize'] . $feed_options['datetextweight'] . $feed_options['textcolor'] . '">&middot;</span>';
1053
+ }
1054
 
1055
+ if ( ctf_show( 'date', $feed_options ) ) {
1056
+ $tweet_html .= '<div class="ctf-tweet-meta">';
1057
+ $tweet_html .= '<a href="https://twitter.com/statuses/' . $post['id_str'] . '" class="ctf-tweet-date" target="_blank" style="' . $feed_options['datetextsize'] . $feed_options['datetextweight'] . $feed_options['textcolor'] . '">' . ctf_get_formatted_date( $post['created_at'] , $feed_options, $post['user']['utc_offset'] ) . '</a>';
1058
+ $tweet_html .= '</div>';
1059
+ } // show date
1060
+ $tweet_html .= '</div> <!-- end .ctf-author-box-link -->';
1061
  $tweet_html .= '</div>';
1062
 
1063
  if ( ctf_show( 'text', $feed_options ) ) {
1064
  $tweet_html .= '<div class="ctf-tweet-content">';
1065
+
1066
  if ( $feed_options['linktexttotwitter'] ) {
1067
  $tweet_html .= '<a href="https://twitter.com/statuses/' . $post['id_str'] . '" target="_blank">';
1068
+ $tweet_html .= '<p class="ctf-tweet-text" style="' . $feed_options['tweettextsize'] . $feed_options['tweettextweight'] . $feed_options['textcolor'] . '">' . $post['text'] . '</p>';
1069
  $tweet_html .= '</a>';
1070
  } else {
1071
  $tweet_html .= '<p class="ctf-tweet-text" style="' . $feed_options['tweettextsize'] . $feed_options['tweettextweight'] . $feed_options['textcolor'] . '">' . $post['text'] . '</p>';
1072
  } // link text to twitter option is selected
1073
 
1074
  $tweet_html .= '</div>';
1075
+ } // show tweet text
1076
 
1077
  if ( ctf_show( 'linkbox', $feed_options ) && isset( $quoted ) ) {
1078
  $tweet_html .= '<a href="https://twitter.com/statuses/' . $quoted['id_str'] . '" class="ctf-quoted-tweet" style="' . $feed_options['quotedauthorsize'] . $feed_options['quotedauthorweight'] . $feed_options['textcolor'] . '" target="_blank">';
1079
+ $tweet_html .= '<span class="ctf-quoted-author-name">' . $quoted['user']['name'] . '</span>';
1080
+
1081
  if ($quoted['user']['verified'] == 1) {
1082
  $tweet_html .= '<span class="ctf-quoted-verified"><i class="fa fa-check-circle" ></i></span>';
1083
+ } // user is verified
1084
+
1085
+ $tweet_html .= '<span class="ctf-quoted-author-screenname">@' . $quoted['user']['screen_name'] . '</span>';
1086
+ $tweet_html .= '<p class="ctf-quoted-tweet-text" style="' . $feed_options['tweettextsize'] . $feed_options['tweettextweight'] . $feed_options['textcolor'] . '">' . $quoted['text'] . '</p>';
1087
  $tweet_html .= '</a>';
1088
+ }// show link box
1089
 
1090
  $tweet_html .= '<div class="ctf-tweet-actions">';
1091
  if ( ctf_show( 'actions', $feed_options ) ) {
1103
  }
1104
  if ( ctf_show( 'twitterlink', $feed_options ) ) {
1105
  $tweet_html .= '<a href="https://twitter.com/statuses/' . $post['id_str'] . '" class="ctf-twitterlink" style="' . $feed_options['textcolor'] . '" target="_blank">' . $feed_options['twitterlinktext'] . '</a>';
1106
+ } // show twitter link or actions
1107
  $tweet_html .= '</div>';
1108
  $tweet_html .= '</div>';
1109
 
1113
  return $tweet_html;
1114
  }
1115
 
1116
+ /**
1117
+ * displays a message if there is an error in the feed
1118
+ *
1119
+ * @return string error html
1120
+ */
1121
  public function getErrorHtml()
1122
  {
1123
  $error_html = '';
1124
  $error_html .= '<div id="ctf" class="ctf">';
1125
+ $error_html .= '<div class="ctf-error">';
1126
+ $error_html .= '<div class="ctf-error-user">';
1127
+ $error_html .= '<p>Unable to load Tweets</p>';
1128
+ $error_html .= '<a class="twitter-share-button"';
1129
+ $error_html .= 'href="https://twitter.com/share"';
1130
+ $error_html .= 'data-size="large"';
1131
+ $error_html .= 'data-url="' . get_the_permalink() . '"';
1132
+ $error_html .= 'data-text="Check out this website">';
1133
+ $error_html .= '</a>';
1134
+
1135
+ if ( isset( $this->feed_options['screenname'] ) ) {
1136
+ $error_html .= '<a class="twitter-follow-button"';
1137
+ $error_html .= 'href="https://twitter.com/' . $this->feed_options['screenname'] . '"';
1138
+ $error_html .= 'data-show-count="false"';
1139
+ $error_html .= 'data-size="large"';
1140
+ $error_html .= 'data-dnt="true">Follow</a>';
1141
+ }
1142
+ $error_html .= '</div>';
1143
 
1144
+ if ( current_user_can( 'manage_options' ) ) {
1145
+ $error_html .= '<div class="ctf-error-admin">';
1146
 
1147
+ $error_html .= '<p><b>This message is only visible to admins:</b><br />';
1148
+ $error_html .= 'An error has occurred with your feed.<br />';
1149
+ if ( $this->missing_credentials ) {
1150
+ $error_html .= 'There is a problem with your access token, access token secret, consumer token, or consumer secret<br />';
1151
+ }
1152
+ if ( isset( $this->errors['error_message'] ) ) {
1153
+ $error_html .= $this->errors['error_message'] . '<br />';
1154
+ }
1155
+ if( ! empty( $this->api_obj->api_error_no ) ) {
1156
+ $error_html .= 'The error response from the Twitter API is the following:<br />';
1157
+ $error_html .= '<code>Error number: ' . $this->api_obj->api_error_no . '<br />';
1158
+ $error_html .= 'Message: ' . $this->api_obj->api_error_message . '</code>';
1159
+ $error_html .= '<a href="https://smashballoon.com/custom-twitter-feeds/support" target="_blank">Click here to troubleshoot</a></p>';
1160
  }
1161
+
1162
+ $error_html .= '</div>';
1163
+ }
1164
+ $error_html .= '</div>'; // end .ctf-error
1165
+ $error_html .= '</div>'; // end #ctf
1166
+
1167
  return $error_html;
1168
  }
1169
  }
js/ctf-scripts.js CHANGED
@@ -2,144 +2,166 @@ var ctf_js_exists = (typeof ctf_js_exists !== 'undefined') ? true : false;
2
  if(!ctf_js_exists){
3
 
4
  (function ($) {
5
-
6
- $('.ctf').each(function(){
7
 
8
- var $ctf = $(this);
 
9
 
10
- //Adds a class if the feed is in a narrow column or on mobile so we can make styling adjustments
11
- if( $ctf.width() <= 480 ) $ctf.addClass('ctf-narrow');
12
- if ( $ctf.width() <= 320 ) $ctf.addClass('ctf-super-narrow');
13
 
14
- // add the load more button and input to simulate a dynamic json file call
15
- $ctf.find('.ctf-more').on('click', function() {
16
- // read the json that is in the ctf-shortcode-data that contains all of the shortcode arguments
17
- var $ctfMore = $(this),
18
- lastIDData = $ctf.find('.ctf-item').last().attr('id'),
19
- shortcodeData = $ctf.attr('data-ctfshortcode');
20
 
21
- //Display loader
22
- $ctfMore.addClass('ctf-loading').append('<div class="ctf-loader"></div>');
23
- $ctfMore.find('.ctf-loader').css('background-color', $ctfMore.css('color'));
24
-
25
- jQuery.ajax({
26
- url : ctf.ajax_url,
27
- type : 'post',
28
- data : {
29
- action : 'ctf_get_more_posts',
30
- last_id_data : lastIDData,
31
- shortcode_data : shortcodeData
32
- },
33
- success : function(data) {
34
- // appends the html echoed out in ctf_get_new_posts() to the last post element
35
- $ctf.find('.ctf-item').removeClass('ctf-new').last().after(data);
36
 
37
- if($ctf.find('.ctf-out-of-tweets').length) {
38
- $ctfMore.hide();
39
- //Fade in the no more tweets message
40
- $ctf.find('.ctf-out-of-tweets p').eq(0).fadeIn().end().eq(1).delay(500).fadeIn();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
 
42
 
43
- //Remove loader
44
- $ctfMore.removeClass('ctf-loading').find('.ctf-loader').remove();
45
-
46
- //Re-run JS code
47
- ctfScripts();
 
48
 
 
 
 
 
49
  }
50
- }); // ajax call
51
- });
52
 
53
 
54
- //Runs every time new tweets are loaded
55
- function ctfScripts(){
56
 
57
- //Loop through each newly loaded tweet
58
- $ctf.find('.ctf-item.ctf-new').each(function(){
59
 
60
- var $ctfItem = $(this),
61
- $ctfText = $ctfItem.find('.ctf-tweet-text'),
62
- ctfTextStr = ' ' + $ctfText.html();
63
 
64
- if( $ctf.attr('data-ctfdisablelinks') != 'true' && typeof ctfTextStr !== 'undefined' ){
65
 
66
- var ctfLinkColor = $ctf.attr('data-ctflinktextcolor'),
67
- ctfLinkColorHex = '';
68
- if( ctfLinkColor ) ctfLinkColorHex = ctfLinkColor.replace(';','').split("#")[1];
69
-
70
- //Link URLs
71
- window.ctfLinkify=(function(){var k="[a-z\\d.-]+://",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])",c="(?:(?:[^\\s!@#$%^&*()_=+[\\]{}\\\\|;:'\",.<>/?]+)\\.)+",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)",f="(?:"+c+n+"|"+h+")",o="(?:[;/][^#?<>\\s]*)?",e="(?:\\?[^#<>\\s]*)?(?:#[^<>\\s]*)?",d="\\b"+k+"[^<>\\s]+",a="\\b"+f+o+e+"(?!\\w)",m="mailto:",j="(?:"+m+")?[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@"+f+e+"(?!\\w)",l=new RegExp("(?:"+d+"|"+a+"|"+j+")","ig"),g=new RegExp("^"+k,"i"),b={"'":"`",">":"<",")":"(","]":"[","}":"{","B;":"B+","b:":"b9"},i={callback:function(q,p){return p?'<a href="'+p+'" title="'+p+'" target="_blank">'+q+"</a>":q},punct_regexp:/(?:[!?.,:;'"]|(?:&|&amp;)(?:lt|gt|quot|apos|raquo|laquo|rsaquo|lsaquo);)$/};return function(u,z){z=z||{};var w,v,A,p,x="",t=[],s,E,C,y,q,D,B,r;for(v in i){if(z[v]===undefined){z[v]=i[v]}}while(w=l.exec(u)){A=w[0];E=l.lastIndex;C=E-A.length;if(/[\/:]/.test(u.charAt(C-1))){continue}do{y=A;r=A.substr(-1);B=b[r];if(B){q=A.match(new RegExp("\\"+B+"(?!$)","g"));D=A.match(new RegExp("\\"+r,"g"));if((q?q.length:0)<(D?D.length:0)){A=A.substr(0,A.length-1);E--}}if(z.punct_regexp){A=A.replace(z.punct_regexp,function(F){E-=F.length;return""})}}while(A.length&&A!==y);p=A;if(!g.test(p)){p=(p.indexOf("@")!==-1?(!p.indexOf(m)?"":m):!p.indexOf("irc.")?"irc://":!p.indexOf("ftp.")?"ftp://":"http://")+p}if(s!=C){t.push([u.slice(s,C)]);s=E}t.push([A,p])}t.push([u.substr(s)]);for(v=0;v<t.length;v++){x+=z.callback.apply(window,t[v])}return x||u}})();
72
- ctfTextStr = ctfLinkify( ctfTextStr );
73
-
74
- //Link hashtags
75
- 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;
76
-
77
- function ctfHashReplacer(hash){
78
- //Remove white space at beginning of hash
79
- var replacementString = jQuery.trim(hash);
80
- //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"
81
- if ( /^#[0-9A-F]{6}$/i.test( replacementString ) ){
82
- return replacementString;
83
- } else {
84
- return ' <a href="https://twitter.com/hashtag/'+ replacementString.substring(1) +'" target="_blank" rel="nofollow">' + replacementString + '</a>';
85
- }
86
- }
87
-
88
- //Replace hashtags in text
89
- if(ctfTextStr.length > 0){
90
- //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.
91
- ctfTextStr = ctfTextStr.replace(/<br>/g, "<br> ");
92
- ctfTextStr = ctfTextStr.replace( ctfHashRegex , ctfHashReplacer );
93
- }
94
 
95
- //Link @tags
96
- function ctfReplaceTags(tag){
97
- var replacementString = jQuery.trim(tag);
98
- return ' <a href="https://twitter.com/'+ replacementString.substring(1) +'" target="_blank" rel="nofollow">' + replacementString + '</a>';
99
- }
100
- var tagRegex = /[\s][@]+[A-Za-z0-9-_]+/g;
101
- ctfTextStr = ctfTextStr.replace( tagRegex , ctfReplaceTags );
102
 
 
 
 
103
 
104
- //Replace text with linked version
105
- $ctfText.html( ctfTextStr.trim() );
 
 
 
106
 
107
- //Add link color
108
- $ctfText.find('a').css('color', '#' + ctfLinkColorHex);
 
 
 
 
109
 
110
- } // End "ctfdata-disablelinks" check
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
- }); // End .ctfItem loop
 
 
 
 
 
 
 
113
 
114
- //Change color of retweet icon to match text
115
- // $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
116
 
117
- //Change colors of some items to match tweet text
118
- $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') );
119
 
120
- //Set the line height of the twitter link to match the icons so that it's centered vertically
121
- var $ctfIconFirst = $ctf.find('.ctf-tweet-actions a').first();
122
- $ctf.find('.ctf-twitterlink').css('line-height', $ctfIconFirst.height() + 'px' );
123
 
124
- //Adjust icon number font size to be slightly smaller than the icon size
125
- if( $ctfIconFirst.length ){
126
- var ctfIconSize = parseInt( $ctfIconFirst.css('font-size').replace('px', '') );
127
- $ctf.find('.ctf-action-count').css({'display' : 'block', 'font-size' : (ctfIconSize-4) + 'px', 'line-height' : $ctfIconFirst.height() + 'px' });
128
  }
 
 
 
 
 
 
 
 
 
 
 
129
 
130
- //Header profile pic hover
131
- $ctf.find('.ctf-header .ctf-header-link').hover(function(){
132
- $ctf.find('.ctf-header .ctf-header-img-hover').fadeIn(200);
133
- }, function(){
134
- $ctf.find('.ctf-header .ctf-header-img-hover').stop().fadeOut(600);
135
- });
136
 
137
- } // end ctfScripts()
138
- ctfScripts();
 
 
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  }); // end .cff each loop
142
-
143
 
144
  })(jQuery);
145
 
2
  if(!ctf_js_exists){
3
 
4
  (function ($) {
 
 
5
 
6
+ //Runs every time new tweets are loaded
7
+ function ctfScripts( $ctf ){
8
 
9
+ //Loop through each newly loaded tweet
10
+ $ctf.find('.ctf-item.ctf-new').each(function(){
 
11
 
12
+ var $ctfItem = $(this),
13
+ $ctfText = $ctfItem.find('.ctf-tweet-text'),
14
+ ctfTextStr = ' ' + $ctfText.html();
 
 
 
15
 
16
+ if( $ctf.attr('data-ctfdisablelinks') != 'true' && typeof ctfTextStr !== 'undefined' ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ var ctfLinkColor = $ctf.attr('data-ctflinktextcolor'),
19
+ ctfLinkColorHex = '';
20
+ if( ctfLinkColor ) ctfLinkColorHex = ctfLinkColor.replace(';','').split("#")[1];
21
+
22
+ //Link URLs
23
+ window.ctfLinkify=(function(){var k="[a-z\\d.-]+://",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])",c="(?:(?:[^\\s!@#$%^&*()_=+[\\]{}\\\\|;:'\",.<>/?]+)\\.)+",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)",f="(?:"+c+n+"|"+h+")",o="(?:[;/][^#?<>\\s]*)?",e="(?:\\?[^#<>\\s]*)?(?:#[^<>\\s]*)?",d="\\b"+k+"[^<>\\s]+",a="\\b"+f+o+e+"(?!\\w)",m="mailto:",j="(?:"+m+")?[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@"+f+e+"(?!\\w)",l=new RegExp("(?:"+d+"|"+a+"|"+j+")","ig"),g=new RegExp("^"+k,"i"),b={"'":"`",">":"<",")":"(","]":"[","}":"{","B;":"B+","b:":"b9"},i={callback:function(q,p){return p?'<a href="'+p+'" title="'+p+'" target="_blank">'+q+"</a>":q},punct_regexp:/(?:[!?.,:;'"]|(?:&|&amp;)(?:lt|gt|quot|apos|raquo|laquo|rsaquo|lsaquo);)$/};return function(u,z){z=z||{};var w,v,A,p,x="",t=[],s,E,C,y,q,D,B,r;for(v in i){if(z[v]===undefined){z[v]=i[v]}}while(w=l.exec(u)){A=w[0];E=l.lastIndex;C=E-A.length;if(/[\/:]/.test(u.charAt(C-1))){continue}do{y=A;r=A.substr(-1);B=b[r];if(B){q=A.match(new RegExp("\\"+B+"(?!$)","g"));D=A.match(new RegExp("\\"+r,"g"));if((q?q.length:0)<(D?D.length:0)){A=A.substr(0,A.length-1);E--}}if(z.punct_regexp){A=A.replace(z.punct_regexp,function(F){E-=F.length;return""})}}while(A.length&&A!==y);p=A;if(!g.test(p)){p=(p.indexOf("@")!==-1?(!p.indexOf(m)?"":m):!p.indexOf("irc.")?"irc://":!p.indexOf("ftp.")?"ftp://":"http://")+p}if(s!=C){t.push([u.slice(s,C)]);s=E}t.push([A,p])}t.push([u.substr(s)]);for(v=0;v<t.length;v++){x+=z.callback.apply(window,t[v])}return x||u}})();
24
+ ctfTextStr = ctfLinkify( ctfTextStr );
25
+
26
+ //Link hashtags
27
+ 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;
28
+
29
+ function ctfHashReplacer(hash){
30
+ //Remove white space at beginning of hash
31
+ var replacementString = jQuery.trim(hash);
32
+ //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"
33
+ if ( /^#[0-9A-F]{6}$/i.test( replacementString ) ){
34
+ return replacementString;
35
+ } else {
36
+ return ' <a href="https://twitter.com/hashtag/'+ replacementString.substring(1) +'" target="_blank" rel="nofollow">' + replacementString + '</a>';
37
  }
38
+ }
39
 
40
+ //Replace hashtags in text
41
+ if(ctfTextStr.length > 0){
42
+ //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.
43
+ ctfTextStr = ctfTextStr.replace(/<br>/g, "<br> ");
44
+ ctfTextStr = ctfTextStr.replace( ctfHashRegex , ctfHashReplacer );
45
+ }
46
 
47
+ //Link @tags
48
+ function ctfReplaceTags(tag){
49
+ var replacementString = jQuery.trim(tag);
50
+ return ' <a href="https://twitter.com/'+ replacementString.substring(1) +'" target="_blank" rel="nofollow">' + replacementString + '</a>';
51
  }
52
+ var tagRegex = /[\s][@]+[A-Za-z0-9-_]+/g;
53
+ ctfTextStr = ctfTextStr.replace( tagRegex , ctfReplaceTags );
54
 
55
 
56
+ //Replace text with linked version
57
+ $ctfText.html( ctfTextStr.trim() );
58
 
59
+ //Add link color
60
+ $ctfText.find('a').css('color', '#' + ctfLinkColorHex);
61
 
62
+ } // End "ctfdata-disablelinks" check
 
 
63
 
64
+ }); // End .ctfItem loop
65
 
66
+ //Change color of retweet icon to match text
67
+ // $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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
+ //Change colors of some items to match tweet text
70
+ $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') );
 
 
 
 
 
71
 
72
+ //Set the line height of the twitter link to match the icons so that it's centered vertically
73
+ var $ctfIconFirst = $ctf.find('.ctf-tweet-actions a').first();
74
+ $ctf.find('.ctf-twitterlink').css('line-height', $ctfIconFirst.height() + 'px' );
75
 
76
+ //Adjust icon number font size to be slightly smaller than the icon size
77
+ if( $ctfIconFirst.length ){
78
+ var ctfIconSize = parseInt( $ctfIconFirst.css('font-size').replace('px', '') );
79
+ $ctf.find('.ctf-action-count').css({'display' : 'block', 'font-size' : (ctfIconSize-4) + 'px', 'line-height' : $ctfIconFirst.height() + 'px' });
80
+ }
81
 
82
+ //Header profile pic hover
83
+ $ctf.find('.ctf-header .ctf-header-link').hover(function(){
84
+ $ctf.find('.ctf-header .ctf-header-img-hover').fadeIn(200);
85
+ }, function(){
86
+ $ctf.find('.ctf-header .ctf-header-img-hover').stop().fadeOut(600);
87
+ });
88
 
89
+ // Call Custom JS if it exists
90
+ if (typeof ctf_custom_js == 'function') ctf_custom_js($);
91
+
92
+ } // end ctfScripts()
93
+
94
+ function ctfLoadTweets( lastIDData, shortcodeData , $ctf, $ctfMore, numNeeded ) {
95
+ //Display loader
96
+ $ctfMore.addClass('ctf-loading').append('<div class="ctf-loader"></div>');
97
+ $ctfMore.find('.ctf-loader').css('background-color', $ctfMore.css('color'));
98
+
99
+ jQuery.ajax({
100
+ url : ctf.ajax_url,
101
+ type : 'post',
102
+ data : {
103
+ action : 'ctf_get_more_posts',
104
+ last_id_data : lastIDData,
105
+ shortcode_data : shortcodeData,
106
+ num_needed : numNeeded
107
+ },
108
+ success : function(data) {
109
+ if(lastIDData !== '') {
110
+ // appends the html echoed out in ctf_get_new_posts() to the last post element
111
+ $ctf.find('.ctf-item').removeClass('ctf-new').last().after(data);
112
 
113
+ if($ctf.find('.ctf-out-of-tweets').length) {
114
+ $ctfMore.hide();
115
+ //Fade in the no more tweets message
116
+ $ctf.find('.ctf-out-of-tweets p').eq(0).fadeIn().end().eq(1).delay(500).fadeIn();
117
+ }
118
+ } else {
119
+ $ctf.find('.ctf-tweets').append(data);
120
+ }
121
 
 
 
122
 
123
+ //Remove loader
124
+ $ctfMore.removeClass('ctf-loading').find('.ctf-loader').remove();
125
 
126
+ //Re-run JS code
127
+ ctfScripts( $ctf );
 
128
 
 
 
 
 
129
  }
130
+ }); // ajax call
131
+ }
132
+
133
+ $('.ctf').each(function(){
134
+
135
+ var $ctf = $(this),
136
+ numNeeded = parseInt($ctf.attr('data-ctfneeded'));
137
+
138
+ //Adds a class if the feed is in a narrow column or on mobile so we can make styling adjustments
139
+ if( $ctf.width() <= 480 ) $ctf.addClass('ctf-narrow');
140
+ if( $ctf.width() <= 320 ) $ctf.addClass('ctf-super-narrow');
141
 
142
+ ctfScripts( $ctf );
 
 
 
 
 
143
 
144
+ if(numNeeded > 0) {
145
+ var $ctfMore = $ctf.find('.ctf-more'),
146
+ lastIDData = $ctf.find('.ctf-item').last().attr('id'),
147
+ shortcodeData = $ctf.attr('data-ctfshortcode');
148
 
149
+ ctfLoadTweets( lastIDData, shortcodeData , $ctf, $ctfMore, numNeeded );
150
+ }
151
+
152
+ // add the load more button and input to simulate a dynamic json file call
153
+ $ctf.find('.ctf-more').on('click', function() {
154
+ // read the json that is in the ctf-shortcode-data that contains all of the shortcode arguments
155
+ var $ctfMore = $(this),
156
+ lastIDData = $ctf.find('.ctf-item').last().attr('id'),
157
+ shortcodeData = $ctf.attr('data-ctfshortcode');
158
+
159
+ ctfLoadTweets( lastIDData, shortcodeData , $ctf, $ctfMore, 0 );
160
+
161
+ });
162
 
163
  }); // end .cff each loop
164
+
165
 
166
  })(jQuery);
167
 
views/admin/support.php CHANGED
@@ -9,7 +9,7 @@
9
 
10
  <textarea readonly="readonly" onclick="this.focus();this.select()" title="To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac)." style="width: 70%; height: 500px; white-space: pre; font-family: Menlo,Monaco,monospace;">
11
  ## SITE/SERVER INFO: ##
12
- Plugin Version: <?php echo CTF_TITLE . ' v' . CTF_VERSION . "\n"; ?>
13
  Site URL: <?php echo site_url() . "\n"; ?>
14
  Home URL: <?php echo home_url() . "\n"; ?>
15
  WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
@@ -35,7 +35,7 @@ foreach ( $plugins as $plugin_path => $plugin ) {
35
 
36
  ## CONFIGURE: ##
37
  <?php
38
- $options = get_option( 'ctf_configure' );
39
  foreach ( $options as $key => $val ) {
40
  $label = $key . ':';
41
  $value = isset( $val ) ? esc_attr( $val ) : 'unset';
@@ -45,7 +45,7 @@ echo str_pad( $label, 24 ) . $value ."\n";
45
 
46
  ## CUSTOMIZE: ##
47
  <?php
48
- $options = get_option( 'ctf_customize' );
49
  foreach ( $options as $key => $val ) {
50
  $label = $key . ':';
51
  $value = isset( $val ) ? esc_attr( $val ) : 'unset';
@@ -55,7 +55,7 @@ echo str_pad( $label, 24 ) . $value ."\n";
55
 
56
  ## STYLE: ##
57
  <?php
58
- $options = get_option( 'ctf_style' );
59
  foreach ( $options as $key => $val ) {
60
  $label = $key . ':';
61
  $value = isset( $val ) ? esc_attr( $val ) : 'unset';
@@ -64,7 +64,7 @@ echo str_pad( $label, 24 ) . $value ."\n";
64
  ?>
65
 
66
  <?php
67
- $config_options = get_option( 'ctf_configure' );
68
  $consumer_key = ! empty( $config_options['consumer_key'] ) && $config_options['have_own_tokens'] ? $config_options['consumer_key'] : 'FPYSYWIdyUIQ76Yz5hdYo5r7y';
69
  $consumer_secret = ! empty( $config_options['consumer_secret'] ) && $config_options['have_own_tokens'] ? $config_options['consumer_secret'] : 'GqPj9BPgJXjRKIGXCULJljocGPC62wN2eeMSnmZpVelWreFk9z';
70
  $request_settings = array(
9
 
10
  <textarea readonly="readonly" onclick="this.focus();this.select()" title="To copy, click the field then press Ctrl + C (PC) or Cmd + C (Mac)." style="width: 70%; height: 500px; white-space: pre; font-family: Menlo,Monaco,monospace;">
11
  ## SITE/SERVER INFO: ##
12
+ Plugin Version: <?php echo CTF_TITLE . ' v' . CTFVER . "\n"; ?>
13
  Site URL: <?php echo site_url() . "\n"; ?>
14
  Home URL: <?php echo home_url() . "\n"; ?>
15
  WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; ?>
35
 
36
  ## CONFIGURE: ##
37
  <?php
38
+ $options = get_option( 'ctf_configure', array() );
39
  foreach ( $options as $key => $val ) {
40
  $label = $key . ':';
41
  $value = isset( $val ) ? esc_attr( $val ) : 'unset';
45
 
46
  ## CUSTOMIZE: ##
47
  <?php
48
+ $options = get_option( 'ctf_customize', array() );
49
  foreach ( $options as $key => $val ) {
50
  $label = $key . ':';
51
  $value = isset( $val ) ? esc_attr( $val ) : 'unset';
55
 
56
  ## STYLE: ##
57
  <?php
58
+ $options = get_option( 'ctf_style', array() );
59
  foreach ( $options as $key => $val ) {
60
  $label = $key . ':';
61
  $value = isset( $val ) ? esc_attr( $val ) : 'unset';
64
  ?>
65
 
66
  <?php
67
+ $config_options = get_option( 'ctf_configure', array() );
68
  $consumer_key = ! empty( $config_options['consumer_key'] ) && $config_options['have_own_tokens'] ? $config_options['consumer_key'] : 'FPYSYWIdyUIQ76Yz5hdYo5r7y';
69
  $consumer_secret = ! empty( $config_options['consumer_secret'] ) && $config_options['have_own_tokens'] ? $config_options['consumer_secret'] : 'GqPj9BPgJXjRKIGXCULJljocGPC62wN2eeMSnmZpVelWreFk9z';
70
  $request_settings = array(