//UTILS START
var ptsUtils = {
  slidesEditWnd: null
  , addMenuItemWnd: null
  , addMenuItemWndBlock: null
  , subSettingsWnd: null
  , subSettingsWndBlock: null
  , subAddFieldWnd: null
  , subAddFieldWndBlock: null
  , iconsLibWnd: null
  , iconsLibWndElement: null
  , badgesLibWnd: null
  , badgesLibWndElement: null
  , colorPicker: null
  , showSlidesEditWnd: function (block) {
    var self = this;
    if (!this.slidesEditWnd) {
      this.slidesEditWnd = jQuery('#ptsManageSlidesWnd').dialog('close');
      this.slidesEditWnd.find('.ptsManageSlidesSaveBtn').click(function () {
        block.beforeSave();
        var listPrev = self.slidesEditWnd.find('.ptsSlidesListPrev')
          , slides = block.getSlides()
          , sliderShell = block.getSliderShell()
          , tmpDiv = jQuery('<div style="display: none;" />').appendTo('body');
        listPrev.find('.ptsSlideManageItem').each(function () {
          var slideId = jQuery(this).data('slide-id');
          slides.each(function () {
            if (jQuery(this).data('slide-id') == slideId) {
              tmpDiv.append(jQuery(this));
              return false;
            }
          });
        });
        sliderShell.html('').append(tmpDiv.find(':data(slide-id)'));
        tmpDiv.remove();
        block.afterSave();
        _ptsSaveCanvas();
        self.slidesEditWnd.dialog('close');
        return false;
      });
      this.slidesEditWnd.find('.ptsSlideManageAddBtn').click(function () {
        // Simulate click on Add slide menu btn
        block._clickMenuItem_add_slide({}, {
          clb: function () {
            self.showSlidesEditWnd(block);
          }
        });
        if (this.slidesEditWnd)
          this.slidesEditWnd.dialog('close');
        return false;
      });
    }
    var listPrev = this.slidesEditWnd.find('.ptsSlidesListPrev');
    listPrev.find('*:not(.ptsSlideManageAddBtn)').remove();
    var slides = block.getSlides();
    if (slides && slides.length) {
      slides.each(function () {
        var newItem = jQuery('#ptsSlideManageItemExl').clone().removeAttr('id');
        newItem.find('img:first').attr('src', jQuery(this).find('.ptsSlideImg').attr('src'));
        newItem.data('slide-id', jQuery(this).data('slide-id'));
        listPrev.prepend(newItem);
        newItem.find('.ptsSlideManageItemRemove').click(function () {
          //if(confirm(toeLangPts('Are you sure want to remove this slide?'))) {
          jQuery(this).parents('.ptsSlideManageItem:first').hide(g_ptsAnimationSpeed, function () {
            jQuery(this).remove();
          });
          //}
          return false;
        });
      });
      listPrev.sortable({
        revert: true
        , items: '.ptsSlideManageItem'
        , placeholder: 'ui-state-highlight'
        //,	axis: 'x'
      });
      listPrev.find('*').disableSelection();
    } else {
      listPrev.prepend('<div>' + toeLangPts('You have no slides for now - try to add them at first.') + '</div>');
    }
    this.slidesEditWnd.dialog('open');
  }
  , _getEllIconsLibHtml: function () {
    return this.iconsLibWnd.find('.ptsIconsLibList .ptsIconLibItem');
  }
  , _showAllIconsLib: function () {
    this._getEllIconsLibHtml().show();
  }
  , initIconsLibWnd: function () {
    var self = this;
    this.iconsLibWnd = jQuery('#ptsIconsLibWnd').dialog({
      resizable: false,
      closeText: "",
      height: "auto",
      width: "90%",
      title: 'ICONS LIBRARY',
      modal: true,
    });
    this.iconsLibWnd.find('.ptsIconsLibSearchTxt').keyup(function () {
      var value = jQuery.trim(jQuery(this).val());
      if (value && value != '') {
        var keys = jQuery(this).val().split(' ')
          , allFoundIcons = self._getEllIconsLibHtml()
          , initialSize = allFoundIcons.length;
        allFoundIcons.show();
        for (var i = 0; i < keys.length; i++) {
          allFoundIcons = allFoundIcons.not('[data-icon*="' + keys[i] + '"]');
        }
        allFoundIcons.hide();
        if (initialSize == allFoundIcons.length) {	// Anything was found
          self._showNothingFoundIconsLib(value);
        }
      } else {
        self._hideNothingFoundIconsLib();
        self._showAllIconsLib();
      }
      return false;
    });
    this.iconsLibWnd.find('.ptsIconsLibSaveBtn').click(function () {
      ptsUtils.iconsLibWnd.dialog('close');
      return false;
    });
    var allIcons = this.getFaIconsList()
      , iconsShell = this.iconsLibWnd.find('.ptsIconsLibList');
    iconsShell.html('');
    for (var i = 0; i < allIcons.length; i++) {
      var iconName = this._faIconClassToName(allIcons[i]);
      iconsShell.append('<div class="ptsIconLibItem supMd3 supSm4" onclick="ptsUtils.selectFaIconFromLib(this); return false;" data-icon="' + allIcons[i] + '" data-name="' + iconName + '">'
        + '<i class="ptsIconLibPrev fa ' + allIcons[i] + '"></i>'
        + '<span class="ptsIconLibTitle">' + iconName + '</span>'
        + '</div>');
    }
  }
  , selectFaIconFromLib: function (clickIcon) {
    if (this.iconsLibWndElement) {
      var prevClass = this.iconsLibWndElement.get('icon')
        , newClass = jQuery(clickIcon).data('icon');
      this.iconsLibWndElement._getEditArea().removeClass(prevClass).addClass(newClass);
      this.iconsLibWndElement.set('icon', newClass);
      _ptsSaveCanvas();
    } else
      console.error('Can not find element for icon apply!!!');
    this.iconsLibWnd.dialog('close');
  }
  , _faIconClassToName: function (str) {
    return str.substr(3);
  }
  , _showNothingFoundIconsLib: function (keys) {
    var msgEl = this.iconsLibWnd.find('.ptsIconsLibEmptySearch');
    if (keys) {
      msgEl.find('.ptsNothingFoundKeys').html(keys);
    }
    msgEl.slideDown(g_ptsAnimationSpeed);
  }
  , _hideNothingFoundIconsLib: function () {
    this.iconsLibWnd.find('.ptsIconsLibEmptySearch').hide();
  }
  , showIconsLibWnd: function (element) {
    if (!this.iconsLibWnd) {
      this.initIconsLibWnd();
    }
    this.iconsLibWndElement = element;
    this._showAllIconsLib();
    this._hideNothingFoundIconsLib();
    this.iconsLibWnd.find('.ptsIconsLibSearchTxt').val('');
    this.iconsLibWnd.dialog('open');
  }
  , converUrl: function (url) {
    if (url.indexOf('http') !== 0) {
      url = 'http://' + url;
    }
    return url;
  }
  , urlToVideoSrc: function (url) {
    var src = '';
    if ((src = url.replace(/.*www\.youtube\.com\/watch\?v\=(.+)/gi, '$1')) !== url) {
      return 'https://www.youtube.com/embed/' + src;
    } else if ((src = url.replace(/.*vimeo\.com.*(\d+)/gi, '$1')) !== url) {
      return 'https://player.vimeo.com/video/' + src + '?badge=0';
    }
    return url;
  }
  , getFaIconsList: function () {
    return ['fa-adjust', 'fa-adn', 'fa-align-center', 'fa-align-justify', 'fa-align-left', 'fa-align-right', 'fa-ambulance', 'fa-anchor', 'fa-android', 'fa-angellist', 'fa-angle-double-down', 'fa-angle-double-left', 'fa-angle-double-right', 'fa-angle-double-up', 'fa-angle-down', 'fa-angle-left', 'fa-angle-right', 'fa-angle-up', 'fa-apple', 'fa-archive', 'fa-area-chart', 'fa-arrow-circle-down', 'fa-arrow-circle-left', 'fa-arrow-circle-o-down', 'fa-arrow-circle-o-left', 'fa-arrow-circle-o-right', 'fa-arrow-circle-o-up', 'fa-arrow-circle-right', 'fa-arrow-circle-up', 'fa-arrow-down', 'fa-arrow-left', 'fa-arrow-right', 'fa-arrow-up', 'fa-arrows', 'fa-arrows-alt', 'fa-arrows-h', 'fa-arrows-v', 'fa-asterisk', 'fa-at', 'fa-automobile(alias)', 'fa-backward', 'fa-ban', 'fa-bank(alias)', 'fa-bar-chart', 'fa-bar-chart-o(alias)', 'fa-barcode', 'fa-bars', 'fa-bed', 'fa-beer', 'fa-behance', 'fa-behance-square', 'fa-bell', 'fa-bell-o', 'fa-bell-slash', 'fa-bell-slash-o', 'fa-bicycle', 'fa-binoculars', 'fa-birthday-cake', 'fa-bitbucket', 'fa-bitbucket-square', 'fa-bitcoin(alias)', 'fa-bold', 'fa-bolt', 'fa-bomb', 'fa-book', 'fa-bookmark', 'fa-bookmark-o', 'fa-briefcase', 'fa-btc', 'fa-bug', 'fa-building', 'fa-building-o', 'fa-bullhorn', 'fa-bullseye', 'fa-bus', 'fa-buysellads', 'fa-cab(alias)', 'fa-calculator', 'fa-calendar', 'fa-calendar-o', 'fa-camera', 'fa-camera-retro', 'fa-car', 'fa-caret-down', 'fa-caret-left', 'fa-caret-right', 'fa-caret-square-o-down', 'fa-caret-square-o-left', 'fa-caret-square-o-right', 'fa-caret-square-o-up', 'fa-caret-up', 'fa-cart-arrow-down', 'fa-cart-plus', 'fa-cc', 'fa-cc-amex', 'fa-cc-discover', 'fa-cc-mastercard', 'fa-cc-paypal', 'fa-cc-stripe', 'fa-cc-visa', 'fa-certificate', 'fa-chain(alias)', 'fa-chain-broken', 'fa-check', 'fa-check-circle', 'fa-check-circle-o', 'fa-check-square', 'fa-check-square-o', 'fa-chevron-circle-down', 'fa-chevron-circle-left', 'fa-chevron-circle-right', 'fa-chevron-circle-up', 'fa-chevron-down', 'fa-chevron-left', 'fa-chevron-right', 'fa-chevron-up', 'fa-child', 'fa-circle', 'fa-circle-o', 'fa-circle-o-notch', 'fa-circle-thin', 'fa-clipboard', 'fa-clock-o', 'fa-close(alias)', 'fa-cloud', 'fa-cloud-download', 'fa-cloud-upload', 'fa-cny(alias)', 'fa-code', 'fa-code-fork', 'fa-codepen', 'fa-coffee', 'fa-cog', 'fa-cogs', 'fa-columns', 'fa-comment', 'fa-comment-o', 'fa-comments', 'fa-comments-o', 'fa-compass', 'fa-compress', 'fa-connectdevelop', 'fa-copy(alias)', 'fa-copyright', 'fa-credit-card', 'fa-crop', 'fa-crosshairs', 'fa-css3', 'fa-cube', 'fa-cubes', 'fa-cut(alias)', 'fa-cutlery', 'fa-dashboard(alias)', 'fa-dashcube', 'fa-database', 'fa-dedent(alias)', 'fa-delicious', 'fa-desktop', 'fa-deviantart', 'fa-diamond', 'fa-digg', 'fa-dollar(alias)', 'fa-dot-circle-o', 'fa-download', 'fa-dribbble', 'fa-dropbox', 'fa-drupal', 'fa-edit(alias)', 'fa-eject', 'fa-ellipsis-h', 'fa-ellipsis-v', 'fa-empire', 'fa-envelope', 'fa-envelope-o', 'fa-envelope-square', 'fa-eraser', 'fa-eur', 'fa-euro(alias)', 'fa-exchange', 'fa-exclamation', 'fa-exclamation-circle', 'fa-exclamation-triangle', 'fa-expand', 'fa-external-link', 'fa-external-link-square', 'fa-eye', 'fa-eye-slash', 'fa-eyedropper', 'fa-facebook', 'fa-facebook-f(alias)', 'fa-facebook-official', 'fa-facebook-square', 'fa-fast-backward', 'fa-fast-forward', 'fa-fax', 'fa-female', 'fa-fighter-jet', 'fa-file', 'fa-file-archive-o', 'fa-file-audio-o', 'fa-file-code-o', 'fa-file-excel-o', 'fa-file-image-o', 'fa-file-movie-o(alias)', 'fa-file-o', 'fa-file-pdf-o', 'fa-file-photo-o(alias)', 'fa-file-picture-o(alias)', 'fa-file-powerpoint-o', 'fa-file-sound-o(alias)', 'fa-file-text', 'fa-file-text-o', 'fa-file-video-o', 'fa-file-word-o', 'fa-file-zip-o(alias)', 'fa-files-o', 'fa-film', 'fa-filter', 'fa-fire', 'fa-fire-extinguisher', 'fa-flag', 'fa-flag-checkered', 'fa-flag-o', 'fa-flash(alias)', 'fa-flask', 'fa-flickr', 'fa-floppy-o', 'fa-folder', 'fa-folder-o', 'fa-folder-open', 'fa-folder-open-o', 'fa-font', 'fa-forumbee', 'fa-forward', 'fa-foursquare', 'fa-frown-o', 'fa-futbol-o', 'fa-gamepad', 'fa-gavel', 'fa-gbp', 'fa-ge(alias)', 'fa-gear(alias)', 'fa-gears(alias)', 'fa-genderless(alias)', 'fa-gift', 'fa-git', 'fa-git-square', 'fa-github', 'fa-github-alt', 'fa-github-square', 'fa-gittip(alias)', 'fa-glass', 'fa-globe', 'fa-google', 'fa-google-plus', 'fa-google-plus-square', 'fa-google-wallet', 'fa-graduation-cap', 'fa-gratipay', 'fa-group(alias)', 'fa-h-square', 'fa-hacker-news', 'fa-hand-o-down', 'fa-hand-o-left', 'fa-hand-o-right', 'fa-hand-o-up', 'fa-hdd-o', 'fa-header', 'fa-headphones', 'fa-heart', 'fa-heart-o', 'fa-heartbeat', 'fa-history', 'fa-home', 'fa-hospital-o', 'fa-hotel(alias)', 'fa-html5', 'fa-ils', 'fa-image(alias)', 'fa-inbox', 'fa-indent', 'fa-info', 'fa-info-circle', 'fa-inr', 'fa-instagram', 'fa-institution(alias)', 'fa-ioxhost', 'fa-italic', 'fa-joomla', 'fa-jpy', 'fa-jsfiddle', 'fa-key', 'fa-keyboard-o', 'fa-krw', 'fa-language', 'fa-laptop', 'fa-lastfm', 'fa-lastfm-square', 'fa-leaf', 'fa-leanpub', 'fa-legal(alias)', 'fa-lemon-o', 'fa-level-down', 'fa-level-up', 'fa-life-bouy(alias)', 'fa-life-buoy(alias)', 'fa-life-ring', 'fa-life-saver(alias)', 'fa-lightbulb-o', 'fa-line-chart', 'fa-link', 'fa-linkedin', 'fa-linkedin-square', 'fa-linux', 'fa-list', 'fa-list-alt', 'fa-list-ol', 'fa-list-ul', 'fa-location-arrow', 'fa-lock', 'fa-long-arrow-down', 'fa-long-arrow-left', 'fa-long-arrow-right', 'fa-long-arrow-up', 'fa-magic', 'fa-magnet', 'fa-mail-forward(alias)', 'fa-mail-reply(alias)', 'fa-mail-reply-all(alias)', 'fa-male', 'fa-map-marker', 'fa-mars', 'fa-mars-double', 'fa-mars-stroke', 'fa-mars-stroke-h', 'fa-mars-stroke-v', 'fa-maxcdn', 'fa-meanpath', 'fa-medium', 'fa-medkit', 'fa-meh-o', 'fa-mercury', 'fa-microphone', 'fa-microphone-slash', 'fa-minus', 'fa-minus-circle', 'fa-minus-square', 'fa-minus-square-o', 'fa-mobile', 'fa-mobile-phone(alias)', 'fa-money', 'fa-moon-o', 'fa-mortar-board(alias)', 'fa-motorcycle', 'fa-music', 'fa-navicon(alias)', 'fa-neuter', 'fa-newspaper-o', 'fa-openid', 'fa-outdent', 'fa-pagelines', 'fa-paint-brush', 'fa-paper-plane', 'fa-paper-plane-o', 'fa-paperclip', 'fa-paragraph', 'fa-paste(alias)', 'fa-pause', 'fa-paw', 'fa-paypal', 'fa-pencil', 'fa-pencil-square', 'fa-pencil-square-o', 'fa-phone', 'fa-phone-square', 'fa-photo(alias)', 'fa-picture-o', 'fa-pie-chart', 'fa-pied-piper', 'fa-pied-piper-alt', 'fa-pinterest', 'fa-pinterest-p', 'fa-pinterest-square', 'fa-plane', 'fa-play', 'fa-play-circle', 'fa-play-circle-o', 'fa-plug', 'fa-plus', 'fa-plus-circle', 'fa-plus-square', 'fa-plus-square-o', 'fa-power-off', 'fa-print', 'fa-puzzle-piece', 'fa-qq', 'fa-qrcode', 'fa-question', 'fa-question-circle', 'fa-quote-left', 'fa-quote-right', 'fa-ra(alias)', 'fa-random', 'fa-rebel', 'fa-recycle', 'fa-reddit', 'fa-reddit-square', 'fa-refresh', 'fa-remove(alias)', 'fa-renren', 'fa-reorder(alias)', 'fa-repeat', 'fa-reply', 'fa-reply-all', 'fa-retweet', 'fa-rmb(alias)', 'fa-road', 'fa-rocket', 'fa-rotate-left(alias)', 'fa-rotate-right(alias)', 'fa-rouble(alias)', 'fa-rss', 'fa-rss-square', 'fa-rub', 'fa-ruble(alias)', 'fa-rupee(alias)', 'fa-save(alias)', 'fa-scissors', 'fa-search', 'fa-search-minus', 'fa-search-plus', 'fa-sellsy', 'fa-send(alias)', 'fa-send-o(alias)', 'fa-server', 'fa-share', 'fa-share-alt', 'fa-share-alt-square', 'fa-share-square', 'fa-share-square-o', 'fa-shekel(alias)', 'fa-sheqel(alias)', 'fa-shield', 'fa-ship', 'fa-shirtsinbulk', 'fa-shopping-cart', 'fa-sign-in', 'fa-sign-out', 'fa-signal', 'fa-simplybuilt', 'fa-sitemap', 'fa-skyatlas', 'fa-skype', 'fa-slack', 'fa-sliders', 'fa-slideshare', 'fa-smile-o', 'fa-soccer-ball-o(alias)', 'fa-sort', 'fa-sort-alpha-asc', 'fa-sort-alpha-desc', 'fa-sort-amount-asc', 'fa-sort-amount-desc', 'fa-sort-asc', 'fa-sort-desc', 'fa-sort-down(alias)', 'fa-sort-numeric-asc', 'fa-sort-numeric-desc', 'fa-sort-up(alias)', 'fa-soundcloud', 'fa-space-shuttle', 'fa-spinner', 'fa-spoon', 'fa-spotify', 'fa-square', 'fa-square-o', 'fa-stack-exchange', 'fa-stack-overflow', 'fa-star', 'fa-star-half', 'fa-star-half-empty(alias)', 'fa-star-half-full(alias)', 'fa-star-half-o', 'fa-star-o', 'fa-steam', 'fa-steam-square', 'fa-step-backward', 'fa-step-forward', 'fa-stethoscope', 'fa-stop', 'fa-street-view', 'fa-strikethrough', 'fa-stumbleupon', 'fa-stumbleupon-circle', 'fa-subscript', 'fa-subway', 'fa-suitcase', 'fa-sun-o', 'fa-superscript', 'fa-support(alias)', 'fa-table', 'fa-tablet', 'fa-tachometer', 'fa-tag', 'fa-tags', 'fa-tasks', 'fa-taxi', 'fa-tencent-weibo', 'fa-terminal', 'fa-text-height', 'fa-text-width', 'fa-th', 'fa-th-large', 'fa-th-list', 'fa-thumb-tack', 'fa-thumbs-down', 'fa-thumbs-o-down', 'fa-thumbs-o-up', 'fa-thumbs-up', 'fa-ticket', 'fa-times', 'fa-times-circle', 'fa-times-circle-o', 'fa-tint', 'fa-toggle-down(alias)', 'fa-toggle-left(alias)', 'fa-toggle-off', 'fa-toggle-on', 'fa-toggle-right(alias)', 'fa-toggle-up(alias)', 'fa-train', 'fa-transgender', 'fa-transgender-alt', 'fa-trash', 'fa-trash-o', 'fa-tree', 'fa-trello', 'fa-trophy', 'fa-truck', 'fa-try', 'fa-tty', 'fa-tumblr', 'fa-tumblr-square', 'fa-turkish-lira(alias)', 'fa-twitch', 'fa-twitter', 'fa-twitter-square', 'fa-umbrella', 'fa-underline', 'fa-undo', 'fa-university', 'fa-unlink(alias)', 'fa-unlock', 'fa-unlock-alt', 'fa-unsorted(alias)', 'fa-upload', 'fa-usd', 'fa-user', 'fa-user-md', 'fa-user-plus', 'fa-user-secret', 'fa-user-times', 'fa-users', 'fa-venus', 'fa-venus-double', 'fa-venus-mars', 'fa-viacoin', 'fa-video-camera', 'fa-vimeo-square', 'fa-vine', 'fa-vk', 'fa-volume-down', 'fa-volume-off', 'fa-volume-up', 'fa-warning(alias)', 'fa-wechat(alias)', 'fa-weibo', 'fa-weixin', 'fa-whatsapp', 'fa-wheelchair', 'fa-wifi', 'fa-windows', 'fa-won(alias)', 'fa-wordpress', 'fa-wrench', 'fa-xing', 'fa-xing-square', 'fa-yahoo', 'fa-yelp', 'fa-yen(alias)', 'fa-youtube', 'fa-youtube-play', 'fa-youtube-square'];
  }
  , extractBootstrapColsClasses: function (element) {
    var currClasses = jQuery.map(jQuery(element).attr('class').split(' '), jQuery.trim)
      , newClasses = [];
    for (var i = 0; i < currClasses.length; i++) {
      if (currClasses[i] == 'col' || currClasses[i].match(/col\-\w{2}\-\d{1,2}/)) {
        newClasses.push(currClasses[i]);
      }
    }
    return newClasses;
  }
  , initBadgesLibWnd: function (tableColumn) {
    var self = this;
    this.badgesLibWnd = jQuery('#ptsBadgesLibWnd').dialog({
      resizable: false,
      closeText: "",
      height: "auto",
      width: "90%",
      title: 'BADGES LIBRARY',
      modal: true,
    });
    this.badgesLibWnd.find('.ptsBadgesLibSaveBtn').click(function () {
      badgeData = self.getBadgesData();
      self.badgesLibWndElement._setBadge(badgeData);
      ptsUtils.badgesLibWnd.dialog('close');
      return false;
    });
    this.badgesLibWnd.find('input[name=badge_name]').change(function () {
      self.updateBadgePrevLib();
    });

    var colorInputs = [
      { key: 'badge_bg_color' }
      , { key: 'badge_txt_color' }
    ]
      , inpSelector
      , oneColorPickerOpt = jQuery.extend(g_ptsVandColorPickerOptions, {
        'altField': null,
        'position': { 'my': 'center top', 'at': 'right bottom', 'of': null },
        'ok': function (event, cpColor) {
          self.updateBadgePrevLib();
        }
      });
    for (var i = 0; i < colorInputs.length; i++) {
      inpSelector = '.ptsColorPickInput[name="' + colorInputs[i].key + '"]';
      var colorInp = this.badgesLibWnd.find(inpSelector);
      oneColorPickerOpt.altField = inpSelector + ' + .ptsColorPickInputTear';
      oneColorPickerOpt.position.of = inpSelector + ' + .ptsColorPickInputTear';
      colorInp.colorpicker(oneColorPickerOpt);
    }
    this.fillInBadgeSettings(tableColumn);
    this.badgesLibWnd.find('.ptsTableBadgePosition').click(function () {
      self.badgesLibWnd.find('.ptsTableBadgePosition').removeClass('active');
      jQuery(this).addClass('active');
      self.badgesLibWnd.find('input[name=badge_pos]').val(jQuery(this).data('pos'));
      self.updateBadgePrevLib();
    });
  }
  , fillInBadgeSettings: function (tableColumn) {
    // init color picker
    var $form = jQuery('#ptsBadgesLibForm'),
      backgroundColor = '#444444',
      foregroundColor = '#ffffff';

    if (tableColumn) {
      var $badge = tableColumn._$.find('.ptsColBadgeContent');
      // badge position
      var pos = tableColumn._$.attr('data-badge-badge_pos');
      if (pos) {
        this.badgesLibWnd.find('input[name=badge_pos]').val(pos);
      } else {
        this.badgesLibWnd.find('input[name=badge_pos]').val('left');
      }
      // badgeName
      if ($badge.length
        && tableColumn._$.attr('data-badge-badge_name')
        && tableColumn._$.attr('data-badge-badge_name') != ''
      ) {
        this.badgesLibWnd.find('input[name=badge_name]').val(tableColumn._$.attr('data-badge-badge_name'));
      } else {
        this.badgesLibWnd.find('input[name=badge_name]').val("SALE!");
      }

      if ($badge.length && $badge.eq(0).visible()) {
        // backgroundColor = $badge.css('background-color');
        // foregroundColor = $badge.css('color');
      }
    }
    // $form.find('input[name="badge_bg_color"]').css('background-color', backgroundColor);
    // $form.find('input[name="badge_txt_color"]').css('background-color', foregroundColor);
    var colorInputs = [
      // 	{key: 'badge_bg_color', def: backgroundColor}
      // ,	{key: 'badge_txt_color', def: foregroundColor}
    ];
    for (var i = 0; i < colorInputs.length; i++) {
      this.badgesLibWnd.find('.ptsColorPickInput[name=' + colorInputs[i].key + ']')
        .colorpicker('setColor', colorInputs[i].def);
    }
  }
  , showBadgesLibWnd: function (element) {
    if (!this.badgesLibWnd) {
      this.initBadgesLibWnd(element);
    } else {
      this.fillInBadgeSettings(element);
    }
    if (this.colorPicker) {
      this.colorPicker.startRender();
    }
    this.badgesLibWndElement = element;
    this.fillInBadgeLibData(this.getBadgesData());
    this.badgesLibWnd.dialog('open');
    var self = this;
    setTimeout(function () {
      self.updateBadgePrevLib();
    }, 500);	// 500 is for transition for popup show
  }
  , fillInBadgeLibData: function (data) {
    if (data.badge_name) {
      this.badgesLibWnd.find('input[name=badge_name]').val(data.badge_name);
    }
    if (data.badge_bg_color) {
      this.badgesLibWnd.find('.ptsColorPickInput[name=badge_bg_color]').colorpicker('setColor', data.badge_bg_color);
    }
    if (data.badge_txt_color) {
      this.badgesLibWnd.find('.ptsColorPickInput[name=badge_txt_color]').colorpicker('setColor', data.badge_txt_color);
    }
    if (data.badge_pos) {
      this.badgesLibWnd.find('.ptsTableBadgePosition[data-pos="' + data.badge_pos + '"]').click();
    }
  }
  , updateBadgePrevLib: function ($badge, data) {
    $badge = $badge ? $badge : jQuery('#ptsTableBadgePrev');
    data = data ? data : this.getBadgesData();
    var $prevContent = $badge.find('.ptsColBadgeContent');
    $badge
      .attr({
        'class': 'ptsColBadge ptsColBadge-' + data.badge_pos
        , 'style': ''
      });

    $prevContent
      .html(data.badge_name)
      .attr({
        'style': ''
      })
      .css({
        // 	'background-color': data.badge_bg_color
        // ,	'color': data.badge_txt_color
        'width': 'auto'
        , 'display': 'inline-block'
      });
    var contW = $prevContent.outerWidth()
      , contH = $prevContent.outerHeight()
      , w = $badge.outerWidth()
      , h = $badge.outerHeight()
      // We need to save as many attributes for frontend as possible - to not allow user theme styles broke our table
      , fontSize = $prevContent.css('font-size')	// TODO: Add possibility to select custom font sizes
      , lineHeight = $prevContent.css('line-height')
      , contAfterStyles = {
        'display': 'block'
        , 'font-size': fontSize
        , 'line-height': lineHeight
      }
      , afterStyles = {}
      , newContentWidth = $prevContent.width();
    switch (data.badge_pos) {
      case 'top':
        contAfterStyles.width = contW;
        break;
      case 'right': case 'left':
        afterStyles[data.badge_pos] = 0;
        afterStyles.top = 0;
        afterStyles.width = contH;
        afterStyles.height = contW;
        contAfterStyles.width = 'auto';
        contAfterStyles.position = 'absolute';
        contAfterStyles.top = contW;
        contAfterStyles[data.badge_pos] = 0;
        break;
      case 'left-top': case 'right-top':
        var posKey = data.badge_pos === 'left-top' ? 'left' : 'right';
        afterStyles[posKey] = 0;
        afterStyles.top = 0;

        contAfterStyles.position = 'absolute';
        var coefOfDisplacement = 50;
        newContentWidth = contW + coefOfDisplacement;
        var d = 5
          , hipoten = (newContentWidth) / 2
          , catet = Math.sqrt((hipoten * hipoten) / 2);
        contAfterStyles.top = catet - Math.sqrt((contH * contH) / 2) - d;
        contAfterStyles[posKey] = -1 * (hipoten - catet) - d;
        $prevContent.width(newContentWidth);
        afterStyles.width = $prevContent.width();
        afterStyles.height = $prevContent.width();
        break;
    }
    $prevContent.css(contAfterStyles);
    $badge.css(afterStyles);
    var baseStyles = $prevContent.attr('style');
    var styleColor = 'color:' + data.badge_txt_color;
    var styleBg = 'background-color:' + data.badge_bg_color;
    var finalStyle = baseStyles + styleColor + ";" + styleBg + ";";
    jQuery($prevContent).attr('style', finalStyle);
  }
  , getBadgesData: function () {
    var data = this.badgesLibWnd.find('#ptsBadgesLibForm').serializeAssoc();
    return data;
  }
};
//UTILS END
//BLOCKS FABRIC
/**
 * Blocks fabric - main object for whole blocks manipulations
 */
