: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
_.each( currentStreamFeeds, function ( feed ) {
// initiate boost for feeds
var $view = feedsView.$popup.find('[data-uid="' + feed.id + '"]');
$view = $( _.template(templates[ feed.type + 'View'])({
feedsView.$el.find( '#feed-views' ).append( $view );
feedsView.setInputsValue( feed.id );
var $channeling = $view.find('input[name="' + feed.id + '-boosted"]');
var allFeeds = feedsModel.get( 'feeds' );
var request = $.Deferred();
requests.push( request );
setTimeout( function () {
allFeeds[ feed.id ]['boosted'] = 'yep';
//allFeeds[ feed.id ]['enabled'] = 'yep';
$channeling.prop('checked', true ).change(); // trigger change
var current = $loaded.data( 'current');
$loaded.html( current + 1 ).data( 'current', current + 1 );
if ( currentStreamFeeds == 0 ) {
$.when.apply( $, requests ).then( function () {
var args = Array.prototype.slice.call( arguments );
console.log( args, requests );
self.model.set( 'cloud', 'yep' );
$inp.prop( 'checked', true );
self.saveViaAjax().done( function () {
self.$el.find( '.dots-loading' ).removeClass( 'dots-loading' )
setTimeout( function () {
self.$el.removeClass( 'toggling-cloud' );
}, function cancel (reason) {
//$t.prop( 'checked', false );
FlowFlow.showNotification( 'Connection with cloud wasn\'t established, please try later or contact us.<i class="flaticon-error"></i>' );
$inp.prop( "checked", false );
} else { // make all feeds regular
var alert = FlowFlow.popup( 'You are about to disable cloud service for this stream, aka removing boosts from all connected feeds. To not overload your server with updating of possibly big amount of feeds they will be disabled, please enable LIVE for each feed individually on FEEDS tab.', 'neutral', false, { right: 'DISABLE CLOUD', left: 'cancel'} )
.then( function yes (value) {
// save cloud prop in stream or do this later?
self.model.set( 'cloud', 'nope' );
$inp.prop( 'checked', false );
_.each( currentStreamFeeds, function ( feed ) {
// initiate boost for feeds
var $view = feedsView.$popup.find('[data-uid="' + feed.id + '"]');
$view = $( _.template(templates[ feed.type + 'View'])({
feedsView.$el.find( '#feed-views' ).append( $view );
feedsView.setInputsValue( feed.id );
var $channeling = $view.find('input[name="' + feed.id + '-boosted"]');
var allFeeds = feedsModel.get( 'feeds' );
setTimeout( function () {
allFeeds[ feed.id ]['boosted'] = 'nope';
$channeling.prop('checked', false ).change(); // trigger change
}, function cancel (reason) {
// $t.prop( 'checked', true );
renderConnectedFeeds: function () {
var feeds = this.model.get('feeds');
var $cont = this.$el.find('.stream-feeds__list');
var feed, name, fullName;
for (var i = 0, len = feeds.length; i < len; i++) {
if (!name && feed.type === "wordpress") {
name = feed['category-name'] || feed['wordpress-type'];
if (feed.type === "rss" ) {
if (feed['channel-name']) name = feed['channel-name'];
} else if (feed.type === "twitter" && feed['timeline-type'] === 'list_timeline') {
name += ' - ' + feed['list-name'];
if (name.length > 13) name = name.substr(0, 13) + '...';
items += '<span data-tooltip="' + capitaliseFirstLetter( feed.type ) + ' - ' + stripslashes( fullName ) + ' - ID: ' + feed.id + '" data-id="' + feed.id +'" class="stream-feeds__item stream-feeds__' + feed.type + (feed.errors && feed.errors.length ? ' stream-feeds__error' : '') + '"><i class="stream-feeds__icon flaticon-' + feed.type + '"></i>' + stripslashes( name ) + '</span>';
$cont.html('').append(items).closest('.stream-feeds').removeClass('stream-feeds--connecting');
connectFeed: function (e) {
var $t = $(e.target).closest('.stream-feeds__btn');
var streamFeeds = this.model.get('feeds');
var allFeeds = feedsModel.get('feeds');
var boostedFeeds = _.filter( streamFeeds , function( feed ){ return feed.boosted == 'yep' });
if ($t.is('.stream-feeds__close')) {
$t.closest('.stream-feeds').removeClass('stream-feeds--connecting')
val = this.$el.find('.stream-feeds select :selected').val();
// if cloud stream and regular feed warn user
if ( false && feed.boosted == 'nope' && boostedFeeds.length == streamFeeds.length ) {
console.log('add regular feed');
promise = FlowFlow.popup( 'You are about to add regular feed to Cloud stream, this will make it Self-Hosted. Are you sure?', 'neutral' );
$t.closest('.stream-feeds').removeClass('stream-feeds--connecting');
// double check it doesn't exist already
if ( !_.find( streamFeeds, function(e){ return e.id === val }) ) {
streamFeeds.push( feed );
FlowFlow.makeOverlayTo( 'show' );
var request = self.model.save();
request.done(function(serverModel){
self.model.trigger('stream-saved');
self.renderConnectedFeeds();
FlowFlow.makeOverlayTo('hide');
displayFeedsSelect: function () {
var connectedFeeds = this.model.get( 'feeds' );
var availableFeeds = _.clone( feedsModel.get( 'feeds' ) );
var isEmpty = _.isEmpty( availableFeeds ), isEmptyAfterFilter;
var connectedFeedsIDs = {};
var isCloudStream = this.model.get( 'cloud' ) == 'yep';
var $select = this.$el.find( '.stream-feeds select' );
_.each( connectedFeeds, function ( el ) { connectedFeedsIDs[ el.id ] = true; } );
// filter connected and boosted / regular type for appropriate stream type
availableFeeds = _.filter( availableFeeds, function ( feed ) {
var isFeedBoosted = feed.boosted == 'yep';
var includeThisFeed = true;
if ( isCloudStream && ! isFeedBoosted ) {
else if ( ! isCloudStream && isFeedBoosted ) {
return !connectedFeedsIDs[ feed.id ] && includeThisFeed;
isEmptyAfterFilter = _.isEmpty( availableFeeds );
if ( isEmpty || isEmptyAfterFilter ) {
// var msg = isEmpty ? 'It seems there are no available feeds for this type of stream. Go to Feeds tab?' : 'You connected all feeds already. Go to Feeds tab?';
var msg ='It seems there are no available feeds for this type of stream. Go to Feeds tab?';
var promise = FlowFlow.popup( msg, 'neutral' );
FlowFlow.$form.find('#sources-tab').click()
for (i = 0, len = availableFeeds.length; i < len; i++) {
feed = availableFeeds[i];
if (!name && feed.type == "wordpress") {
name = capitaliseFirstLetter(feed['category-name'] || 'Posts');
options += '<option value="' + feed.id + '">' + capitaliseFirstLetter(feed.type) + ' - ' + name + ' - ' + feed.id + '</option>';
$select.html('').append(options).closest('.stream-feeds').addClass('stream-feeds--connecting');
$select.chosen("destroy");
detachFeed: function (e) {
var promise = FlowFlow.popup('Disconnect feed from stream?', 'neutral');
var $t = $(e.target).closest('span');
self.model.set('feeds', _.filter(self.model.get('feeds'), function(el){return el.id != id}));
FlowFlow.makeOverlayTo('show');
var request = self.model.save();
request.done(function(serverModel){
self.model.trigger('stream-saved');
FlowFlow.makeOverlayTo('hide');
disableAction: function (e) {
e.stopImmediatePropagation()
setInputsValue: function () {
// console.log('set inputs value');
var id = this.model.get('id');
var attrs = this.model.attributes;
//if (/s.+?\-f/.test(name)) continue;
selector = '[name="stream-' + id + '-' + name + '"]';
$input = this.$el.find( selector );
val = typeof attrs[name] === 'object' ? JSON.stringify( attrs[name] ) : attrs[name];
if ($input.length > 1) { // assume checkbox group
if (typeof optVal === 'object') {
if (!this.disabled) $t.prop('checked', optVal[this.value]);
if (!this.disabled) $t.prop('checked', $t.val() == optVal);
else if ($input.is(':radio') || $input.is(':checkbox')) {
if ( !this.disabled ) $t.prop( 'checked', attrs[name] === 'yep' );
$input.val(val ? stripslashes(val.toString()) : '');
changeDesignMode: function (e) {
var val = e.currentTarget.value;
var $p = $(e.currentTarget).closest('.section');
$p.removeClass(function(index, cls) {
return cls.match(/\w+-layout-chosen/)[0];
}).addClass(val + '-layout-chosen').find('.section-settings').removeClass('settings-section__active').end()
.find('.settings-' + val).addClass('settings-section__active');
FlowFlow.setHeight(self.model.get('id'));
previewChangeAlign: function (e) {
var val = e.target.value;
var $preview = $(e.target).closest('dl').find('.preview .ff-stream-wrapper');
$preview.css('text-align', val);
previewChangeUpic: function (e) {
var val = e.target.value;
this.$preview.removeClass('ff-upic-timestamp ff-upic-centered ff-upic-centered-big ff-upic-off').addClass('ff-upic-' + val);
previewChangeCorners: function (e) {
var val = e.target.value;
this.$preview.removeClass('ff-upic-round ff-upic-square').addClass('ff-upic-' + val);
this.$el.find( '.upic-style-toggle' ).hide();
this.$el.find( '.upic-style-toggle' ).show();
previewChangeIcon: function (e) {
var val = e.target.value;
this.$preview.removeClass('ff-sc-label1 ff-sc-label2 ff-sc-stamp1 ff-sc-off').addClass('ff-sc-' + val);
previewChangeBradius: function (e) {
var val = e.target.value;
this.$preview.find('.picture-item__inner, .ff-img-holder img').css( 'borderRadius', val + 'px' );
previewChangeIconsLook: function (e) {
var val = e.target.value;
this.$preview.removeClass('ff-fill-icon ff-outline-icon').addClass('ff-' + val + '-icon');
previewChangeStyle: function (e) {
var val = e.target.value;
var $preview = $(e.target).closest('dl').find('.preview .ff-stream-wrapper');
var cls = $preview.attr( 'class' );
this.reformat($preview, val);
$preview.removeClass(function() {
return cls.match(/ff-style-[1-9]/)[0];
}).addClass('ff-' + val);
previewChangeTheme: function (e) {
var val = e.target.value;
var $cont = $(e.target).closest('.design-step-2');
$cont.find('.style-choice').hide();
$cont.find('.' + val + '-style').show();
previewChangeWidth: function (e) {
var val = e.target.value;
var $preview = $(e.target).closest('.design-step-2').find('.classic-style .preview, .flat-style .preview');
$preview.find('.ff-item').css('width', val + 'px')
reformat: function ($stream, style) {
$stream.find('.ff-item').each(function(i,el){
var $img = $el.find('.ff-img-holder');
if (/[12]/.test(style)) {
$meta = $el.find('.ff-item-meta');
$el.find('.ff-item-cont').prepend($meta);
if (style === 'style-1') {
$meta.append($meta.find('.ff-userpic'));
$el.addClass('ff-no-image')
} else if (style === 'style-3') {
$el.prepend($el.find('.ff-icon'));
$el.addClass('ff-' + (!$img.length ? 'no-' : '') +'image');
revert: function ($stream) {
$stream.find('.ff-item').each(function(i,el){
//console.log('revert',el)
var $cont = $el.find('.ff-item-cont');
$cont.append($cont.find('h4'));
$cont.append($cont.find('.ff-img-holder'));
$cont.append($cont.find('p'));
$cont.append($cont.find('.ff-item-meta'));
$el.find('.ff-userpic').append($el.find('.ff-icon'))
previewontriggerelement: true,
color: 'rgb(255, 88, 115)',
customswatches: 'card_bg',
onchange: function(container, color) {
var $preview = container.data('preview');