ptsBlockFabric.prototype.checkSortStart = function (ui) {
  if (!this._isSorting) {
    this._sortStart(ui);
    this._isSorting = true;
  }
};
ptsBlockFabric.prototype._sortStart = function (ui) {
  if (this._blocks.length) {
    var height = 178
      , margin = 20
      , draggedId = ui.item.attr('id')
      , elementFound = false
      , canvaPaddTop = 0
      , canvaPaddBottom = 0
      , currentScroll = jQuery(document).scrollTop()
      , newDocScroll = currentScroll
      , totalHeight = 0;
    for (var i = 0; i < this._blocks.length; i++) {
      var rawJq = this._blocks[i].getRaw()
        , originalHeight = rawJq.height();
      height = originalHeight * 0.5;
      if (height > 178)
        height = 178;
      rawJq.addClass('ptsInSortProcess')
        .data('original-height', originalHeight)
        .animate({
          'height': height + 'px'
          , 'margin-top': margin + 'px'
        }, this._animationSpeed, function () {
          /*console.time('sortable - refreshPositions');
          jQuery('#ptsCanvas').sortable('refreshPositions');
          console.timeEnd('sortable - refreshPositions');*/
        })
        .find('.ptsBlockContent').zoom(0.5, 'center top');

      if (rawJq.attr('id') == draggedId) {
        elementFound = true;
      }
      var newFullHeight = height + margin;
      elementFound
        ? canvaPaddBottom += originalHeight - newFullHeight
        : canvaPaddTop += originalHeight - newFullHeight;
      if (!draggedId && currentScroll && currentScroll >= totalHeight) {
        newDocScroll -= originalHeight - newFullHeight;
      }
      totalHeight += originalHeight;
    }
    setTimeout(function () {
      jQuery('#ptsCanvas').sortable('refreshPositions');
    }, this._animationSpeed);
    // if(draggedId) {
    // 	jQuery('#ptsCanvas').css({
    // 		'padding-top': canvaPaddTop
    // 	,	'padding-bottom': canvaPaddBottom
    // 	});
    // } else {
    // 	if(currentScroll) {
    // 		if(newDocScroll < 0)
    // 			newDocScroll = 0;
    // 		jQuery(document).scrollTop( newDocScroll );
    // 	}
    // }
  }
};
ptsBlockFabric.prototype.checkSortStop = function (ui) {
  if (this._isSorting) {
    this._sortStop(ui);
    this._isSorting = false;
  }
};
ptsBlockFabric.prototype._sortStop = function (ui) {
  if (this._blocks.length) {
    var height = 178
      , margin = 20
      , draggedId = ui.item.attr('id')
      , newDocScroll = 0
      //,	scrollToIter = 0
      , scrolledBlockPass = false
      , currentScroll = jQuery(document).scrollTop()
      , totalHeight = 0
      , offsetTop = ui.offset.top + ui.placeholder.height();
    for (var i = 0; i < this._blocks.length; i++) {
      var rawJq = this._blocks[i].getRaw()
        , originalHeight = rawJq.data('original-height');
      height = rawJq.height();
      rawJq.removeClass('ptsInSortProcess')
        .animate({
          'height': originalHeight
          , 'margin-top': '0'
        }, this._animationSpeed)
        .find('.ptsBlockContent').zoom(1);

      if (draggedId && !scrolledBlockPass) {
        newDocScroll += originalHeight;
      }
      if (draggedId && rawJq.attr('id') == draggedId) {
        scrolledBlockPass = true;
      }

      if (!draggedId && totalHeight <= offsetTop) {
        newDocScroll += originalHeight;
      }
      totalHeight += height + margin;
    }
    jQuery('#ptsCanvas').css({
      'padding-top': 0
      , 'padding-bottom': 0
    });
    jQuery(document).scrollTop(newDocScroll);
  }
};
ptsBlockFabric.prototype.getDataForSave = function () {
  var res = [];
  if (this._blocks.length) {
    var prevDocScroll = jQuery(document).scrollTop();
    this.updateSortOrder();
    var requiredKeys = ['id', 'params', 'sort_order', 'original_id'];
    for (var i = 0; i < this._blocks.length; i++) {
      var requiredParams = {};
      for (var j = 0; j < requiredKeys.length; j++) {
        requiredParams[requiredKeys[j]] = this._blocks[i].get(requiredKeys[j]);
      }
      this._blocks[i].beforeSave();
      requiredParams.html = this._blocks[i].getHtml();
      requiredParams.css = this._blocks[i].get('css');
      this._blocks[i].afterSave();
      res.push(requiredParams);
    }
    // jQuery(document).scrollTop( prevDocScroll );
  }
  return res;
};
ptsBlockFabric.prototype.updateSortOrder = function () {
  if (this._blocks.length) {
    for (var i = 0; i < this._blocks.length; i++) {
      this._blocks[i].set('sort_order', this._blocks[i].getRaw().index());
    }
  }
};
ptsBlockFabric.prototype.getBlocks = function () {
  return this._blocks;
};
ptsBlockFabric.prototype.removeBlockByIter = function (iter) {
  if (this._blocks.length && this._blocks[iter]) {
    this._blocks.splice(iter, 1);
    if (this._blocks.length) {
      // Update iterators for blocks
      for (var i = 0; i < this._blocks.length; i++) {
        this._blocks[i].setIter(i);
      }
    }
  }
};
ptsBlockFabric.prototype.beforeSave = function () {
  if (this._blocks.length) {
    for (var i = 0; i < this._blocks.length; i++) {
      this._blocks[i].beforeSave();
    }
  }
};
ptsBlockFabric.prototype.afterSave = function () {
  if (this._blocks.length) {
    for (var i = 0; i < this._blocks.length; i++) {
      this._blocks[i].afterSave();
    }
  }
};
//BLOCKS FABRIC END
//EDITOR ELEMENTS
/**
 * Destroy current element
 */
ptsElementBase.prototype.destroy = function (clb) {
  if (this._$) {
    var childElements = this._getChildElements();
    if (childElements) {
      for (var i = 0; i < childElements.length; i++) {
        childElements[i]._remove();
      }
    }
    var self = this;
    this._$.slideUp(this._animationSpeed, function () {
      self._remove();
      if (clb && typeof (clb) === 'function') {
        clb();
      }
      if (g_ptsAllowAddUndo) {
        _ptsSaveCanvas();
      }
    });
  }
};
ptsElementBase.prototype.getMenuShowEvent = function () {
  return this._showMenuEvent;
};
ptsElementBase.prototype._remove = function () {
  if (this._showMenuEvent === 'click') {
    jQuery(document).unbind('click.menu_el_click_hide_' + this.getId());
  }
  this._destroyMenu();
  if (this._$) {
    this._$.remove();
    this._$ = null;
  }
  this._afterDestroy();
  this._block.removeElementByIterNum(this.getIterNum());
};
ptsElementBase.prototype._getChildElements = function () {
  var allFoundHtml = this._$.find('.ptsEl');
  if (allFoundHtml && allFoundHtml.length) {
    var foundElements = []
      , selfBlock = this.getBlock();
    allFoundHtml.each(function () {
      var element = selfBlock.getElementByIterNum(jQuery(this).data('iter-num'));
      if (element) {
        foundElements.push(element);
      }
    });
    return foundElements.length ? foundElements : false;
  }
  return false;
};
ptsElementBase.prototype._afterDestroy = function () {

};
ptsElementBase.prototype.beforeSave = function () {
  this._destroyMoveHandler();
};
ptsElementBase.prototype.afterSave = function () {
  this._initMoveHandler();
};
ptsElementBase.prototype._initMenu = function () {
  if (this._menuOriginalId && this._menuOriginalId != '') {
    this._initMenuClbs();
    var menuParams = {
      changeable: this._changeable,
      showEvent: 'click'
    };
    this._menu = new window[this._menuClass](this._menuOriginalId, this, this._menuClbs, menuParams);
    if (!this._initedComplete) {
      var self = this;
      this._$.click(function (e) {
        e.stopPropagation();
        self.showMenu();
      });
      var startHideTimer = function () {
        jQuery(self._$).data('hide-menu-timeout', setTimeout(function () {
          var scrollY = window.scrollY;
          self.hideMenu();
          window.scrollTo(0, scrollY);
        }, 500));
      };
      this._$.hover(function () {
        clearTimeout(jQuery(self._$).data('hide-menu-timeout'));
      }, function () {
        startHideTimer();
      });
      this._menu.$().hover(function () {
        clearTimeout(jQuery(self._$).data('hide-menu-timeout'));
      }, function () {
        startHideTimer();
      });
      jQuery(document).on('click.menu_el_click_hide_' + this.getId(), function (e) {
        var $target = jQuery(e.target);
        if (self._menu && self._menu.isVisible() && !$target.closest(self._$).length && !$target.closest(self._menu.$()).length) {
          clearTimeout(jQuery(self._$).data('hide-menu-timeout'));
          self.hideMenu();
        }
      });
    }
    if (this._isMovable) {
      this._initMoveHandler();
      this._initMovableMenu();
    }
    this.initPostLinks(this._menu._$);
  } else {
  }
};
ptsElementBase.prototype.initPostLinks = function ($menu) {
  if (!this.includePostLinks) return;

  var $linkTab = $menu.find('.ptsPostLinkList')
    , $field = null
    , fieldSelector = $linkTab.attr('data-postlink-to');

  if (!fieldSelector.length) return;

  if (fieldSelector.indexOf(':parent') == 0) {
    fieldSelector = fieldSelector.substring(7, fieldSelector.length).trim();

    $field = $linkTab.parent().find(fieldSelector);
  } else {
    $field = jQuery(fieldSelector);
  }

  if (!$field.length) return;

  this.showPostsLinks($linkTab);

  $linkTab.css({
    height: 120
  });

  $linkTab.on('click', 'li', function () {
    var $item = jQuery(this)
      , url = $item.attr('data-value');

    if (!url) return;

    $field.val(url);

    $field.change();
  });

  $linkTab.slimScroll({
    height: 120
    , railVisible: true
    , alwaysVisible: true
    , allowPageScroll: true
    , color: '#f72497'
    , opacity: 1
    , distance: 0
    , borderRadius: '3px'
  });

  $linkTab.parent('.slimScrollDiv')
    .addClass('ptsPostLinkRoot')
    .hide();

  var $rootTab = $linkTab.parent('.ptsPostLinkRoot');

  /** Hide and show handlers **/
  var ignoreHide = false
    , isFocus = false;

  $field.on('postlink.hide', function () {
    $rootTab.hide();

    $linkTab.hide();

    $field.trigger('postlink.hide:after');
  });

  $field.focus(function () {
    $field.trigger('postlink.show');

    $rootTab.show();

    $linkTab.show();

    isFocus = true;

    $field.trigger('postlink.show:after');
  });

  $rootTab.hover(function () {
    ignoreHide = true;
  }, function () {
    ignoreHide = false;

    if (!isFocus) {
      $field.trigger('postlink.hide');
    }
  });

  $field.blur(function () {
    isFocus = false;

    if (!ignoreHide) {
      $field.trigger('postlink.hide');
    }
  });
};
ptsElementBase.prototype.escapeString = function (str) {
  return jQuery('<div/>').text(str).html();
}
ptsElementBase.prototype.showPostsLinks = function ($tab) {
  if (!$tab.find('ul').length) {
    $tab.html('<ul></ul>');
  }

  $tab.find('ul').html('');

  for (var i in ptsEditor.posts) {
    $tab.find('ul')
      .append(
        '<li data-value="' + this.escapeString(ptsEditor.posts[i].url) + '">' +
        '<span>' + this.escapeString(ptsEditor.posts[i].title) + '</span>' +
        '</li>'
      );
  }
};
ptsElementBase.prototype._closeMenuOnDocClick = function (e, element) {
  if (!this._menu.isVisible()) return;
  var $target = jQuery(e.target);
  if (!this.$().find($target).length && !this.getMenu().$().find($target).length) {
    this.hideMenu();
  }
};
ptsElementBase.prototype.getMenu = function () {
  return this._menu;
};
ptsElementBase.prototype._initMovableMenu = function () {
  this._menu.setMovable(true);
  this._menu.$().bind('ptsElMenuReposite', function (e, menu, top, left, useAnimation, setActive) {
    var element = menu.getElement()
      , $element = element.$()
      , $menu = menu.$()
      , elWidth = $element.width()
      , menuWidth = $menu.width()
      , menuHeight = $menu.height();
    // var placePos = menu.$().find('.ptsElMenuMoveHandlerPlace').position()
    // ,	moveTop = -1 * menuHeight + placePos.top;
    // if($element.hasClass('hover')) {
    // 	moveTop -= g_ptsHoverMargin;
    // }

    // var elementParams = {
    // 	'top': moveTop
    // ,	'left': ((elWidth - menuWidth) / 2) + placePos.left - 10
    // };
    var elementParams = {
      'top': '0'
      , 'left': '-20px'
      //,	'background-color': '#f1f1f1'
    };

    if (typeof useAnimation != 'undefined' && useAnimation == true) {
      element._moveHandler.animate(elementParams, menu._animationSpeed);
    } else {
      element._moveHandler.css(elementParams);
    }
    if (typeof setActive == 'undefined' || setActive == true) {
      element._moveHandler.addClass('active')
    }
  }).bind('ptsElMenuHide', function (e, menu) {
    var element = menu.getElement();
    if (!element._sortInProgress) {
      element._moveHandler.removeClass('active');
    }
  });
};
ptsElementBase.prototype.onSortStart = function (axis) {
  this._sortInProgress = true;
  this._moveHandler.addClass('sortInProgress');
  if (axis === 'y') {
    this._$.addClass('ptsColSortInProgressY');
  }
  this._menu.hide();
};
ptsElementBase.prototype.onSortStop = function () {
  this._sortInProgress = false;
  this._moveHandler.removeClass('sortInProgress');
  this._$.removeClass('ptsColSortInProgressY');
  this._menu.show();
};
ptsElementBase.prototype._initMenuClbs = function () {
  var self = this;
  this._menuClbs['.ptsRemoveElBtn'] = function () {
    self.destroy();
    setTimeout(function () {
      _ptsAddUndoBuffer(true);
    }, 300);
  };
  if (this._changeable) {
    this._menuClbs['.ptsTypeTxtBtn'] = function () {
      self.getBlock().replaceElement(self, 'txt_item_html', 'txt');
    };
    this._menuClbs['.ptsTypeImgBtn'] = function () {
      self.getBlock().replaceElement(self, 'img_item_html', 'img');
    };
    this._menuClbs['.ptsTypeIconBtn'] = function () {
      self.getBlock().replaceElement(self, 'icon_item_html', 'icon');
    };
    this._menuClbs['.ptsTypeButtonBtn'] = function () {
      self.getBlock().replaceElement(self, 'icon_item_html', 'btn');
    };
  }
};
ptsElementBase.prototype._initMoveHandler = function () {
  if (this._isMovable && !this._moveHandler) {
    var handler = this._$.find('.ptsMoveHandler');
    this._moveHandler = (handler.length) ? handler : jQuery('#ptsMoveHandlerExl').clone().removeAttr('id').appendTo(this._$);
  }
};
ptsElementBase.prototype._destroyMoveHandler = function () {
  if (this._isMovable) {
    this._moveHandler.remove();
    this._moveHandler = null;
  }
};
ptsElementBase.prototype._afterFullContentLoad = function () {
  //sthis.repositeMenu();
};
ptsElementBase.prototype._destroyMenu = function () {
  if (this._menu) {
    this._menu.destroy();
    this._menu = null;
  }
};
ptsElementBase.prototype.showMenu = function () {
  if (this._menu) {
    this._menu.show();
  }
};
ptsElementBase.prototype.hideMenu = function () {
  if (this._menu) {
    this._menu.hide();
  }
};
ptsElementBase.prototype.menuInAnimation = function () {
  if (this._menu) {
    return this._menu.inAnimation();
  }
  return false;
};
ptsElementBase.prototype.setMovable = function (state) {
  this._isMovable = state;
};
ptsElementBase.prototype.repositeMenu = function () {
  if (this._menu) {
    this._menu.reposite();
  }
};
/**
 * Text element
 */
function ptsElement_txt(jqueryHtml, block) {
  this._elId = null;
  this._editorElement = null;
  this._editor = null;
  this.includePostLinks = true;
  this._editorToolbarBtns = [
    ['pts_editattrs'], ['pts_fontselect'], ['pts_fontsizeselect'], ['pts_code', 'bold', 'italic', 'strikethrough'], ['pts_link'], ['pts_tooltip'], ['forecolor']
  ];
  ptsElement_txt.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_txt, ptsElementBase);
ptsElement_txt.prototype._init = function () {
  ptsElement_txt.superclass._init.apply(this, arguments);
  var id = this._$.attr('id'),
    self = this;
  if (!id || id == '') {
    this._$.attr('id', 'ptsTxt_' + mtRand(1, 99999));
  }
  var toolbarBtns = [];
  for (var i = 0; i < this._editorToolbarBtns.length; i++) {
    toolbarBtns.push(typeof (this._editorToolbarBtns[i]) === 'string' ? this._editorToolbarBtns[i] : this._editorToolbarBtns[i].join(' '));
  }
  if (typeof ptsMCEUrl != 'undefined') {
    tinyMCE.baseURL = ptsMCEUrl;
  }
  tinyMCE.suffix = '.min';
  this._editorElement = this._$.tinymce({
    inline: true,
    toolbar: toolbarBtns.join(' |  | '),
    menubar: false,
    autofocus: false,
    plugins: 'pts_editattrs pts_textcolor pts_link pts_fontselect pts_fontsizeselect pts_tooltip pts_code',
    fontsize_formats: '8pt 10pt 12pt 14pt 18pt 24pt 36pt 48pt 64pt 72pt',
    skin: 'octo',
    convert_urls: false,
    link_context_toolbar: true,
    setup: function (ed) {
      this._editor = ed;
      ed.on('keyup', function (e) {
        var $cell = self._$.closest('.ptsCell, .ptsColDesc, .ptsColHeader');
        if ($cell.length) {
          var scrollTop = jQuery(window).scrollTop();
          $cell.css('height', 'auto');
          var newHeight = $cell[0].scrollHeight;
          $cell.css('height', newHeight + 'px');
          jQuery(window).scrollTop(scrollTop);
        }
        var selectionCoords = getSelectionCoords();
        ptsMceMoveToolbar(self._editorElement.tinymce(), selectionCoords.x);
        self.getBlock().hideElementsMenus();
      });
      ed.on('blur', function (e) {
        var currentContent = ed.getContent();
        if (e.target._ptsChanged) {
          e.target._ptsChanged = false;
          var scrollTop = jQuery(window).scrollTop();
          self.getBlock().contentChanged();
          jQuery(window).scrollTop(scrollTop);
          _ptsSaveCanvas();
        }
        jQuery('.mce-container.mce-panel.mce-floatpanel.mce-menu:visible').hide();
      });
      ed.on('click', function (e) {
        ptsMceMoveToolbar(self._editorElement.tinymce(), e.clientX);
        self.getBlock().hideElementsMenus();
        if (ed.theme.panel.hasOwnProperty('isInitPostlinkClick')) return;
        var handler = function () {
          ed.theme.panel.isInitPostlinkClick = true;
          if (!self || !self._$) return;
          var $fieldWp = jQuery('#' + self._$.attr('id') + 'ptsPostLinkList');
          if ($fieldWp.length) {
            ed.theme.panel.off('click', handler);
            self.initPostLinks($fieldWp.parents('.mce-container'));
          }
        };
        ed.theme.panel.on('click', handler);
      });
      if (self._afterEditorInit) {
        self._afterEditorInit(ed);
      }
    }
  });
  this._$.removeClass('mce-edit-focus');
  this._$.bind('dragover drop', function (event) {
    event.preventDefault();
  });
};
ptsElement_txt.prototype.destroy = function (clb) {
  if (this._editor) {
    this._editor.remove();  // Clean up TinyMCE editor
  }
  ptsElement_txt.superclass.destroy.apply(this, arguments);
};
ptsElement_txt.prototype.getEditorElement = function () {
  return this._editorElement;
};
ptsElement_txt.prototype.getEditor = function () {
  return this._editor;
};
ptsElement_txt.prototype.beforeSave = function () {
  ptsElement_txt.superclass.beforeSave.apply(this, arguments);
  if (!this._$) return;	// TODO: Make this work corect - if there are no html (_$) - then this method should not simple triggger. For now - it trigger even if _$ === null
  this._elId = this._$.attr('id');
  this._$
    .removeAttr('id')
    .removeAttr('contenteditable')
    .removeAttr('spellcheck')
    .removeClass('mce-content-body mce-edit-focus');
};
ptsElement_txt.prototype.afterSave = function () {
  ptsElement_txt.superclass.afterSave.apply(this, arguments);
  if (this._elId) {
    this._$
      .attr('id', this._elId)
      .attr('contenteditable', 'true')
      .attr('spellcheck', 'false')
      .addClass('mce-content-body');;
  }
};
/**
 * Image element
 */
function ptsElement_img(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuTableCellImgExl';
  }
  this._menuClass = 'ptsElementMenu_img';
  this.includePostLinks = true;
  ptsElement_img.superclass.constructor.apply(this, arguments);
  var self = this;
  this._getImg().load(function () {
    self._block.contentChanged();
  });
}
extendPts(ptsElement_img, ptsElementBase);
ptsElement_img.prototype._beforeImgChange = function (opts, attach, imgUrl, imgToChange) {

};
ptsElement_img.prototype._afterImgChange = function (opts, attach, imgUrl, imgToChange) {

};
// ptsElement_img.prototype._init: Initialize image-specific behaviors
ptsElement_img.prototype._init = function () {
  ptsElement_img.superclass._init.apply(this, arguments); // Call parent init

  var self = this;
  var img = this._getImg(); // Retrieve the image element

  // Only enable resizable and related features in edit mode (backend)
  if (g_ptsEdit) {
    // Check if jQuery UI resizable is available
    if (!jQuery.fn.resizable) {
      console.warn('jQuery UI Resizable is not loaded. Image resizing will not work.');
      return;
    }

    // Function to apply/resync bindings (called on init and after toggle rebuild)
    function applyBindings() {
      // Get current img (in case HTML was rebuilt)
      img = self._getImg();

      // Clean up old resizable and events first
      if (jQuery(img).hasClass('ui-resizable')) {
        try {
          jQuery(img).resizable('destroy');
        } catch (e) {
          console.warn('Error destroying resizable:', e);
        }
      }
      jQuery(img).removeClass('ui-resizable ui-resizable-active');
      jQuery(img).find('.ui-resizable-handle').remove();
      if (jQuery(img).parent().hasClass('ui-wrapper')) {
        jQuery(img).unwrap();
      }
      jQuery(img).off('dblclick click'); // Remove old event handlers

      // Re-bind double-click to enable resizable
      jQuery(img).on('dblclick', function (e) {
        // Enable resizable
        if (!jQuery(this).hasClass('ui-resizable')) {
          jQuery(this).resizable({
            aspectRatio: true,
            handles: 'se',
            ghost: true,
            minWidth: 20,
            minHeight: 20,
            stop: function (event, ui) {
              self._block._refreshCellsHeight();
              self._block.contentChanged();
              _ptsSaveCanvas();
            }
          });
        }
        jQuery(this).addClass('ui-resizable-active');
        e.stopPropagation();
        e.preventDefault();
      });

      // Prevent single click bubbling
      jQuery(img).on('click', function (e) {
        // e.stopPropagation();
      });

      // Disable on click outside (stateful per element ID)
      jQuery(document).off('click.ptsdblclick_' + self._id).on('click.ptsdblclick_' + self._id, function (e) {
        if (!jQuery(e.target).closest(img).length && jQuery(img).hasClass('ui-resizable-active')) {
          if (jQuery(img).hasClass('ui-resizable')) {
            try {
              jQuery(img).resizable('destroy');
            } catch (e) {
              console.warn('Error destroying resizable:', e);
            }
          }
          jQuery(img).removeClass('ui-resizable-active');
          jQuery(img).find('.ui-resizable-handle').remove();
          if (jQuery(img).parent().hasClass('ui-wrapper')) {
            jQuery(img).unwrap();
          }
          if (self._$.parents('.ptsTog').length) {
            jQuery(document.body).trigger('updateToggleHtml');
          }
        }
      });

      // Reposition menu
      self.repositeMenu();
    }

    // Apply bindings initially
    applyBindings();

    // Re-apply bindings after toggle rebuild (bind to toggle-specific event)
    jQuery(document.body).off('changeToggleReplaceHrefBtn.ptstoggle_' + self._id).on('changeToggleReplaceHrefBtn.ptstoggle_' + self._id, function () {
      setTimeout(function () {
        applyBindings(); // Re-sync after toggle HTML change
        self._block.contentChanged(); // Optional: Trigger content change if needed
      }, 100); // Short delay to ensure DOM update complete
    });

    // // Menu on hover (if not already 'hover')
    // if (self._showMenuEvent !== 'click') {
    //     jQuery(self._$).hover(
    //         function() {
    //             self.showMenu();
    //         },
    //         function() {
    //             setTimeout(function() {
    //                 if (!self.menuInAnimation() && self._menu && !jQuery(self._menu.$()).is(':hover')) {
    //                     self.hideMenu();
    //                 }
    //             }, 1000);
    //         }
    //     );
    //     if (self._menu) {
    //         self._menu.$().hover(
    //             function() {
    //                 clearTimeout(jQuery(self._$).data('hide-menu-timeout'));
    //             },
    //             function() {
    //                 jQuery(self._$).data('hide-menu-timeout', setTimeout(function() {
    //                     self.hideMenu();
    //                 }, 1000));
    //             }
    //         );
    //     }
    // }
  }

  // Handle image load for menu positioning
  img.load(function () {
    self.repositeMenu();
  });

  // Fallback for already loaded images
  if (img[0]) {
    if (img[0].complete) {
      self.repositeMenu();
    }
  }
};

// ptsElement_img.prototype.beforeSave: Clean up resizable before saving
ptsElement_img.prototype.beforeSave = function () {
  ptsElement_img.superclass.beforeSave.apply(this, arguments);
  var img = this._getImg();
  if (jQuery(img).hasClass('ui-resizable')) {
    try {
      jQuery(img).resizable('destroy');
    } catch (e) {
      console.warn('Error destroying resizable in beforeSave:', e);
    }
    jQuery(img).find('.ui-resizable-handle').remove();
    if (jQuery(img).parent().hasClass('ui-wrapper')) {
      jQuery(img).unwrap();
    }
  }
  jQuery(img).removeClass('ui-resizable-active');
};

// Set default showMenuEvent for images to 'hover'
if (typeof ptsElement_img.prototype._showMenuEvent === 'undefined') {
  ptsElement_img.prototype._showMenuEvent = 'click';
}
ptsElement_img.prototype._initMenuClbs = function () {
  ptsElement_img.superclass._initMenuClbs.apply(this, arguments);
  var self = this;
  this._menuClbs['.ptsImgChangeBtn'] = function () {
    self.set('type', 'img');
    self._getImg().show();
    self._getVideoFrame().remove();
    ptsCallWpMedia({
      id: self._$.attr('id')
      , clb: function (opts, attach, imgUrl) {
        var imgToChange = self._getImg();
        self._block.beforeSave();
        self._innerImgsLoaded = 0;
        self._beforeImgChange(opts, attach, imgUrl, imgToChange);
        imgToChange.attr('src', imgUrl);
        self._afterImgChange(opts, attach, imgUrl, imgToChange);
        self._block.afterSave();
        self._block.contentChanged();
        _ptsSaveCanvas();
      }
    });
  };
  this._menuClbs['.ptsImgVideoSetBtn'] = function () {
    self.set('type', 'video');
    self._buildVideo(self._menu.$().find('[name=video_link]').val());
  };
};
ptsElement_img.prototype._buildVideo = function (url) {
  url = url ? jQuery.trim(url) : false;
  if (url) {
    var $editArea = this._getEditArea()
      , $videoFrame = this._getVideoFrame($editArea)
      , $img = this._getImg($editArea)
      , src = ptsUtils.urlToVideoSrc(url);
    $videoFrame.attr({
      'src': src
      , 'width': $img.width()
      , 'height': $img.height()
    }).show();
    $img.hide();
  }
};
ptsElement_img.prototype._getVideoFrame = function (editArea) {
  editArea = editArea ? editArea : this._getEditArea();
  var videoFrame = editArea.find('iframe.ptsVideo');
  if (!videoFrame.length) {
    videoFrame = jQuery('<iframe class="ptsVideo" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen />').appendTo(editArea);
  }
  return videoFrame;
};
ptsElement_img.prototype._getImg = function (editArea) {
  if (!this._$ || !this._$.length) {
    console.warn('ptsElement_img._getImg: Element is not initialized or removed from DOM');
    return jQuery();
  }
  return this._$.find('.ptsElArea img:first');
};
ptsElement_img.prototype._initMenu = function () {
  ptsElement_img.superclass._initMenu.apply(this, arguments);
  var self = this;
  this._menu.$().find('[name=video_link]').change(function () {
    self._buildVideo(jQuery(this).val());
  }).keyup(function (e) {
    if (e.keyCode == 13) {	// Enter
      self._buildVideo(jQuery(this).val());
    }
  });
};
ptsElement_img.prototype._getLink = function () {
  var $link = this._$.find('a.ptsLink');
  return $link.length ? $link : false;
};
ptsElement_img.prototype._setLinkAttr = function (attr, val) {
  switch (attr) {
    case 'href':
      if (val) {
        var $link = this._createLink();
        $link.attr(attr, val);
      } else
        this._removeLink();
      break;
    case 'title':
      var $link = this._createLink();
      $link.attr(attr, val);
      break;
    case 'target':
      var $link = this._createLink();
      val ? $link.attr('target', '_blank') : $link.removeAttr('target');
      break;
  }
};
ptsElement_img.prototype._createLink = function () {
  var $link = this._getLink();
  if (!$link) {
    $link = jQuery('<a class="ptsLink" />').append(this._$.find('img')).appendTo(this._getEditArea());
    $link.click(function (e) {
      e.preventDefault();
    });
  }
  return $link;
};
ptsElement_img.prototype._removeLink = function () {
  var $link = this._getLink();
  if ($link) {
    this._getEditArea().append(this._$.find('img'));
    $link.remove();
  }
};
ptsElement_img.prototype._isRelNofollow = function (nofollow) {
  var $link = this._getLink();

  if (!$link)
    $link = this._createLink();

  if (nofollow)
    $link.attr('rel', 'nofollow');
  else
    $link.removeAttr('rel');
};
/**
 * Gallery image element
 */
function ptsElement_gal_img(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuGalItemExl';
  }
  ptsElement_gal_img.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_gal_img, ptsElement_img);
ptsElement_gal_img.prototype._afterDestroy = function () {
  ptsElement_gal_img.superclass._afterDestroy.apply(this, arguments);
  this._block.recalcRows();
};
ptsElement_gal_img.prototype._afterImgChange = function (opts, attach, imgUrl, imgToChange) {
  ptsElement_gal_img.superclass._afterImgChange.apply(this, arguments);
  imgToChange.attr('data-full-img', attach.url);
  imgToChange.parents('.ptsGalLink:first').attr('href', attach.url);
};
/**
 * Menu item element
 */
function ptsElement_menu_item(jqueryHtml, block) {
  /*if(typeof(this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuGalItemExl';
  }*/
  ptsElement_menu_item.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_menu_item, ptsElement_txt);
ptsElement_menu_item.prototype._afterEditorInit = function (editor) {
  var self = this;
  editor.addButton('tables_remove', {
    title: 'Remove'
    , onclick: function (e) {
      self.destroy();
    }
  });
};
ptsElement_menu_item.prototype._beforeInit = function () {
  this._editorToolbarBtns.push('tables_remove');
};

/**
 * Menu item image
 */
function ptsElement_menu_item_img(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuMenuItemImgExl';
  }
  ptsElement_menu_item_img.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_menu_item_img, ptsElement_img);
/**
 * Input item
 */
function ptsElement_input(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuInputExl';
  }
  ptsElement_input.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_input, ptsElementBase);
ptsElement_input.prototype._init = function () {
  ptsElement_input.superclass._init.apply(this, arguments);
  var saveClb = function (element) {
    jQuery(element).attr('placeholder', jQuery(element).val());
    jQuery(element).val('');
    _ptsSaveCanvasDelay();
  };
  this._getInput().focus(function () {
    jQuery(this).val(jQuery(this).attr('placeholder'));
  }).blur(function () {
    if (jQuery(this).data('saved')) {
      jQuery(this).data('saved', 0);
      return;
    }
    saveClb(this)
  }).keyup(function (e) {
    if (e.keyCode == 13) {	// Enter
      saveClb(this);
      jQuery(this).data('saved', 1).trigger('blur');	// We must blur from element after each save in any case
    }
  });
};
ptsElement_input.prototype._getInput = function () {
  if (!this._$) return;	// TODO: Make this work corect - if there are no html (_$) - then this method should not simple triggger. For now - it trigger even if _$ === null
  // TODO: Modify this to return all fields types
  return this._$.find('input');
};
ptsElement_input.prototype._initMenu = function () {
  ptsElement_input.superclass._initMenu.apply(this, arguments);
  if (!this._$) return;	// TODO: Make this work corect - if there are no html (_$) - then this method should not simple triggger. For now - it trigger even if _$ === null
  var self = this
    , menuReqCheck = this._menu.$().find('[name="input_required"]');
  menuReqCheck.change(function () {
    var required = jQuery(this).attr('checked');
    if (required) {
      self._getInput().attr('required', '1');
    } else {
      self._getInput().removeAttr('required');
    }
    self._block.setFieldRequired(self._getInput().get(0).name, (helperChecked ? 1 : 0));
    _ptsSaveCanvasDelay();
  });
  self._getInput().attr('required')
    ? menuReqCheck.attr('checked', 'checked')
    : menuReqCheck.removeAttr('checked');
};
ptsElement_input.prototype.destroy = function () {
  // Remove field from block fields list at first
  var name = this._getInput().attr('name');
  this._block.removeField(name);
  ptsElement_input.superclass.destroy.apply(this, arguments);
};
/**
 * Input button item
 */
function ptsElement_input_btn(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuInputBtnExl';
  }
  ptsElement_input_btn.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_input_btn, ptsElementBase);
ptsElement_input_btn.prototype._getInput = function () {
  // TODO: Modify this to return all fields types
  return this._$.find('input');
};
ptsElement_input_btn.prototype._init = function () {
  ptsElement_input_btn.superclass._init.apply(this, arguments);
  var saveClb = function (element) {
    jQuery(element).attr('type', 'submit');
    _ptsSaveCanvasDelay();
  };
  this._getInput().click(function () {
    return false;
  }).focus(function () {
    var value = jQuery(this).val();
    jQuery(this).attr('type', 'text').val(value);
  }).blur(function () {
    if (jQuery(this).data('saved')) {
      jQuery(this).data('saved', 0);
      return;
    }
    saveClb(this);
  }).keyup(function (e) {
    if (e.keyCode == 13) {	// Enter
      saveClb(this);
      jQuery(this).data('saved', 1).trigger('blur');	// We must blur from element after each save in any case
    }
  });
};
/**
 * Standart button item
 */
ptsElement_btn.prototype.beforeSave = function () {
  ptsElement_btn.superclass.beforeSave.apply(this, arguments);
  this._getEditArea().removeAttr('contenteditable');
};
ptsElement_btn.prototype.afterSave = function () {
  ptsElement_btn.superclass.afterSave.apply(this, arguments);
  this._getEditArea().attr('contenteditable', true);
};
ptsElement_btn.prototype._init = function () {
  ptsElement_btn.superclass._init.apply(this, arguments);
  var self = this;
  this._getEditArea().attr('contenteditable', true).blur(function () {
    setTimeout(function () {
      self._block.contentChanged();
    }, 2000);
    //_ptsSaveCanvasDelay();
  }).keypress(function (e) {
    if (e.keyCode == 13 && window.getSelection) {	// Enter
      document.execCommand('insertHTML', false, '<br>');
      if (typeof e.preventDefault != "undefined") {
        e.preventDefault();
      } else {
        e.returnValue = false;
      }
    }
  });
  if (this.get('customhover-clb')) {

  }
};
ptsElement_btn.prototype._setColor = function (color) {
  this.set('bgcolor', color);
  var bgElements = this.get('bgcolor-elements');
  if (bgElements)
    bgElements = this._$.find(bgElements);
  else
    bgElements = this._$;
  switch (this.get('bgcolor-to')) {
    case 'border':	// Change only borders color
      bgElements.css({
        'border-color': color
      });
      break;
    case 'txt':
      bgElements.css({
        'color': color
      });
      break;
    case 'bg':
    default:
      bgElements.css({
        'background-color': color
      });
      break;
  }
  if (this._haveAdditionBgEl === null) {
    this._haveAdditionBgEl = this._$.find('.ptsAddBgEl');
    if (!this._haveAdditionBgEl.length) {
      this._haveAdditionBgEl = false;
    }
  }
  if (this._haveAdditionBgEl) {
    this._haveAdditionBgEl.css({
      'background-color': color
    });
  }
  if (this.get('bgcolor-clb')) {
    var clbName = this.get('bgcolor-clb');
    if (typeof (this[clbName]) === 'function') {
      this[clbName](color);
    }
  }
};
/**
 * Icon item
 */
function ptsElement_icon(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuIconExl';
  }
  this._menuClass = 'ptsElementMenu_icon';
  this.includePostLinks = true;
  ptsElement_icon.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_icon, ptsElementBase);
ptsElement_icon.prototype._setColor = function (color) {
  this.set('color', color);
  this._getEditArea().css('color', color);
};
ptsElement_icon.prototype._getLink = function () {
  var $link = this._$.find('a.ptsLink');
  return $link.length ? $link : false;
};
ptsElement_icon.prototype._setLinkAttr = function (attr, val) {
  switch (attr) {
    case 'href':
      if (val) {
        var $link = this._createLink();
        $link.attr(attr, val);
      } else
        this._removeLink();
      break;
    case 'title':
      var $link = this._createLink();
      $link.attr(attr, val);
      break;
    case 'target':
      var $link = this._createLink();
      val ? $link.attr('target', '_blank') : $link.removeAttr('target');
      break;
  }
};
ptsElement_icon.prototype._createLink = function () {
  var $link = this._getLink();
  if (!$link) {
    $link = jQuery('<a class="ptsLink" />').append(this._$.find('.ptsInputShell')).appendTo(this._$);
    $link.click(function (e) {
      e.preventDefault();
    });
  }
  return $link;
};
ptsElement_icon.prototype._removeLink = function () {
  var $link = this._getLink();
  if ($link) {
    this._$.append($link.find('.ptsInputShell'));
    $link.remove();
  }
};
ptsElement_icon.prototype._isRelNofollow = function (nofollow) {
  var $link = this._getLink();

  if (!$link)
    $link = this._createLink();

  if (nofollow)
    $link.attr('rel', 'nofollow');
  else
    $link.removeAttr('rel');
};
/**
 * Table column element
 */
ptsElement_table_col.prototype._setColor = function (color) {
  if (color) {
    this.set('color', color);
  } else {
    color = this.get('color');
  }
  var enbColor = parseInt(this.get('enb-color'))
    , block = this.getBlock()
    , colNum = this._colNum
    , cssTag = 'col color ' + colNum
    , cellColorCss = block.getParam('cell_color_css')
    , useCss = cellColorCss && cellColorCss !== '';
  if (enbColor) {
    if (useCss) {
      block.setTaggedStyle(block.getParam('cell_color_css'), cssTag, { num: colNum, color: color });
    } else {
      var $bgColorTo = this._$.find('[data-bg-to]')
        , firstBgColor = this.get('first-bg-color');
      if (!firstBgColor) {
        this.set('first-bg-color', $bgColorTo.css('background-color'));
      }
      $bgColorTo.css('background-color', color);
    }
  } else {
    if (useCss) {
      block.removeTaggedStyle(cssTag);
    } else {
      var $bgColorTo = this._$.find('[data-bg-to]');
      $bgColorTo.css('background-color', this.get('first-bg-color'));
    }
  }
  //_ptsSaveCanvas();
};
ptsElement_table_col.prototype._setColNum = function (num) {
  this._colNum = num;
};
ptsElement_table_col.prototype._afterDestroy = function () {
  ptsElement_table_col.superclass._afterDestroy.apply(this, arguments);
  this._block.checkColWidthPerc();
};
ptsElement_table_col.prototype._showSelectBadgeWnd = function () {
  this.hideMenu();
  ptsUtils.showBadgesLibWnd(this);
};
ptsElement_table_col.prototype._disableBadge = function () {
  this._getBadgeHtml().hide();
};
ptsElement_table_col.prototype._setBadge = function (data) {
  if (data) {
    for (var key in data) {
      this.set('badge-' + key, data[key]);
    }
  } else {
    data = this._getBadgeData();
  }
  if (!data) return;

  ptsUtils.updateBadgePrevLib(this._getBadgeHtml().show(), data);
  this.set('enb-badge', 1);
  var $enbBadgeCheck = this._menu.$().find('[name=enb_badge_col]');
  $enbBadgeCheck.prop('checked', true);
  $enbBadgeCheck.data('checked', true);
  $enbBadgeCheck.attr('checked', true);
};
ptsElement_table_col.prototype._getBadgeData = function () {
  var keys = ['badge_name', 'badge_bg_color', 'badge_txt_color', 'badge_pos']
    , data = {};
  for (var i = 0; i < keys.length; i++) {
    data[keys[i]] = this.get('badge-' + keys[i]);
    if (!data[keys[i]])
      return false;
  }
  return data;
};
ptsElement_table_col.prototype._getBadgeHtml = function () {
  var $badge = this._$.find('.ptsColBadge');
  if (!$badge.length) {
    $badge = jQuery('<div class="ptsColBadge"><div class="ptsColBadgeContent"></div></div>').appendTo(this._getEditArea());
  }
  return $badge;
};
/**
 * Table description column element
 */
ptsElement_table_col_desc.prototype._initMenu = function () {
  ptsElement_table_col_desc.superclass._initMenu.apply(this, arguments);
  // Column description created from usual table column element, with it's menu.
  // But we can't move or remove (we can hide this from block settings) this type of column, so let's just remove it's move handle from menu.
  var $moveHandle = this._menu.$().find('.ptsElMenuMoveHandlerPlace')
    , $removeBtn = this._menu.$().find('.ptsRemoveElBtn');
  $moveHandle.next('.ptsElMenuBtnDelimiter').remove();
  $moveHandle.remove();
  $removeBtn.prev('.ptsElMenuBtnDelimiter').remove();
  $removeBtn.remove();
  this._menu.$().css('min-width', '130px');
};
/**
 * Table cell element
 */
function ptsElement_table_cell(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuTableCellExl';
  }
  this._menuClass = 'ptsElementMenu_table_cell';
  ptsElement_table_cell.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_table_cell, ptsElementBase);
ptsElement_table_cell.prototype._initMenuClbs = function () {
  ptsElement_table_cell.superclass._initMenuClbs.apply(this, arguments);
  var self = this;
  this._menuClbs['.ptsTypeTxtBtn'] = function () {
    self._replaceElement('txt_cell_item', 'txt');
  };
  this._menuClbs['.ptsTypeImgBtn'] = function () {
    self._replaceElement('img_cell_item', 'img');
  };
  this._menuClbs['.ptsTypeIconBtn'] = function () {
    self._replaceElement('icon_cell_item', 'icon');
  };
  this._menuClbs['.ptsTypeButtonBtn'] = function () {
    self._replaceElement('icon_cell_item', 'btn');
  };

};
// ptsElement_table_cell.prototype._replaceElement = function(toParamCode, type) {
// 	var editArea = this._getEditArea()
// 	,	elementIter = editArea.find('.ptsEl').data('iter-num')
// 	,	block = this.getBlock();
// 	// Destroy current element in cell
// 	block.destroyElementByIterNum( elementIter );
// 	// Add new one
// 	editArea.html( block.getParam( toParamCode ) );
// 	block._initElementsForArea( editArea );
// 	this.set('type', type);
// 	this._menu.$().find('[name=type]').removeAttr('checked').filter('[value='+ type+ ']').attr('checked', 'checked');
// };
ptsElement_table_cell.prototype._replaceElement = function (toParamCode, type) {
  var editArea = this._getEditArea(),
    elementIter = editArea.find('.ptsEl').data('iter-num'),  // Assume this gets the current content's iter-num; adjust if multiple .ptsEl
    block = this.getBlock(),
    self = this;

  // Destroy with callback to wait for animation/removal
  block.destroyElementByIterNum(elementIter, function () {
    // Extra safety: Clear the edit area (handles cases like .ptsTog with multiples)
    editArea.empty();

    // If .ptsTog exists (toggle enabled), recreate it or handle specially; assuming it's recreated in the param HTML
    editArea.html(block.getParam(toParamCode));

    // Re-init elements
    block._initElementsForArea(editArea);

    // Update type and menu
    self.set('type', type);
    self._menu.$().find('[name=type]').removeAttr('checked').filter('[value=' + type + ']').attr('checked', 'checked');

    // If toggle/schedule is enabled, re-apply duplication logic here if needed (e.g., call a toggle init function)
    // Example: if (parseInt(self.get('enb-toggle')) || parseInt(self.get('enb-schedule'))) { self._duplicateForToggle(); }
    // But implement _duplicateForToggle based on your toggle feature.

    // Trigger content change and save
    self.getBlock().contentChanged();
    _ptsSaveCanvas();
  });
};
/**
 * Table Cell Icon element
 */
function ptsElement_table_cell_icon(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuTableCellIconExl';
  }
  this._changeable = true;
  this.includePostLinks = true;
  ptsElement_table_cell_icon.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_table_cell_icon, ptsElement_icon);
/**
 * Table Cell Image element
 */
function ptsElement_table_cell_img(jqueryHtml, block) {
  if (typeof (this._menuOriginalId) === 'undefined') {
    this._menuOriginalId = 'ptsElMenuTableCellImgExl';
  }
  this._changeable = true;
  this.includePostLinks = true;
  ptsElement_table_cell_img.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_table_cell_img, ptsElement_img);
/**
 * Table Cell Image element
 */
function ptsElement_table_cell_txt(jqueryHtml, block) {
  this._typeBtns = {
    pts_el_menu_type_txt: {
      text: toeLangPts('Text')
      , type: 'txt'
      , checked: true
    }
    , pts_el_menu_type_img: {
      text: toeLangPts('Image / Video')
      , type: 'img'
    }
    , pts_el_menu_type_icon: {
      text: toeLangPts('Icon')
      , type: 'icon'
    }
    , pts_el_menu_type_btn: {
      text: toeLangPts('Button')
      , type: 'btn'
    }
  };
  this.includePostLinks = true;
  ptsElement_table_cell_txt.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElement_table_cell_txt, ptsElement_txt);
ptsElement_table_cell_txt.prototype._afterEditorInit = function (editor) {
  var self = this;

  var onclickClb = function () {

    var $btn = jQuery('#' + this._id).find('button:first')
      , $btnsGroupShell = $btn.parents('.mce-container.mce-btn-group:first')
      , $radio = $btn.find('input[type=radio]')
      , type = $radio.val();
    if (type === 'txt') return;

    $btnsGroupShell.find('input[type=radio]').removeAttr('checked');
    $radio.attr('checked')
      ? $radio.removeAttr('checked')
      : $radio.attr('checked', 'checked');
    // And now - let's make element change
    var element = this.settings._ptsElement;

    element.getBlock().replaceElement(element, type + '_item_html', type);
  }, onPostRenderClb = function (type, checked) {

    var $btnShell = jQuery('#' + this._id)
      , $btn = $btnShell.find('button:first')
      , txt = $btn.html()
      , $radioHtml = jQuery('<label><input type="radio" name="type" value="' + type + '" ' + (checked ? 'checked' : '') + ' />' + txt + '</label>');

    $btn.html('').append($radioHtml);
    $radioHtml.find('input').change(jQuery.proxy(onclickClb, this));
  };
  for (var btnKey in this._typeBtns) {
    editor.addButton(btnKey, {
      text: this._typeBtns[btnKey].text
      , _ptsType: this._typeBtns[btnKey].type
      , _ptsChecked: this._typeBtns[btnKey].checked
      , _ptsElement: this
      , classes: 'btn'
      , onclick: function () {	// see onPostRenderClb() - $radioHtml.find('input').change()
        jQuery.proxy(onclickClb, this)();
      }
      , onpostrender: function (e) {
        jQuery.proxy(onPostRenderClb, this)(this.settings._ptsType, this.settings._ptsChecked);
      }
    });
  }

  editor.addButton('remove', {
    _ptsElement: this
    , icon: 'remove fa fa-trash-o'
    , classes: 'btn'
    , onclick: function () {
      self.destroy();
    }
  });
};
ptsElement_table_cell_txt.prototype._beforeInit = function () {
  var btnsPack = [];
  for (var btnKey in this._typeBtns) {
    btnsPack.push(btnKey);
  }
  btnsPack.push('remove');
  this._editorToolbarBtns.push(btnsPack);
};
//EDITOR ELEMENTS END
//EDITOR ELEMENTS MENU START
function ptsElementMenu(menuOriginalId, element, btnsClb, params) {
  params = params || {};
  this._$ = null;
  this._animationSpeed = g_ptsAnimationSpeed;
  this._menuOriginalId = menuOriginalId;
  this._element = element;
  this._btnsClb = btnsClb;
  this._visible = false;
  this._isMovable = false;
  this._changeable = params.changeable ? params.changeable : false;
  this._inAnimation = false;
  this._id = 'ptsElMenu_' + mtRand(1, 99999);
  this._showEvent = params.showEvent ? params.showEvent : 'click';
  this.init();
}
ptsElementMenu.prototype.getId = function () {
  return this._id;
};
ptsElementMenu.prototype.setMovable = function (state) {
  this._isMovable = state;
};
ptsElementMenu.prototype.setChangeable = function (state) {
  this._changeable = state;
};
ptsElementMenu.prototype._afterAppendToElement = function () {
  if (this._changeable) {
    /** this._updateType(); **/
  }
};
ptsElementMenu.prototype._updateType = function (refreshCheck) {
  if (this._changeable) {
    var type = this._element.get('type');

    this._$
      .find('[name=type]').removeAttr('checked')
      .filter('[value=' + type + ']').attr('checked', 'checked');
  }
};
ptsElementMenu.prototype.$ = function () {
  return this._$;
};
ptsElementMenu.prototype.init = function () {
  var self = this
    , $original = jQuery('#' + this._menuOriginalId);
  this._$ = $original
    .clone()
    .attr('id', this._id)
    .appendTo('body');
  this._afterAppendToElement();

  this._fixClickOnRadio();
  this.reposite();
  this._initAddHtmlAttributes();

  if (this._btnsClb) {
    for (var selector in this._btnsClb) {
      if (this._$.find(selector).length) {
        this._$.find(selector).click(function () {
          self._btnsClb[jQuery(this).data('click-clb-selector')]();
          return false;
        }).data('click-clb-selector', selector);
      }
    }
  }

  this._initSubMenus();
};
ptsElementMenu.prototype._initAddHtmlAttributes = function () {
  var attrs = new ptsChangeElAttrs(this);
};
ptsElementMenu.prototype._fixClickOnRadio = function () {
  this._$.find('.ptsElMenuBtn').each(function () {
    if (jQuery(this).find('[type=radio]').length) {
      jQuery(this).find('[type=radio]').click(function () {
        jQuery(this).parents('.ptsElMenuBtn:first').click();
      });
    }
  });
};

ptsElementMenu.prototype._hideSubMenus = function () {
  if (!this._$) return;

  var menuAtBottom = this._$.hasClass('ptsElMenuBottom'),
    menuOpenBottom = this._$.hasClass('ptsMenuOpenBottom'),
    self = this;

  this._inAnimation = true;

  this._$.find('.ptsElMenuSubPanel[data-sub-panel]:visible').each(function () {
    jQuery(this).slideUp(self._animationSpeed);
  });

  this._$.removeClass('ptsMenuSubOpened');

  if (!menuAtBottom && !menuOpenBottom && typeof self._originalTop !== 'undefined') {
    this._$.data('animation-in-process', 1).animate({
      'top': self._originalTop
    }, this._animationSpeed, function () {
      if (self._$) {
        self._$.data('animation-in-process', 0);
        self._inAnimation = false;
        delete self._originalTop;
        if (self._isMovable) {
          self._$.trigger('ptsElMenuReposite', [self, null, null, null, false]);
        }
      }
    });
  } else if (menuOpenBottom) {
    this._$.removeClass('ptsMenuOpenBottom');
  }
};

ptsElementMenu.prototype._initSubMenus = function () {
  var self = this;

  if (this._$.find('.ptsElMenuBtn[data-sub-panel-show]').length) {
    this._$.find('.ptsElMenuBtn').click(function () {
      self._hideSubMenus();
    });

    this._$.find('.ptsElMenuBtn[data-sub-panel-show]').click(function () {
      var subPanelShow = jQuery(this).data('sub-panel-show'),
        subPanel = self._$.find('.ptsElMenuSubPanel[data-sub-panel="' + subPanelShow + '"]'),
        menuPos = self._$.position(),
        menuAtBottom = self._$.hasClass('ptsElMenuBottom'),
        menuTop = menuPos.top;

      if (!subPanel.is(':visible')) {
        self._inAnimation = true;
        subPanel.slideDown(self._animationSpeed, function () {
          if (!menuAtBottom) {
            var subPanelHeight = subPanel.outerHeight();

            if (menuTop - subPanelHeight < g_ptsTopBarH) {
              self._$.addClass('ptsMenuOpenBottom');
              self._inAnimation = false;
            } else {
              if (typeof self._originalTop === 'undefined') {
                self._originalTop = parseInt(self._$[0].style.top || self._$.css('top')) || 0;
              }

              self._$.animate({
                'top': menuTop - subPanelHeight
              }, self._animationSpeed, function () {
                self._inAnimation = false;
              });
            }
          }
        });

        if (self._element._$.find('a[rel="nofollow"]').length && self._$.find('input[name$="link_rel_nofollow"]').length) {
          self._$.find('input[name$="link_rel_nofollow"]').prop('checked', true);
        }

        self._$.addClass('ptsMenuSubOpened');
      }

      return false;
    });
  }
};

ptsElementMenu.prototype.reposite = function () {
  var elOffset = this._element.$().offset()
    , elWidth = this._element.$().width()
    //,	elHeight = this._element.$().height()
    , width = this._$.width()
    , height = this._$.height()
    , left = elOffset.left - (width - elWidth) / 2
    , top = elOffset.top - height;
  if (this._element.$().hasClass('hover')) {
    top -= g_ptsHoverMargin;
  }
  if (left < 0)
    left = 0;
  this._$.css({
    'left': (left) + 'px'
    , 'top': (top) + 'px'
  });
  var elementOffset = this._element.$().offset();
  this._menuOnBottom = elementOffset.top <= g_ptsTopBarH || this._element.$().data('menu-to-bottom');
  if (this._menuOnBottom) {
    this._$.addClass('ptsElMenuBottom');
  }
  if (this._isMovable) {
    this._$.trigger('ptsElMenuReposite', [this, top, left]);
  }
};
ptsElementMenu.prototype.destroy = function () {
  if (this._$) {
    this._$.remove();
    this._$ = null;
  }
};
ptsElementMenu.prototype.getShowEvent = function () {
  return this._showEvent;
};
ptsElementMenu.prototype.show = function () {
  if (!this._$) return;	// If menu was already destroyed, with destroy element for example
  if (!this._visible && !_ptsSortInProgress()) {
    // Let's hide all other element menus in current block before show this one
    this.getElement().getBlock().hideElementsMenus(this._showEvent);
    this.reposite();
    // And now - show current menu
    this._$.addClass('active');
    this._visible = true;
  }
};
ptsElementMenu.prototype.inAnimation = function () {
  return this._inAnimation;
};
ptsElementMenu.prototype.hide = function () {
  if (!this._$) return;	// If menu was already destroyed, with destroy element for example
  if (this._visible) {
    this._hideSubMenus();
    this._$.removeClass('active');
    this._visible = false;
    if (this._isMovable) {
      this._$.trigger('ptsElMenuHide', this);
    }
    _ptsAddUndoBuffer();
  }
};
ptsElementMenu.prototype.getElement = function () {
  return this._element;
};
ptsElementMenu.prototype._initColorpicker = function (params) {
  params = params || {};
  var self = this
    , color = params.color ? params.color : this._element.get('color')
    , $cpTear = jQuery("#" + self._$.attr('id') + ' .ptsColorPickInputTear')
    , $spanColorPick = jQuery("#" + self._$.attr('id') + ' .ptsInlineColorPicker')
    , oneColorPickerOpt = jQuery.extend(g_ptsVandColorPickerOptions, {
      'inline': true
      , 'altField': $cpTear
      , 'color': color
      , 'select': function (event, cpColor) {
        self._element._setColor(cpColor.formatted);
      }
    });
  $spanColorPick.colorpicker(oneColorPickerOpt);
};
ptsElementMenu.prototype.isVisible = function () {
  return this._visible;
};
function ptsElementMenu_btn(menuOriginalId, element, btnsClb) {
  ptsElementMenu_btn.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElementMenu_btn, ptsElementMenu);
ptsElementMenu_btn.prototype._afterAppendToElement = function () {
  ptsElementMenu_btn.superclass._afterAppendToElement.apply(this, arguments);

  this.$().find('.ptsPostLinkDisabled')
    .removeClass('ptsPostLinkDisabled')
    .addClass('ptsPostLinkList');

  // Link settings
  var self = this
    , $btnLink = this._element._getEditArea()
    , $linkInp = this._$.find('[name=btn_item_link]')
    , $titleInp = this._$.find('[name=btn_item_title]')
    , $newWndInp = this._$.find('[name=btn_item_link_new_wnd]')
    , $relNofollow = this._$.find('[name=btn_item_link_rel_nofollow]');

  $linkInp.val($btnLink.attr('href'));

  $linkInp.change(function () {
    $btnLink.attr('href', jQuery(this).val());
    $(document.body).trigger('updateToggleHtml');
  });

  //after change toggle replace href value in sub menu
  jQuery(document.body).on('changeToggleReplaceHrefBtn', function () {
    $linkInp.val($btnLink.attr('href'));
  });

  $titleInp.val($btnLink.attr('title'));
  $titleInp.change(function () {
    $btnLink.attr('title', jQuery(this).val());
  });
  $btnLink.attr('target') == '_blank' ? $newWndInp.attr('checked', 'checked') : $newWndInp.removeAttr('checked');
  $newWndInp.change(function () {
    jQuery(this).prop('checked') ? $btnLink.attr('target', '_blank') : $btnLink.removeAttr('target');
  });
  $relNofollow.change(function () {
    jQuery(this).prop('checked') ? $btnLink.attr('rel', 'nofollow') : $btnLink.removeAttr('rel');
  });
  // Color settings
  this._initColorpicker({
    color: this._element.get('bgcolor')
  });

  // Tooltip settings
  var $tooltipInp = this._$.find('[name=btn_item_tooltip]'),
    $divElem = this._element._getEditArea().closest('div.ptsCell, div.ptsColFooter, div.ptsColDesc, div.ptsColHeader');

  $tooltipInp.val($divElem.attr('title'));
  $tooltipInp.change(function () {
    $divElem.attr('title', jQuery(this).val());
  });
};
function ptsElementMenu_icon(menuOriginalId, element, btnsClb) {
  ptsElementMenu_icon.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElementMenu_icon, ptsElementMenu);
ptsElementMenu_icon.prototype._afterAppendToElement = function () {
  ptsElementMenu_icon.superclass._afterAppendToElement.apply(this, arguments);

  this.$().find('.ptsPostLinkDisabled')
    .removeClass('ptsPostLinkDisabled')
    .addClass('ptsPostLinkList');

  var self = this
    , iconSizeID = ['fa-lg', 'fa-2x', 'fa-3x', 'fa-4x', 'fa-5x']
    , iconSize = {
      'fa-lg': '1.33333333em'
      , 'fa-2x': '2em'
      , 'fa-3x': '3em'
      , 'fa-4x': '4em'
      , 'fa-5x': '5em'
    }
    , $icon = this._element._$.find('.fa');

  if ($icon.length) {
    var iconClasses = $icon.attr("class").split(' ').reverse()
      , currentIconSize = undefined;

    for (var i in iconClasses) {
      if (iconSizeID.indexOf(iconClasses[i]) != -1) {
        currentIconSize = iconClasses[i];
        break;
      }
    }

    if (currentIconSize)
      this._$.find('[data-size="' + currentIconSize + '"]').addClass('active');
  }

  this._$.on('click', '[data-size]', function () {
    var classSize = jQuery(this).attr('data-size')
      , $icon = self._element._$.find('.fa');

    if (!$icon.length || !classSize) return;

    $icon.removeClass(iconSizeID.join(' '));
    $icon.addClass(classSize);
    $icon.css('font-size', iconSize[classSize]);
    self._$.find('[data-size].active').removeClass('active');
    self._$.find('[data-size="' + classSize + '"]').addClass('active');
    self._element._block._refreshCellsHeight();
  });

  var btnLink = this._element._getLink()
    , linkInp = this._$.find('[name=icon_item_link]')
    , titleInp = this._$.find('[name=icon_item_title]')
    , newWndInp = this._$.find('[name=icon_item_link_new_wnd]')
    , relNofollow = this._$.find('[name=icon_item_link_rel_nofollow]');

  if (btnLink) {
    linkInp.val(btnLink.attr('href'));
    titleInp.val(btnLink.attr('title'));
    btnLink.attr('target') == '_blank' ? newWndInp.attr('checked', 'checked') : newWndInp.removeAttr('checked');
    btnLink.click(function (e) {
      e.preventDefault();
    });
  }
  relNofollow.change(function () {
    self._element._isRelNofollow(jQuery(this).prop('checked') ? true : false);
  });
  linkInp.change(function () {
    self._element._setLinkAttr('href', jQuery(this).val());
  });
  titleInp.change(function () {
    self._element._setLinkAttr('title', jQuery(this).val());
  });
  newWndInp.change(function () {
    self._element._setLinkAttr('target', jQuery(this).prop('checked') ? true : false);
  });
  // Open links library
  this._$.find('.ptsIconLibBtn').click(function () {
    ptsUtils.showIconsLibWnd(self._element);
    return false;
  });
  // Color settings
  this._initColorpicker();

  // Tooltip settings
  var $tooltipInp = this._$.find('[name=icon_item_tooltip]'),
    $divElem = this._element._getEditArea().closest('div.ptsCell, div.ptsColFooter, div.ptsColDesc, div.ptsColHeader');

  $tooltipInp.val($divElem.attr('title'));
  $tooltipInp.change(function () {
    $divElem.attr('title', jQuery(this).val());
  });
};
function ptsElementMenu_img(menuOriginalId, element, btnsClb) {
  ptsElementMenu_img.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElementMenu_img, ptsElementMenu);
ptsElementMenu_img.prototype._afterAppendToElement = function () {
  ptsElementMenu_img.superclass._afterAppendToElement.apply(this, arguments);

  this.$().find('.ptsPostLinkDisabled')
    .removeClass('ptsPostLinkDisabled')
    .addClass('ptsPostLinkList');

  this.getElement().get('type') === 'video'
    ? this.$().find('[name=type][value=video]').attr('checked', 'checked')
    : this.$().find('[name=type][value=img]').attr('checked', 'checked');

  var self = this;
  var btnLink = this._element._getLink()
    , linkInp = this._$.find('[name=image_item_link]')
    , titleInp = this._$.find('[name=image_item_title]')
    , newWndInp = this._$.find('[name=image_item_link_new_wnd]')
    , relNofollow = this._$.find('[name=image_item_link_rel_nofollow]');

  if (btnLink) {
    linkInp.val(btnLink.attr('href'));
    titleInp.val(btnLink.attr('title'));
    btnLink.attr('target') == '_blank' ? newWndInp.attr('checked', 'checked') : newWndInp.removeAttr('checked');
    btnLink.click(function (e) {
      e.preventDefault();
    });
  }

  relNofollow.change(function () {
    self._element._isRelNofollow(jQuery(this).prop('checked') ? true : false);
  });

  linkInp.change(function () {
    self._element._setLinkAttr('href', jQuery(this).val());
  });

  titleInp.change(function () {
    self._element._setLinkAttr('title', jQuery(this).val());
  });

  newWndInp.change(function () {
    self._element._setLinkAttr('target', jQuery(this).prop('checked') ? true : false);
  });

  // Tooltip settings
  var $tooltipInp = this._$.find('[name=image_item_tooltip]'),
    $divElem = this._element._getEditArea().closest('div.ptsCell, div.ptsColFooter, div.ptsColDesc, div.ptsColHeader');

  $tooltipInp.val($divElem.attr('title'));
  $tooltipInp.change(function () {
    $divElem.attr('title', jQuery(this).val());
  });
};
function ptsElementMenu_table_cell(menuOriginalId, element, btnsClb) {
  ptsElementMenu_table_cell.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElementMenu_table_cell, ptsElementMenu);
ptsElementMenu_table_cell.prototype._afterAppendToElement = function () {
  ptsElementMenu_table_cell.superclass._afterAppendToElement.apply(this, arguments);
  var type = this.getElement().get('type');
  if (!type)
    type = 'txt';
  this._$.find('[name=type][value=' + type + ']').attr('checked', 'checked');
};
/**
 * Table col menu
 */
function ptsElementMenu_table_col(menuOriginalId, element, btnsClb) {
  ptsElementMenu_table_col.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElementMenu_table_col, ptsElementMenu);
ptsElementMenu_table_col.prototype._afterAppendToElement = function () {
  ptsElementMenu_table_col.superclass._afterAppendToElement.apply(this, arguments);
  var self = this;
  // Enb/Dslb fill color
  var $enbFillColorCheck = this._$.find('[name=enb_fill_color]');
  $enbFillColorCheck.change(function () {
    self.getElement().set('enb-color', jQuery(this).prop('checked') ? 1 : 0);
    self.getElement()._setColor();	// Just update it from existing color
    return false;
  });
  //console.log(this.getElement());
  parseInt(this.getElement().get('enb-color'))
    ? $enbFillColorCheck.attr('checked', 'checked')
    : $enbFillColorCheck.removeAttr('checked');
  // Color settings
  this._initColorpicker();
  // Enb/Dslb badge
  var $enbBadgeCheck = this._$.find('[name=enb_badge_col]');
  $enbBadgeCheck.change(function () {
    //self.getElement().set('enb-badge', jQuery(this).attr('checked') ? 1 : 0);
    if (jQuery(this).prop('checked')) {
      self.getElement()._setBadge();	// Just update it from existing badge data
      self.getElement()._showSelectBadgeWnd();
    } else {
      self.getElement()._disableBadge();
    }
    return false;
  });
  parseInt(this.getElement().get('enb-badge'))
    ? $enbBadgeCheck.attr('checked', 'checked')
    : $enbBadgeCheck.removeAttr('checked');
  // Badge click
  this._btnsClb['.ptsColBadgeBtn'] = function () {
    $enbBadgeCheck.trigger('click');
    //self.getElement()._showSelectBadgeWnd();
  };
  if (PTS_DATA.isPro) {
    if (typeof (ptsMenuColSchedule) !== 'undefined') {
      this._scheduler = new ptsMenuColSchedule(this.$(), this.getElement());
    }
  } else {
    this._btnsClb['.ptsScheduleColBtn'] = function () {
      // TODO: Show here some PRO promo
    };
  }

};
function ptsElementMenu_table_cell_icon(menuOriginalId, element, btnsClb) {
  ptsElementMenu_table_cell_icon.superclass.constructor.apply(this, arguments);
}
extendPts(ptsElementMenu_table_cell_icon, ptsElementMenu_icon);
// EDITOR ELEMENTS MENU END
// EDITOR BLOCKS START
/**
 * Base block object - for extending
 * @param {object} blockData all block data from database (block database row)
 */
ptsBlockBase.prototype.destroy = function () {
  this._clearElements();
  this._$.slideUp(this._animationSpeed, jQuery.proxy(function () {
    this._$.remove();
    g_ptsBlockFabric.removeBlockByIter(this.getIter());
    if (g_ptsAllowAddUndo) {
      _ptsSaveCanvas();
    }
  }, this));
};
ptsBlockBase.prototype.build = function (params) {
  params = params || {};
  var innerHtmlContent = '';
  if (this._data.css && this._data.css != '') {
    innerHtmlContent += '<style type="text/css" class="ptsBlockStyle">' + this._data.css + '</style>';
  }
  if (this._data.html && this._data.html != '') {
    innerHtmlContent += '<div class="ptsBlockContent">' + this._data.html + '</div>';
  }
  innerHtmlContent = '<div class="ptsBlock" id="{{block.view_id}}">' + innerHtmlContent + '</div>';
  if (!this._data.session_id) {
    this._data.session_id = mtRand(1, 999999);
  }
  if (!this._data.view_id) {
    this._data.view_id = 'ptsBlock_' + this._data.session_id;
  }
  var template = twig({
    data: innerHtmlContent
  });
  var generatedHtml = template.render({
    block: this._data
  });
  this._$ = jQuery(generatedHtml);
  if (params.insertAfter) {
    this._$.insertAfter(params.insertAfter);
  }
  this._initElements();
  this._initHtml();
};
ptsBlockBase.prototype.set = function (key, value) {
  this._data[key] = value;
};
ptsBlockBase.prototype.setData = function (data) {
  this._data = data;
};
ptsBlockBase.prototype.getData = function () {
  return this._data;
};
ptsBlockBase.prototype.appendToCanvas = function () {
  this._$.appendTo('#ptsCanvas');
};
ptsBlockBase.prototype._initHtml = function () {
  this._beforeInitHtml();
};
ptsBlockBase.prototype._beforeInitHtml = function () {

};
ptsBlockBase.prototype._rebuildCss = function () {
  var template = twig({
    data: this._data.css
  });
  var generatedHtml = template.render({
    table: this._data
  });
  this.getStyle().html(generatedHtml);
};
ptsBlockBase.prototype._rebuildHtml = function () {
  var template = twig({
    data: this._data.html
  });
  var generatedHtml = template.render({
    table: this._data
  });
  this.getHtmlBlock().html(generatedHtml);
};
ptsBlockBase.prototype.getStyle = function () {
  return this._$.find('style.ptsBlockStyle');
};
ptsBlockBase.prototype.getHtmlBlock = function () {
  return this._$.find('div.ptsBlockContent');
};
ptsBlockBase.prototype.setTaggedStyle = function (style, tag, elData) {
  this.removeTaggedStyle(tag);
  var $style = this.getStyle()
    , styleHtml = $style.html()
    , tags = this._getTaggedStyleStartEnd(tag);

  var template = twig({
    data: style
  });
  var generatedStyle = template.render({
    el: elData
    , table: this._data
  }), fullGeneratedStyleTag = tags.start + "\n" + generatedStyle + "\n" + tags.end;
  if (generatedStyle == undefined || !generatedStyle) return;
  $style.html(styleHtml + fullGeneratedStyleTag);
  this.set('css', this.get('css') + this._revertReplaceContent(fullGeneratedStyleTag));
};
ptsBlockBase.prototype.removeTaggedStyle = function (tag, params) {
  params = params || {};
  var tags = this._getTaggedStyleStartEnd(tag, true)
    , $style = params.$style ? params.$style : this.getStyle()
    , styleHtml = params.styleHtml ? params.styleHtml : $style.html()
    , replaceRegExp = new RegExp(tags.start + '(.|[\n\r])+' + tags.end, 'gmi');
  $style.html(styleHtml.replace(replaceRegExp, ''));
  this.set('css', this.get('css').replace(replaceRegExp, ''));
};
ptsBlockBase.prototype.getTaggedStyle = function (tag) {
  // TODO: Finish this method
  var tags = typeof (tag) === 'string' ? this._getTaggedStyleStartEnd(tag) : tag;
};
ptsBlockBase.prototype._getTaggedStyleStartEnd = function (tag, forRegExp) {
  return {
    start: forRegExp ? '\\/\\*start for ' + tag + '\\*\\/' : '/*start for ' + tag + '*/'
    , end: forRegExp ? '\\/\\*end for ' + tag + '\\*\\/' : '/*end for ' + tag + '*/'
  };
};
ptsBlockBase.prototype._initMenuItem = function (newMenuItemHtml, item) {
  if (this['_initMenuItem_' + item.type] && typeof (this['_initMenuItem_' + item.type]) === 'function') {
    var menuItemName = this.getParam('menu_item_name_' + item.type);
    if (menuItemName && menuItemName != '') {
      newMenuItemHtml.find('.ptsBlockMenuElTitle').html(menuItemName);
    }
    this['_initMenuItem_' + item.type](newMenuItemHtml, item);
  }
};
ptsBlockBase.prototype._initMenuItem_align = function (newMenuItemHtml, item) {
  if (this._data.params && this._data.params.align) {
    //newMenuItemHtml.find('input[name="params[align]"]').val( this._data.params.align.val );
    //newMenuItemHtml.find('.ptsBlockMenuElElignBtn').removeClass('active');
    //newMenuItemHtml.find('.ptsBlockMenuElElignBtn[data-align="'+ this._data.params.align.val+ '"]').addClass('active');
    this._setAlign(this._data.params.align.val, true, newMenuItemHtml);
  }
  var self = this;
  newMenuItemHtml.find('.ptsBlockMenuElElignBtn').click(function () {
    self._setAlign(jQuery(this).data('align'));
  });
};
ptsBlockBase.prototype._clickMenuItem_align = function (options) {
  return false;
};
ptsBlockBase.prototype._setAlign = function (align, ignoreAutoSave, menuItemHtml) {
  var possibleAligns = ['left', 'center', 'right'];
  for (var i in possibleAligns) {
    this._$.removeClass('ptsAlign_' + possibleAligns[i]);
  }
  this._$.addClass('ptsAlign_' + align);
  this.setParam('align', align);

  if (!menuItemHtml) {
    var menuOpt = this._$.data('_contentMenuOpt');
    menuItemHtml = menuOpt.items.align.$node;
  }
  menuItemHtml.find('input[name="params[align]"]').val(align);
  menuItemHtml.find('.ptsBlockMenuElElignBtn').removeClass('active');
  menuItemHtml.find('.ptsBlockMenuElElignBtn[data-align="' + align + '"]').addClass('active');

  if (!ignoreAutoSave) {
    _ptsSaveCanvas();
  }
};
ptsBlockBase.prototype._initMenuItem_bg_img = function (newMenuItemHtml, item) {
  if (this._data.params && this._data.params.bg_img_enb && parseInt(this._data.params.bg_img_enb.val)) {
    newMenuItemHtml.find('input[name="params[bg_img_enb]"]').attr('checked', 'checked');
  }
  var self = this;
  newMenuItemHtml.find('input[name="params[bg_img_enb]"]').change(function () {
    self.setParam('bg_img_enb', jQuery(this).attr('checked') ? 1 : 0);
    self._updateBgImg();
  });
};
ptsBlockBase.prototype._clickMenuItem_bg_img = function (options) {
  var self = this;
  ptsCallWpMedia({
    id: this._$.attr('id')
    , clb: function (opts, attach, imgUrl) {
      // we will use full image url from attach.url always here (not image with selected size imgUrl) - as this is bg image
      // but if you see really big issue with this - just try to do it better - but don't broke everything:)
      self.setParam('bg_img', attach.url);
      self._updateBgImg();
    }
  });
};
ptsBlockBase.prototype._updateBgImg = function (ignoreAutoSave) {
  this._rebuildCss();

  if (!ignoreAutoSave) {
    _ptsSaveCanvas();
  }
};
ptsBlockBase.prototype._clickMenuItem = function (key, options) {
  if (this['_clickMenuItem_' + key] && typeof (this['_clickMenuItem_' + key]) === 'function') {
    return this['_clickMenuItem_' + key](options);
  }
};
ptsBlockBase.prototype.getContent = function () {
  return this._$.find('.ptsBlockContent:first');
};
ptsBlockBase.prototype._revertReplaceContent = function (content) {
  var revertReplace = [
    { key: 'view_id' }
  ];
  for (var i = 0; i < revertReplace.length; i++) {
    var key = revertReplace[i].key
      , value = this.get(key)
      , replaceFrom = [value]
      , replaceTo = revertReplace[i].raw ? '{{table.' + key + '|raw}}' : '{{table.' + key + '}}';
    if (typeof (value) === 'string' && revertReplace[i].raw) {
      replaceFrom.push(value.replace(/\s+\/>/g, '>'));
    }
    for (var j = 0; j < replaceFrom.length; j++) {
      content = str_replace(content, replaceFrom[j], replaceTo);
    }
  }
  return content;
};
ptsBlockBase.prototype.getHtml = function () {
  var html = this.getContent().html();
  return this._revertReplaceContent(html);
};
ptsBlockBase.prototype.getCss = function () {
  var css = this.getStyle().html();
  return this._revertReplaceContent(css);
  return css;
};
ptsBlockBase.prototype.getIter = function () {
  return this._iter;
};
ptsBlockBase.prototype.beforeSave = function () {
  if (this._elements && this._elements.length) {
    for (var i = 0; i < this._elements.length; i++) {
      this._elements[i].beforeSave();
    }
  }
};
ptsBlockBase.prototype.afterSave = function () {
  if (this._elements && this._elements.length) {
    for (var i = 0; i < this._elements.length; i++) {
      this._elements[i].afterSave();
    }
  }
};
ptsBlockBase.prototype.mapElementsFromHtml = function ($html, clb) {
  var self = this
    , mapCall = function ($el) {

      var element = self.getElementByIterNum(jQuery($el).data('iter-num'));
      if (element && element[clb]) {
        element[clb]();
      }
    };
  $html.find('.ptsEl').each(function () {
    mapCall(this);
  });
  if ($html.hasClass('ptsEl')) {
    mapCall($html);
  }
};
ptsBlockBase.prototype.replaceElement = function (element, toParamCode, type) {
  // Save current element content - in new element internal data
  var oldElContent = element.$().get(0).outerHTML
    , oldElType = element.get('type')
    , savedContent = element.$().data('pre-el-content');
  if (!savedContent)
    savedContent = {};
  savedContent[oldElType] = oldElContent;
  // Check if there are already saved prev. data for this type of element

  var newHtmlContent = '';

  if (type == 'btn') {
    var existsBtnHTML = null;

    for (var i in this._elements) {
      if (this._elements[i] instanceof ptsElement_btn && this._elements[i]._$.length) {
        existsBtnHTML = this._elements[i]._$.get(0).outerHTML;

        break;
      }
    }

    if (existsBtnHTML)
      newHtmlContent = existsBtnHTML;
    else
      newHtmlContent = jQuery('#ptsElementButtonDefaultTemplate').removeAttr('id').get(0).outerHTML;
  } else {
    newHtmlContent = savedContent[type] ? savedContent[type] : this.getParam(toParamCode);
  }

  // Create and append new element HTML after current element
  var $newHtml = jQuery(newHtmlContent);
  $newHtml.insertAfter(element.$());
  // Destroy current element
  var self = this;
  this.destroyElementByIterNum(element.getIterNum(), function () {
    self._disableContentChange = true;
    // Init new element after prev. one was removed
    var newElements = self._initElementsForArea($newHtml);
    for (var i = 0; i < newElements.length; i++) {
      // Save prev. updated content info - in new elements $()
      newElements[i].$().data('pre-el-content', savedContent);
    }
    self._disableContentChange = false;
    self.contentChanged();
  });
};
ptsBlockBase.prototype.contentChanged = function () {
  if (!this._disableContentChange) {
    this._$.trigger('ptsBlockContentChanged', this);
  }
  // setTimeout(function() {
  // 	_ptsAddUndoBuffer(true);
  // }, 200);
};
ptsBlockBase.prototype.hideElementsMenus = function (showEvent) {
  if (this._elements && this._elements.length) {
    for (var i = 0; i < this._elements.length; i++) {
      if (this._elements[i].menuInAnimation()) return;	// Menu is in animation - so we don't need to hide it
      if (showEvent && showEvent != this._elements[i].getMenuShowEvent()) continue;
      this._elements[i].hideMenu();
    }
  }
};
/**
 * Price table block base class
 */
ptsBlock_price_table.prototype.addColumn = function () {
  var $colsWrap = this._getColsContainer()
    , $cols = this._getCols()
    , $col = null
    , self = this;
  if ($cols.length) {
    var $lastCol = $cols.last();
    this.mapElementsFromHtml($lastCol, 'beforeSave');
    $col = $cols.last().clone();
    this.mapElementsFromHtml($lastCol, 'afterSave');
  } else {
    $col = jQuery(this.getParam('new_column_html'));
  }
  if (isRtl) {
    $colsWrap.prepend($col);
  } else {
    $colsWrap.append($col);
  }

  this._initElementsForArea($col);
  this._initCellsEdit($col.find('.ptsCell'));
  this._switchHeadRow({ $cols: $col });
  this._switchDescRow({ $cols: $col });
  this._switchFootRow({ $cols: $col });
  this._initCellsMovable($col);
  this._refreshColNumbers();
  $cols = this._getCols();
  $cols.each(function () {
    var element = self.getElementByIterNum(jQuery(this).data('iter-num'));
    if (element) {
      // Update CSS style if required for updated classes
      element._setColor();
    }
  });
  this.checkColWidthPerc();
};
ptsBlock_price_table.prototype._initCellsEdit = function ($cell) {
  var block = this;

  $cell = $cell ? $cell : this._$.find('.ptsCell');
  $cell.each(function () {
    var $currentCell = jQuery(this);

    // Append cell buttons
    var $btnsShell = jQuery(this).find('.ptsCellEditBtnsShell');
    if ($btnsShell.length) {
      $btnsShell.html('');
    } else {
      $btnsShell = jQuery('<div class="ptsCellEditBtnsShell ptsShowSmooth" />').appendTo(this);
    }
    jQuery(this).on('click', function () {
      clearTimeout(jQuery(this).data('btn-shell-hide-timeout'));
      $btnsShell.addClass('active');

      var elementLeft = $btnsShell.offset().left
        , elementWidth = $btnsShell.outerWidth()
        , elementRight = elementLeft + elementWidth
        , screenWidth = screen.width;

      //off-screen element
      if (screenWidth < elementRight) {
        $btnsShell.addClass('ptsRightArrows');
        $btnsShell.css({ 'left': -(elementWidth + 5) + 'px' });
        $btnsShell.css({ 'left': -(elementWidth + 5) + 'px' });
        if (!jQuery('#ptsRightArrows').length) {
          jQuery('head').append('<style id="ptsRightArrows">.ptsCellEditBtnsShell.ptsRightArrows:before{border-left: 5px solid rgba(45, 34, 52, 0.96); border-right: none; left:' + elementWidth + 'px}</style>');
        }
      }

      $btnsShell.find('.ptsTextAlignColumn .ptsTextAlignSwitch.active')
        .removeClass('active');

      switch ($currentCell.css('text-align')) {
        case 'left':
          $btnsShell.find('.ptsTextAlignColumn .ptsTextAlignSwitch[data-align="left"]')
            .addClass('active');
          break;
        case 'center':
          $btnsShell.find('.ptsTextAlignColumn .ptsTextAlignSwitch[data-align="center"]')
            .addClass('active');
          break;
        case 'right':
          $btnsShell.find('.ptsTextAlignColumn .ptsTextAlignSwitch[data-align="right"]')
            .addClass('active');
          break;
      }
    });
    jQuery(this).hover(function () {
      clearTimeout(jQuery(this).data('btn-shell-hide-timeout'));
    }, function () {
      if (!$currentCell.hasClass('ui-sortable-helper')) {
        $currentCell.data('btn-shell-hide-timeout', setTimeout(function () {
          if (!$btnsShell.is(':hover')) {
            $btnsShell.removeClass('active');
            $btnsShell.find('.ptsTooltipEditWnd').removeClass('active');
          }
        }, 500));
      }
    });
    $btnsShell.hover(function () {
      clearTimeout($currentCell.data('btn-shell-hide-timeout'));
    }, function () {
      if (!$currentCell.hasClass('ui-sortable-helper')) {
        $currentCell.data('btn-shell-hide-timeout', setTimeout(function () {
          $btnsShell.removeClass('active');
          $btnsShell.find('.ptsTooltipEditWnd').removeClass('active');
        }, 500));
      }
    });

    // Move cell btn
    jQuery('#ptsMoveCellBtnExl').clone().removeAttr('id').appendTo($btnsShell);

    jQuery('#ptsTextAlignColumn')
      .clone()
      .removeAttr('id')
      .appendTo($btnsShell)
      .on('click', '.ptsTextAlignSwitch', function () {
        var $this = jQuery(this)
          , $cell = jQuery(this).parents('.ptsCell:first')
          , align = $this.attr('data-align');

        align = align.charAt(0).toUpperCase() + align.substr(1);

        $this.parent()
          .find('.ptsTextAlignSwitch')
          .removeClass('active');

        $this.addClass('active');

        $cell.removeClassWild('ptsCellAlign*');

        $cell.addClass('ptsCellAlign' + align);
      });

    // Add row after btn
    jQuery('#ptsAddRowAfterBtnExl').clone().removeAttr('id').appendTo($btnsShell).click(function () {
      block.addRow(jQuery(this).parents('.ptsCell:first').index(), true);
      return false;
    });
    // Add row before btn
    jQuery('#ptsAddRowBeforeBtnExl').clone().removeAttr('id').appendTo($btnsShell).click(function () {
      block.addRow(jQuery(this).parents('.ptsCell:first').index(), false);
      return false;
    });

    jQuery('#ptsAddOneCellInColumn').clone().removeAttr('id').appendTo($btnsShell).click(function () {
      var cell = jQuery(this).parents('.ptsCell:first').index()
        , col = jQuery(this).closest('.ptsCol').index();

      block.addOneRow(cell, col, true);

      return false;
    });
    jQuery('#ptsAddTextInCell').clone().removeAttr('id').appendTo($btnsShell).click(function () {

      block.addTextBlock(jQuery(this).parents('.ptsCell:first'));

      return false;
    });

    // Combining rows
    jQuery('#ptsCombiningPrevBtnExl').clone().removeAttr('id').appendTo($btnsShell).click(function () {
      var cell = jQuery(this).closest('.ptsCol')
        .find('.ptsRows .ptsCell')
        .get(
          jQuery(this)
            .parents('.ptsCell:first')
            .index()
        );

      block.combiningRow(cell);
      return false;
    });
    jQuery('#ptsCombiningNextBtnExl').clone().removeAttr('id').appendTo($btnsShell).click(function () {
      var cell = jQuery(this).closest('.ptsCol')
        .find('.ptsRows .ptsCell')
        .get(
          jQuery(this)
            .parents('.ptsCell:first')
            .index()
        );

      block.combiningRow(cell, true);
      return false;
    });

    // Tooltips edit buttons manipulations
    var $tooltipBtnShell = jQuery('#ptsTooltipEditBtnShellExl').clone().removeAttr('id').appendTo($btnsShell);
    $tooltipBtnShell.find('.ptsTooltipEditBtn').click(function () {
      var $tooltipWnd = $tooltipBtnShell.find('.ptsTooltipEditWnd');
      if ($tooltipWnd.hasClass('active')) {
        $tooltipWnd.removeClass('active')
      } else {
        $tooltipWnd.find('[name=tooltip]').val(jQuery(this).parents('.ptsCell:first').attr('title'));
        $tooltipWnd.addClass('active');
      }
      return false;
    });
    $tooltipBtnShell.find('[name=tooltip]').change(function () {
      var tooltip = jQuery.trim(jQuery(this).val());
      if (tooltip && tooltip != '') {
        jQuery(this).parents('.ptsCell:first').attr('title', tooltip);
      } else {
        jQuery(this).parents('.ptsCell:first').removeAttr('title');
      }
    });
    // Remove btn
    jQuery('#ptsRemoveRowBtnExl').clone().removeAttr('id').appendTo($btnsShell).click(function () {
      block.removeRow(jQuery(this).parents('.ptsCell:first'));
      return false;
    });
  });
};
ptsBlock_price_table.prototype._destroyCellsEdit = function ($cell) {
  this._$.find('.ptsCellEditBtnsShell').remove();
};
ptsBlock_price_table.prototype.getColsNum = function () {
  return this._getCols().length;
};
ptsBlock_price_table.prototype.addPtsEl = function (parent) {
  var $cellAppend = jQuery(this.getParam('new_cell_html'));
  parent.before($cellAppend);
  this._disableContentChange = false;
  this._initElementsForArea($cellAppend);
  this._initCellsEdit($cellAppend);
  this._disableContentChange = false;
  this.contentChanged();
};
ptsBlock_price_table.prototype.addTextBlock = function ($cellElement) {
  var $cellAppend = jQuery(this.getParam('new_cell_html')).find('.ptsTog');

  this._disableContentChange = true;
  $cellAppend.appendTo($cellElement);
  this._initElementsForArea($cellAppend);
  this._initCellsEdit($cellAppend);
  this._disableContentChange = false;

  this.contentChanged();
};
ptsBlock_price_table.prototype.addOneRow = function (positionCell, positionCol, isAfter) {
  var $cellAppend = jQuery(this.getParam('new_cell_html'))
    , columnObject
    , $cellElement;

  for (var i in this._elements) {
    var elementObject = this._elements[i];

    if (elementObject instanceof ptsElement_table_col && elementObject._colNum == positionCol) {
      columnObject = elementObject;

      break;
    }
  }

  if (!columnObject) return;

  $cellElement = columnObject._$.find(this.getColSelectors().cells.sel).eq(positionCell);

  if (!$cellElement) return;

  this._disableContentChange = true;

  if (isAfter)
    $cellAppend.insertAfter($cellElement);
  else
    $cellAppend.insertBefore($cellElement);

  this._initElementsForArea($cellAppend);

  this._initCellsEdit($cellAppend);

  this._disableContentChange = false;

  this.contentChanged();
};
ptsBlock_price_table.prototype.addRow = function (positionIndex, after) {
  this._disableContentChange = true;
  var $cols = this._getCols(true)
    , self = this;
  $cols.each(function () {
    var $rowsWrap = jQuery(this).find('.ptsRows')
      , $cell = null;
    if (typeof (positionIndex) === 'undefined') {
      $cell = jQuery(self.getParam('new_cell_html'));
      $rowsWrap.append($cell);
    } else {
      var $positionCell = $rowsWrap.find('.ptsCell:eq(' + positionIndex + ')');
      self.mapElementsFromHtml($positionCell, 'beforeSave');
      $cell = $positionCell.clone();
      self.mapElementsFromHtml($positionCell, 'afterSave');
      after
        ? $positionCell.after($cell)
        : $positionCell.before($cell);
    }
    self._initElementsForArea($cell);
    self._initCellsEdit($cell);
  });
  this._disableContentChange = false;
  this.contentChanged();
};
ptsBlock_price_table.prototype.combiningRow = function (cell1, next) {
  var $cell1 = jQuery(cell1);
  var $cell2 = next ? jQuery($cell1.next('.ptsCell')) : jQuery($cell1.prev('.ptsCell'));

  if ($cell2.length == 0) return;

  this._disableContentChange = true;
  var c1, c2;

  if (next) {
    c1 = $cell1;
    c2 = $cell2;
  } else {
    c1 = $cell2;
    c2 = $cell1;
  }

  this.mapElementsFromHtml(c1, 'beforeSave');
  this.mapElementsFromHtml(c2, 'beforeSave');

  c1.find('.ptsCellEditBtnsShell').remove();
  c2.find('.ptsCellEditBtnsShell').remove();
  c1.html(c1.html() + c2.html());
  c2.remove();

  this.mapElementsFromHtml(c1, 'afterSave');
  this.mapElementsFromHtml(c2, 'afterSave');

  this._initElementsForArea(c1);
  this._initCellsEdit(c1);

  this._disableContentChange = false;
  this.contentChanged();
};
ptsBlock_price_table.prototype.removeRow = function ($cell) {
  var block = this
    , cellIndex = $cell && typeof ($cell) === 'object' ? $cell.index() : false
    , $cols = this._getCols(true);
  if (cellIndex === false) {
    cellIndex = typeof ($cell) === 'number' ? $cell : $cols.last().find('.ptsCell').length - 1;
  }
  if (block._data && block._data.params && block._data.params.is_horisontal_row_type && block._data.params.is_horisontal_row_type.val && block._data.params.is_horisontal_row_type.val == 1) {
    setTimeout(function () {
      $cell.animateRemovePts(g_ptsAnimationSpeed);
    }, g_ptsAnimationSpeed);
  } else {
    $cols.each(function () {
      var $rowsWrap = jQuery(this).find('.ptsRows')
        , $removeCell = $rowsWrap.find('.ptsCell:eq(' + cellIndex + ')');
      if ($removeCell && $removeCell.length) {
        var $elements = $removeCell.find('.ptsEl');
        $elements.each(function () {
          block.removeElementByIterNum(jQuery(this).data('iter-num'));
        });
        setTimeout(function () {
          $removeCell.animateRemovePts(g_ptsAnimationSpeed);
        }, g_ptsAnimationSpeed);	// Wait animation speed time to finally remove cell html element
      }
    });
  }
  setTimeout(function () {
    block.contentChanged();
  }, 2 * g_ptsAnimationSpeed + 50);	// See prev lines - timeout for g_ptsAnimationSpeed + animation remove for same time g_ptsAnimationSpeed
};
ptsBlock_price_table.prototype.removeCol = function ($col) {
  var $cols = this._getCols();
  if ($cols.length) {
    var $removeCol = null;
    if (typeof ($col) === 'object') {	// Colum jquery obj specified
      $removeCol = $col;
    } else if (typeof ($col) === 'number') {	// Column item number specified
      $removeCol = $cols.filter(':eq(' + $col + ')');
    } else {	// Nothing was specified - remove last column in set
      $removeCol = $cols.last();
    }
    var colElement = this.getElementByIterNum($removeCol.data('iter-num'));
    if (colElement) {
      var self = this;
      colElement.destroy(function () {
        self.contentChanged();
      });
    }
  }
};
ptsBlock_price_table.prototype.getRowsNum = function () {
  return this._getCols().first().find('.ptsRows').find('.ptsCell').length;
};
ptsBlock_price_table.prototype._initHtml = function () {
  ptsBlock_price_table.superclass._initHtml.apply(this, arguments);
  var $colsWrap = this._getColsContainer()
    , self = this
    , axis = 'x';

  if (typeof self._data.params.is_horisontal_row_type !== 'undefined' && self._data.params.is_horisontal_row_type.val === '1') {
    axis = 'y';
  }

  $colsWrap.sortable({
    items: '.ptsCol:not(.ptsTableDescCol)'
    , axis: axis
    , handle: '.ptsMoveHandler'
    , start: function (e, ui) {
      _ptsSetSortInProgress(true);
      var dragElement = self.getElementByIterNum(ui.item.data('iter-num'));
      if (dragElement) {
        dragElement.onSortStart(axis);
      }
    }
    , stop: function (e, ui) {
      _ptsSetSortInProgress(false);
      var dragElement = self.getElementByIterNum(ui.item.data('iter-num'));
      if (dragElement) {
        dragElement.onSortStop();
      }

      var desiredOrder = [],
        unsortedCols = [];

      var $cols = self._getCols(),
        num = 1;

      $cols.each(function () {
        var element = self.getElementByIterNum(jQuery(this).data('iter-num'));

        if (element) {
          if (element._colNum != num) {
            desiredOrder.push(num);
            unsortedCols.push(element);
          }
          var classes = jQuery(this).attr('class')
            , newClasses = '';
          newClasses = (classes.replace(/ptsCol\-\d+/g, '') + ' ptsCol-' + num).replace(/\s+/g, ' ');
          jQuery(this).attr('class', newClasses);
        }

        num++;
      });

      var blockCss = self.get('css'),
        resultCss = '';
      for (var i = 0; i < unsortedCols.length; i++) {
        var el = unsortedCols[i],
          newNum = desiredOrder[i],
          num = unsortedCols[i]._colNum,
          mark = self._getTaggedStyleStartEnd('col color ' + unsortedCols[i]._colNum),
          colCss = '';

        el._setColNum(newNum);

        if (blockCss.indexOf(mark.start) > -1 && blockCss.indexOf(mark.end) > -1) {
          colCss = blockCss.substring(blockCss.indexOf(mark.start), blockCss.indexOf(mark.end) + mark.end.length);
        }

        if (!colCss.length)
          continue;
        var s = mark.start.replace('col color ' + num, 'col color ' + newNum);
        var e = mark.end.replace('col color ' + num, 'col color ' + newNum);

        colCss = colCss.replace(mark.start, s);
        colCss = colCss.replace(mark.end, e);
        colCss = str_replace_all(colCss, '.ptsCol-' + num, '.ptsCol-' + newNum);
        self.removeTaggedStyle('col color ' + num);
        resultCss += colCss;
      }
      if (!resultCss.length) return;
      self.set('css', self.get('css') + resultCss);
      self._rebuildCss();
      self.contentChanged();
    }
  });
  // Set cols numbers for all columns

  this._refreshColNumbers();
  this._initCellsEdit();
  this._initCellsMovable();
};
ptsBlock_price_table.prototype._refreshColNumbers = function () {
  var self = this
    , $cols = this._getCols()
    , num = 1;
  $cols.each(function () {
    var element = self.getElementByIterNum(jQuery(this).data('iter-num'));
    if (element) {
      element._setColNum(num);
      var classes = jQuery(this).attr('class')
        , newClasses = '';
      newClasses = (classes.replace(/ptsCol\-\d+/g, '') + ' ptsCol-' + num).replace(/\s+/g, ' ');
      jQuery(this).attr('class', newClasses);
    }
    num++;
  });
};
ptsBlock_price_table.prototype._setColorFromColorpicker = function (pcColor, ignoreAutoSave) {
  this.setParam('bg_color', pcColor.formatted);
  this._updateFillColor(ignoreAutoSave);
};
ptsBlock_price_table.prototype._updateFillColor = function (ignoreAutoSave) {
  this._rebuildCss();
  if (!ignoreAutoSave) {
    _ptsSaveCanvas();
  }
};
ptsBlock_price_table.prototype._getDescCol = function () {
  return this._$.find('.ptsTableDescCol');
};
ptsBlock_price_table.prototype.switchDescCol = function (state) {
  var $descCol = this._getDescCol();
  this.setParam('enb_desc_col', state ? 1 : 0);
  if (isRtl) {
    $descCol.closest('.ptsColsWrapper').append($descCol);
  }
  state
    ? $descCol.addClass('ptsShow').removeClass('ptsHide')
    : $descCol.addClass('ptsHide').removeClass('ptsShow');
  this.checkColWidthPerc();
};
ptsBlock_price_table.prototype._switchHeadRow = function (params) {
  params = params || {};
  if (typeof (params.state) === 'undefined') {
    params.state = !parseInt(this.getParam('hide_head_row'));	// "!" here is because option is actually for hide
  } else {
    this.setParam('hide_head_row', params.state ? 0 : 1);
  }
  if (typeof (params.$cols) === 'undefined') {
    params.$cols = this._getCols(true);
  }
  params.$cols.each(function () {
    var $cell = jQuery(this).find('.ptsColHeader');
    if ($cell && $cell.length) {
      params.state
        ? $cell.addClass('ptsShow').removeClass('ptsHide')
        : $cell.addClass('ptsHide').removeClass('ptsShow');
    }
  });
};
ptsBlock_price_table.prototype._switchDescRow = function (params) {
  params = params || {};
  if (typeof (params.state) === 'undefined') {
    params.state = !parseInt(this.getParam('hide_desc_row'));	// "!" here is because option is actually for hide
  } else {
    this.setParam('hide_desc_row', params.state ? 0 : 1);
  }
  if (typeof (params.$cols) === 'undefined') {
    params.$cols = this._getCols(true);
  }
  params.$cols.each(function () {
    var $cell = jQuery(this).find('.ptsColDesc');
    if ($cell && $cell.length) {
      params.state
        ? $cell.addClass('ptsShow').removeClass('ptsHide')
        : $cell.addClass('ptsHide').removeClass('ptsShow');
    }
  });
};
ptsBlock_price_table.prototype._switchFootRow = function (params) {
  params = params || {};
  if (typeof (params.state) === 'undefined') {
    params.state = !parseInt(this.getParam('hide_foot_row'));	// "!" here is because option is actually for hide
  } else {
    this.setParam('hide_foot_row', params.state ? 0 : 1);
  }
  if (typeof (params.$cols) === 'undefined') {
    params.$cols = this._getCols(true);
  }
  params.$cols.each(function () {
    var $cell = jQuery(this).find('.ptsColFooter');
    if ($cell && $cell.length) {
      params.state
        ? $cell.addClass('ptsShow').removeClass('ptsHide')
        : $cell.addClass('ptsHide').removeClass('ptsShow');
    }
  });
};
ptsBlock_price_table.prototype.beforeSave = function () {
  ptsBlock_price_table.superclass.beforeSave.apply(this, arguments);
  var $hoveredCol = this._getCols().filter('.hover');
  if ($hoveredCol && $hoveredCol.length) {
    this._backHoverFont($hoveredCol);
    this._$lastHoveredCol = $hoveredCol;
  }
  this._destroyCellsEdit();
};
ptsBlock_price_table.prototype.afterSave = function () {
  ptsBlock_price_table.superclass.afterSave.apply(this, arguments);
  if (this._$lastHoveredCol) {
    this._increaseHoverFont(this._$lastHoveredCol);
    this._$lastHoveredCol = null;
  }
  this._initCellsEdit();
};
ptsBlock_price_table.prototype._initCellsMovable = function ($cols) {
  $cols = $cols ? $cols : this._getCols(true);
  var block = this;
  $cols.each(function () {
    jQuery(this).find('.ptsRows').sortable({
      items: '.ptsCell'
      , axis: 'y'
      , handle: '.ptsMoveCellBtn'
      // No placeholder for now - it is look nice now without it too
      //,	placeholder: 'ptsCellDragHolder'
      , stop: function (event, ui) {
        block._refreshCellsHeight();
      }
    });
  });
};
//EDITOR BLOCKS END
//TABLES EDITOR
var g_ptsMainMenu = null
  , g_ptsFileFrame = null	// File frame for wp media uploader
  , g_ptsEdit = true
  , g_ptsTopBarH = 32		// Height of the Top Editor Bar
  , g_ptsSortInProgress = false
  , g_ptsEditMode = true	// If this script is loaded - this mean that we in edit mode
  , g_ptsUndoBuffer = []
  , g_ptsUndoBufferLength = 10
  , g_ptsUndoCurElement = -1
  , g_ptsAllowAddUndo = false
  , g_ptsVandColorPickerOptions = {
    'altAlpha': false,
    'showOn': 'alt',
    'altProperties': 'background-color',
    'altColorFormat': 'rgba(rd,gd,bd,af)',
    'okOnEnter': true,
    'stop': function () { _ptsAddUndoBuffer(true); },
    //'mode': 's',
    'alpha': true,
    'color': 'rgba(255, 255, 255, 0.8)',
    'colorFormat': 'RGBA',
    'title': 'Pick a color',
    'part': { 'map': { size: 128 }, 'bar': { size: 128 } },
    'parts': ['map', 'bar', 'rgb', 'alpha', 'hex', 'preview'],
    'layout': { 'map': [0, 0, 1, 4], 'bar': [1, 0, 1, 4], 'preview': [2, 0, 1, 1], 'rgb': [2, 1, 1, 1], 'alpha': [2, 2, 1, 1], 'hex': [2, 3, 1, 1], },
  };
jQuery(document).ready(function () {
  _ptsInitTwig();
  // Prevent all default browser event - such as links redirecting, forms submit, etc.
  jQuery('#ptsCanvas').on('click', 'a', function (event) {
    event.preventDefault();
  });
  jQuery('.ptsMainSaveBtn').click(function () {
    _ptsSaveCanvas();
    return false;
  });
  jQuery('#ptsUndoButton').click(function () {
    _ptsShowProcessing(true);
    setTimeout(function () {
      _ptsUndoCanvas();
      _ptsShowProcessing(false);
    }, 5);
    return false;
  });
  jQuery('#ptsRedoButton').click(function () {
    _ptsShowProcessing(true);
    setTimeout(function () {
      _ptsRedoCanvas();
      _ptsShowProcessing(false);
    }, 5);
    return false;
  });
});
function _ptsShowProcessing(show) {
  jQuery('#ptsUndoProcess').css('display', show ? 'inline-block' : 'none');
}
function _ptsSetUndoDelay(delay) {
  delay = delay ? delay : 200;
  setTimeout(function () {
    g_ptsAllowAddUndo = true;
  }, delay);
}
function _ptsAddUndoBuffer(isChange, refresh, force) {
  return false;
  if (!g_ptsAllowAddUndo || g_ptsSortInProgress) return;
  if (jQuery(!isChange && '.mce-edit-focus').length > 0) return;
  if (jQuery('.mce-floatpanel:visible:not(.mce-tinymce)').length > 0) return;
  if (jQuery('.ptsCellEditBtnsShell.active').length > 0 || jQuery('.ptsMenuSubOpened.active').length > 0) return;
  if (jQuery('.media-modal:visible').length > 0) return;

  var block = g_ptsBlockFabric._blocks[0];
  block.checkColWidthPerc();
  block._refreshCellsHeight();

  var curLength = g_ptsUndoBuffer.length,
    data = ptsGetFabric().getDataForSave()[0],
    canvasHtml = data['html'].trim(),
    canvasCss = jQuery('.ptsBlockStyle').html();

  if (curLength > 0) {
    var last = g_ptsUndoBuffer[(g_ptsUndoCurElement < 0 ? curLength - 1 : g_ptsUndoCurElement)];
    if (!force && last['html'] == canvasHtml && last['css'] == canvasCss) return;
  }

  var attrClass = jQuery('.ptsBlock').attr('class'),
    attrStyle = jQuery('.ptsBlock').attr('style'),
    settings = jQuery('.ptsSettingsContent').clone(true, true).html(),
    params = _ptsGetTableBlock().get('params'),
    paramsArr = [];

  for (var key in params) {
    paramsArr.push({ key: key, val: params[key].val });
  }
  _ptsInitSettings(false);

  if (refresh) {
    if (g_ptsUndoCurElement >= 0) {
      g_ptsUndoBuffer[g_ptsUndoCurElement] = { html: canvasHtml, css: canvasCss, settings: settings, attrClass: attrClass, attrStyle: attrStyle, params: paramsArr };
    }
  } else {
    if (g_ptsUndoCurElement >= 0) {
      var delta = curLength - g_ptsUndoCurElement - 1;
      if (delta > 0) {
        g_ptsUndoBuffer.splice(g_ptsUndoCurElement + 1, delta);
      }
    }
    if (curLength > g_ptsUndoBufferLength) {
      g_ptsUndoBuffer.shift();
    }
    g_ptsUndoBuffer.push({ html: canvasHtml, css: canvasCss, settings: settings, attrClass: attrClass, attrStyle: attrStyle, params: paramsArr });
    g_ptsUndoCurElement = -1;
    if (g_ptsUndoBuffer.length > 1) {
      jQuery('#ptsUndoButton').removeAttr('disabled');
    }
    jQuery('#ptsRedoButton').attr('disabled', 'disabled');
  }
  g_ptsAllowAddUndo = false;
  _ptsSetUndoDelay();
}
function _ptsRefreshTable(num) {
  var $tbl = jQuery('.ptsBlockContent').closest('.ptsBlock'),
    block = g_ptsBlockFabric._blocks[0],
    settings = jQuery('.ptsSettingsContent');

  block.setRaw($tbl);
  jQuery('.ptsBlock').attr('class', g_ptsUndoBuffer[num]['attrClass']);
  jQuery('.ptsBlock').attr('style', g_ptsUndoBuffer[num]['attrStyle']);
  jQuery('#containerWrapper .ptsSettingsTabs a.nav-tab-active').trigger('click');
  _ptsInitSettings(true);

  settings.find('select.chosen').each(function () {
    var $this = jQuery(this),
      selected = $this.parent().find('a.chosen-single span').text();
    $this.find('option').removeAttr('selected');
    $this.find('option[value="' + selected + '"]').prop('selected', true);
  });

  settings.find('.chosen-container').remove();
  settings.find('.chosen').chosen({ disable_search_threshold: 5 });

  var block = _ptsGetTableBlock(),
    paramsArr = g_ptsUndoBuffer[num]['params'];
  for (var i in paramsArr) {
    block.setParam(paramsArr[i]['key'], paramsArr[i]['val']);
  }
  _ptsAddUndoBuffer(false, true);
}
function _ptsSetTableFromBuffer(num) {
  jQuery('.ptsBlockContent').html(g_ptsUndoBuffer[num]['html']);
  jQuery('.ptsBlockStyle').html(g_ptsUndoBuffer[num]['css']);
  jQuery('.ptsSettingsContent').html(g_ptsUndoBuffer[num]['settings']);
  _ptsRefreshTable(num);
}
function _ptsUndoCanvas() {
  var curLength = g_ptsUndoBuffer.length;

  if (curLength == 0) return;
  g_ptsAllowAddUndo = false;
  g_ptsUndoCurElement = (g_ptsUndoCurElement < 0 || g_ptsUndoCurElement >= curLength ? curLength - 2 : g_ptsUndoCurElement - 1);
  if (g_ptsUndoCurElement >= 0) {
    _ptsSetTableFromBuffer(g_ptsUndoCurElement);
  }
  jQuery('#ptsRedoButton').removeAttr('disabled');
  if (g_ptsUndoCurElement <= 0) {
    jQuery('#ptsUndoButton').attr('disabled', 'disabled');
  }
  _ptsSetUndoDelay();
}
function _ptsRedoCanvas() {
  var curLength = g_ptsUndoBuffer.length;

  if (curLength == 0) return;
  g_ptsAllowAddUndo = false;
  g_ptsUndoCurElement++;
  if (g_ptsUndoCurElement < curLength) {
    _ptsSetTableFromBuffer(g_ptsUndoCurElement);
  }
  jQuery('#ptsUndoButton').removeAttr('disabled');
  if (g_ptsUndoCurElement >= curLength - 1) {
    jQuery('#ptsRedoButton').attr('disabled', 'disabled');
  }
  _ptsSetUndoDelay();
}
function _ptsSaveCanvasDelay(delay) {
  delay = delay ? delay : 200;
  setTimeout(_ptsSaveCanvas, delay);
}
function _ptsSaveCanvas(params, byHands) {
  if (!!parseInt(toeOptionPts('disable_autosave')) && 'undefined' == typeof byHands) {
    return;	// Autosave disabled in admin area
  }
  if (typeof (ptsTables) === 'undefined' || !ptsTables || !ptsTables.length || (typeof (g_ptsIsTableBuilder) !== 'undefined' && g_ptsIsTableBuilder)) {
    return;
  }
  if (typeof (ptsTables[0].params.enable_switch_toggle) != 'undefined' && ptsTables[0].params.enable_switch_toggle.val == 0) {
    //toggle options not enabled
  } else {
    //toggle enabled
    jQuery(document.body).trigger('updateToggleHtml');
  }

  params = params || {};
  savedData = ptsGetFabric().getDataForSave()[0]; //[0] - is because only one block (table) is in this plugin saved
  var dataForSave = {
    mod: 'tables'
    , action: 'save'
    , pts_nonce: PTS_NONCE['pts_nonce']
    , data: savedData
  };
  if (params.sendData) {
    for (var key in params.sendData) {
      dataForSave.data[key] = params.sendData[key];
    }
  }
  jQuery.sendFormPts({
    btn: jQuery('.ptsTableSaveBtn')
    , data: dataForSave
    , onSuccess: function (res) {
      if (!res.error) {

      }
    }
  });
}
function _ptsSortInProgress() {
  return g_ptsSortInProgress;
}
function _ptsSetSortInProgress(state) {
  g_ptsSortInProgress = state;
}
function _ptsInitTwig() {
  Twig.extendFunction('adjBs', function (hex, steps) {
    if (!hex)
      return hex;
    var isRgb = hex.indexOf('rgb') !== -1;
    if (isRgb) {
      var colorObj = tinycolor(hex);
      hex = colorObj.toHex();
    }
    // Steps should be between -255 and 255. Negative = darker, positive = lighter
    steps = Math.max(-255, Math.min(255, steps));
    // Normalize into a six character long hex string
    hex = str_replace(hex, '#', '');
    if (hex.length == 3) {
      hex = str_repeat(hex.substr(0, 1), 2) + str_repeat(hex.substr(1, 1), 2) + str_repeat(hex.substr(2, 1), 2);
    }
    // Split into three parts: R, G and B
    var color_parts = str_split(hex, 2);
    var res = '#';
    for (var i in color_parts) {
      var color = color_parts[i];
      color = hexdec(color); // Convert to decimal
      color = Math.max(0, Math.min(255, color + steps)); // Adjust color
      res += str_pad(dechex(color), 2, '0', 'STR_PAD_LEFT'); // Make two char hex code
    }
    if (isRgb) {
      return tinycolor(res).setAlpha(colorObj.getAlpha());
    }
    return res;
  });
}
// TABLES EDITOR END