Zedity

Description

/*

Screenshots

Reviews

Great Plugin and Fantastic Support

I’ve been using Zedity since late 2015 and it’s helped me create wonderful effects for [link removed] The Zedity team is constantly looking for ways to enhance Zedity and make it easier for everyone to use. Their support is wonderful! They are responsive and incredibly helpful. I’ve never been disappointed and highly recommend them!

Beyond great support

After having a number of difficulties caused by the way my site was develoepd, tech support at Zedity did everything, and then some, to help me get things fixed. I’m not only delighted to be up and running (finally) – I’m also happy that these people put up with me for as long as the did. This truly is beyond great service!

Read all 110 reviews

Contributors & Developers

“Zedity” is open source software. The following people have contributed to this plugin.

“Zedity” has been translated into 3 locales. Thank you to the translators for their contributions.

Translate “Zedity” into your language.

Interested in development?

Browse the code, check out the SVN repository, or subscribe to the development log by RSS.

Changelog

7.3.2

  • Improved compatibility with IE11.

7.3.1

  • Improved compatibility with third-party plugins.

7.3.0

  • The HTML box is now available also in the free version.

7.2.2

  • Fixed link target in Image box.
  • Theme isolation improvements for Text box.

7.2.1

  • Minor CSS improvements.

7.2.0

  • Added undo/redo functions in Text box.

7.1.5

  • Minor optimizations.
  • Custom web fonts handling improvements (only Premium).

7.1.3

  • Various optimizations in editor main menu.
  • Color selection adjustments for transparency.
  • Plugin activation improvement.

7.1.2

  • Style tweaks.
  • Updated Facebook video embed (only Premium).
  • Improved integration with lightbox plugins (only Premium).

7.1.1

  • Improved compatibility with WP 4.5+.
  • Improved integration with TinyMCE.

7.1.0

  • Various optimizations.
  • Multiple Layout Responsive Design (MLRD) improvements:
    • Function to clear a layout.
    • Label in “Content” tab with current layout indication.
    • Label on boxes to show the owner layout.
    • Option to hide the icons for hidden boxes.

7.0.1

  • Optimized script loading.
  • Multiple Layout Responsive Design (MLRD) improvements:
    • Now can add custom layout after defining any of the basic layouts.
    • Keep custom layout width when adding next custom layout.
    • Fixed ability to change image in Image box for different layouts.

7.0.0

  • New Draw box.
  • Touch screen usability improvements.
  • Improved themes compatibility.

6.4.0

  • Added Hungarian and Vietnamese languages.

6.3.1

  • Improved themes compatibility.

6.3.0

  • Various Video Box optimizations.
  • Added support for Autoplay option in YouTube and Vimeo videos (Premium only).

6.2.8

  • Many touch screen usability improvements.
  • Various other optimizations.

6.2.7

  • Text box optimizations.
  • Multiple Layout Responsive Design (MLRD) optimizations (Premium only).
  • Updated facebook video embed (Premium only).

6.2.6

  • Minor optimizations.

6.2.5

  • Minor fixes.

6.2.4

  • Some translation updates for inclusion in WP translation system.
  • Minor fixes.

6.2.3

  • Editor loading improvements and loading indication.
  • Improved compatibility with other plugins.

6.2.2

  • Tutorials usability improvements.
  • Various style adjustments.

6.2.1

  • Various optimizations: faster loading, less memory usage, smaller file size.
  • Theme isolation improvements.

6.2.0

  • Interactive step-by-step tutorials.
  • Text box optimizations.
  • Theme isolation improvements.

6.1.5

  • Improved compatibility with some non-standard server configurations.
  • Various optimizations.

6.1.4

  • Setting to enable/disable adding empty lines above/below Zedity content on save.
  • Improved compatibility with third-party plugins.
  • Various API and style improvements.

6.1.3

  • Box drag & drop optimizations.
  • Improved compatibility with WP >4.2.
  • Interface adjustments.
  • Box size feature with “Keep aspect ratio” lock (only Premium).
  • Responsive hide/show box fix (only Premium).

6.1.2

  • WP compatibility improvements (various adjustments for WP versions >4.2 and <4.1)
  • Grid performance improvements and size lock (only Premium).

6.1.1

  • Shortcut to edit boxes with double-click.
  • Minor improvements.

6.1.0

  • Added Box opacity feature.
  • Added help tips to Content Duplicate feature.
  • Minor adjustments.
  • Added support for Google Drive documents in Document Box (only Premium).

6.0.0

  • Completely redesigned interface.
  • Support for touch screen devices.
  • Easier box one-click selection and drag.
  • Many minor improvements and optimizations.
  • Ability to specify text alignment for single paragraphs or for the whole Text box (only Premium).
  • Paragraph spacing in Text box (only Premium).
  • New option for the links: open in same frame (only Premium).

5.0.4

  • Added Chinese translation.
  • Color picker and misc optimizations.

5.0.3

  • Fixed a security issue.

5.0.2

  • Optimizations in Box positioning.
  • Various minor optimizations and improvements.

5.0.1

  • Fixes for minor bugs affecting text boxes (text selection with keyboard, link styling).
  • Minor optimizations.

5.0.0

  • Dialogs interface major restyling and functionality improvements.
  • Improved compatibility with other plugins.
  • Various optimizations.

4.14.0

  • Added Dutch translation.

4.13.1

  • Content save optimizations.
  • Minor styling adjustments.

4.13.0

  • Improved box handles interface.
  • Improved compatibility with older versions of WP.

4.12.0

  • New interface (drag handle) to rotate boxes.
  • Improved compatibility with older versions of WP.

4.11.0

  • Now can resize rotated boxes.
  • Various rotation improvements.

4.10.2

  • Improved interface in Text box font/size selection.
  • Improved compatibility with WP 4.1.
  • Optimized use of custom colors in Text box links.

4.10.1

  • Optimized text selection in Text box.
  • Various UI tweaks.
  • Optimized link on Image box.

4.10.0

  • Increased content maximum height.
  • Added support for YouTube playlists.
  • Enhanced themes compatibilities.

4.9.1

  • Compatibility adjustments for upcoming WP 4.1.

4.9.0

  • Promo notification messages are now dismissable.

4.8.2

  • Optimized text shadow handling.

4.8.1

  • Fixed a problem in Audio boxes when using HTML5 audio in a responsive design.
  • Added “Rate Zedity” link in Plugins page.

4.8.0

  • Rewritten integration with TinyMCE. Increased stability and compatibility with other plugins, including the Fullscreen feature of WP.

4.7.2

  • Fixed MLRD Audio box management.
  • Optimizations in Text box text selection.

4.7.1

  • Fixed edit existing contents in Internet Explorer.

4.7.0

  • New feature to paste into the Text box as either plain text or formatted text.

4.6.0

  • Added line spacing feature in Text box Paragraph settings.
  • Added subscript and superscript features in Text box Font settings.
  • Added Indonesian translation.

4.5.2

  • Zedity core enhancements.

4.5.1

  • Addded a workaround to cope with a bug in Chrome causing problems with the text selection.
  • Improved grid when there is a background box.
  • Enhanced Dialogs, Image box and translations.
  • Updated YouTube video API.

4.5.0

  • Added content templating system.
  • Added box shadow function.
  • Fixed an Audio box browser compatibility when using a responsive design.

4.4.1

  • Various improvements including cache optimizations.

4.4.0

  • New feature to copy a Zedity content into another post or page. It can also be used to create templates.

4.3.0

  • Added Polish translation.
  • Minor optimizations.

4.2.1

  • Adjustments for upcoming WP4.
  • Minor improvements.

4.2.0

  • Added Grid and Snap to grid functions.
  • Various optimizations.

4.1.0

  • Added Czech translation.
  • Enhanced compatibility with WP network installations.

4.0.0

  • Improved MLRD (Multiple Layout Responsive Design):
    • Start design from any layout.
    • Add boxes in any layout.
    • Hide boxes added in other layouts.

3.6.1

  • Updated Russian and Ukrainian translations.

3.6.0

  • Added Ukrainian translation.
  • Some fixes and optimizations.

3.5.0

  • Added Russian translation.
  • Enabled Video box to support Instagram videos.

3.4.0

  • Content width and height can also be resized easily with a drag handle.
  • Snap to page/box now available also for box resizing.
  • Enabled Video box to support Facebook videos.

3.3.0

  • Improved HTML box for social sharing scripts.
  • Don’t show the Z icon for user roles who don’t have enough permissions.
  • Various optimizations.

3.2.0

  • Custom layouts in “Multiple Layout Responsive Design” (MLRD).
  • New fit to page width/height functions.
  • MLRD improvements: auto-fit big boxes and abort MLRD.
  • Optimizations for WordPress 3.9.

3.1.2

  • Adjustments to improve compatibility with new TinyMCE included in WordPress 3.9.

3.1.1

  • Fixed compatibility issue with WordPress 3.9.

3.1.0

  • Integration of Video and Audio boxes with WP Media Library: insert video and audio directly from your library.
  • Added Spanish translation.
  • Extended box size panel with x/y box position fields to specify exact box position.

3.0.1

  • Improved compatibility with other plugins.

3.0.0

  • New “Multiple Layout Responsive Design” (MLRD) feature.
  • Added help in menu with link to Zedity tutorials.

2.5.2

  • Improved link styles in Text box.
  • Minor optimizations and fixes.

2.5.1

  • Fixed an XSS issue and improved overall security.
  • Improved text and link styles in Text box.
  • Various optimizations and fixes.

2.5.0

  • Improved Text box styles to avoid external influences, e.g. WordPress removing empty paragraphs.
  • Added German and Greek translations.

2.4.0

  • Text box: new feature to specify custom link styles both the normal case and on mouse hovering.
  • Image box: new features to set the box size to real image size and to have visual feedback (box border color) when the box size is different than the original image size.
  • Multi-language: added support for French.
  • Various fixes and optimizations.

2.3.0

  • Multilanguage enabled. Now available in Italian.
  • Enhanced integration with Media Library: choose image size.
  • Various optimizations.

2.2.1

  • Minor fix for a PHP warning.

2.2.0

  • Now Zedity can be used also by Authors and Editors, not only Administrators.
  • HTML Box enhancements.
  • Image box with link to itself like for WP images from the Media Library.
  • Various optimizations and fixes.

2.1.4

  • Removed dependency from jQueryUI default css.

2.1.3

  • Optimizations in TinyMCE content selection.
  • Custom web fonts in Isolated mode.
  • Enhanced compatibility with other plugins and with WP edit image.
  • Some UI optimizations.

2.1.2

  • Enhanced compatibility with other plugins and themes.
  • Minor optimizations.

2.1.1

  • Improved compatibility with secondary TinyMCE editors provided by other plugins.
  • Various optimizations in Image box image layout.

2.1.0

  • New content save method. Choose between isolated mode or standard mode.
  • Integration of Image box with WP Media Library: insert images directly from your library.
  • Optimized Image box for SEO and social sharing.
  • New paragraph indent/outdent feature in Text box.
  • New ordered/unordered lists feature in Text box.
  • Color buttons and custom colors now available also in Text box for text color.
  • Added support for Google Fonts in custom web fonts.
  • Visual feedback of snap to box feature.
  • Added status bar.
  • Enhanced content saving handling (addressing cases of post returning 302 and target attributes for links).

2.0.3

  • Added safe mode feature for HTML Box.
  • Added setting to enable/disable the Zedity content preview in the WP editor.

2.0.2

  • Better management of webfonts.
  • Enhanced compatibility with other plugins using their own media plugin.

2.0.1

  • Manage content loading when the Media Library, or users, generate urls with different domain from the admin area.

2.0.0

  • Introduced Responsive Scaling, making Zedity contents perfectly fit into responsive designs.
  • Zedity content saved into the WordPress Media Library.
    That comes with a better content management, safer content uploading and no more undesired modifications from other plugins/themes.
  • Responsive no-conflict setting for themes who already provide responsive iframes.
  • Added 1-click align to page feature.
  • Added snap to page and snap to box for any box.
  • Possibility to associate a global url link to the whole Zedity content.
  • Added color buttons to show currently selected color and specify unlimited custom colors.

1.5.4

  • Enhanced compatibility with plugins that change the standard WordPress editor.
  • Prevent the WP editor from removing empty paragraphs in Zedity content.

1.5.3

  • Added support to address a bug in Chrome 31 with TinyMCE selection.

1.5.2

  • New feature to associate a link to the Text and Color boxes (like for the Image box).
  • Minor enhancements, including styled dialogs for page dimensions, etc.

1.5.1

  • Fixed a text styling issue in some browsers.

1.5.0

  • Introduced HTML5 box, for ultimate flexibility.
  • Added feature to keep aspect ratio when specifying box size.
  • Various optimizations and improvements.

1.4.0

  • New feature to enable/disable the WP Theme style for the published Zedity content.
  • Text box: improved text shadow and text height.

1.3.0

  • Added support for adding custom fonts.
  • Added support for WP multisite network installation and activation.
  • Added possibility to edit existing links in Text box.

1.2.0

  • New feature to change box size by entering exact dimensions.
  • New dialog for links in Text box, with possibility to open link in the same or new tab.
  • Added option to remove the link from Image box.
  • Support to notify users directly in WordPress admin area whenever a new version is available.
  • Optimized images css for some non-default themes.
  • Workaround for a WordPress bug where ThickBox breaks sites with RTL languages.

1.1.0

  • New feature to associate a link to the Image box.
  • Added indication of media services who don’t support preview.
  • Now border opacity slider applies opacity during slide.

1.0.2

  • Fixed an issue with TinyMCE css handling that affected images.

1.0.1

  • Optimized visual/text switch mode.

1.0.0

  • Initial version

*/

class WP_Zedity_Plugin_Premium extends WP_Zedity_Plugin {

protected $zedityServerBaseUrl;

const NETWORK_ERROR = '<h3>Your WordPress environment failed to reach our server.</h3><p>This may be caused by a temporary glitch, firewalls or your network configuration.<br/>If the error persists, please double check with your network administrator, who may have to whitelist zedity.com or take any other action needed.</p>';

public function __construct() {
    parent::__construct();

    register_deactivation_hook(__FILE__, array(&$this, 'deactivate'));

    //stop here if we are not in admin area
    if (!is_admin()) return;

    add_filter('pre_set_site_transient_update_plugins', array(&$this, 'check_version'));
    add_filter('plugins_api', array(&$this, 'plugins_api'), 10, 3);

    //show message on top for new update available
    $version = get_option('zedity_premium_new_version_available',FALSE);
    if ($version!==FALSE) {
        $version = trim($version);
        if (version_compare(trim($this->plugindata['Version']), $version, '<')) {
            $this->show_message(
                '<p>' . sprintf(__('A new version of %s is available','zedity'),'<b>Zedity Premium</b>') . " ($version).</p>".
                '<p>' . sprintf(__('Please %s to download the new version.','zedity'),
                "<a target='_blank' href='$this->zedityServerBaseUrl/account/login'>".sprintf(__('access your %s profile','zedity'),'Zedity Premium').'</a>').'</p>',
                array('plugins.php','update-core.php')
            );
        } else {
            delete_option('zedity_premium_new_version_available');
        }
    }
}

public function activate($network_wide) {
    if (isset($_GET['action']) && $_GET['action'] == 'error_scrape') {
        //show error message
        echo get_site_transient('zedity_activation_error');
        exit;
    }
    $this->server_activation($network_wide);
    parent::activate($network_wide);
}

public function server_activation($network_wide){
    $key = trim(@file_get_contents(sprintf("%s/data/key.txt", dirname(__FILE__))));
    $response = wp_remote_post("$this->zedityServerBaseUrl/plugin/wppactivate", array('body' => array(
        'key' => $key,
        'at' => $network_wide ? '2' : '1',
        'hosts' => $network_wide ? get_blog_count() : '1',
        'pver' => $this->plugindata['Version'],
        'admin_email' => get_option('admin_email'),
        'user_email' => wp_get_current_user()->data->user_email,
    )));
    $respCode = wp_remote_retrieve_response_code($response);
    $errMsg = FALSE;
    if ($respCode===0 || is_wp_error($response)) {
        $errMsg = self::NETWORK_ERROR;
    } else {
        //do not check resp code
        $data = wp_remote_retrieve_body($response);
        if (!empty($data)) {
            $errMsg = $data;
        }
    }
    if ($errMsg !== FALSE) {
        //set error message and trigger error
        set_site_transient('zedity_activation_error',$errMsg,60);
        trigger_error($errMsg, E_USER_ERROR);
    }
}

public function deactivate() {
    delete_option('zedity_premium_new_version_available');
}


public function is_premium() {
    return TRUE;
}

public function version_check(){
    $version = parent::version_check();
    $version['message'] = str_replace(
        __('update now','zedity'),
        "<a target=\"_blank\" href=\"{$this->zedityServerBaseUrl}/plugin/wp\">".__('update now','zedity').'</a>',
        $version['message']
    );
    return $version;
}

public function promo_check() {
    delete_site_transient('zedity_promo');
    return array('promocode'=>'');
}

public function check_version($transient) {
    if (empty($transient->checked)) return $transient;

    $request = wp_remote_get("$this->zedityServerBaseUrl/plugin/wppinfo?ask=version");
    if (is_wp_error($request) || wp_remote_retrieve_response_code($request)!=200) return false;
    $remote_version = wp_remote_retrieve_body($request);

    if (version_compare($this->plugindata['Version'], $remote_version, '<')) {
        $transient->response['zedity-premium/zedity-premium.php'] = (object)array(
            'slug' => 'zedity-premium',
            'new_version' => $remote_version,
            'url' => $this->plugindata['PluginURI'],
            //'package' => 'https://zedity.com/update.zip',
        );
        update_option('zedity_premium_new_version_available',$remote_version);
    } else {
        update_option('zedity_premium_new_version_available',FALSE);
    }
    return $transient;
}

public function plugins_api($false, $action, $args) {
    if (empty($args) || empty($args->slug) || $args->slug != 'zedity-premium') return false;

    //get Zedity info from WP repository
    $request = wp_remote_post('https://api.wordpress.org/plugins/info/1.0/', array('body' => array(
        'action' => 'plugin_information',
        'request' => serialize((object) array('slug' => 'zedity'))
    )));
    if (is_wp_error($request) || wp_remote_retrieve_response_code($request)!=200) return false;
    $body = wp_remote_retrieve_body($request);
    $body = unserialize($body);
    $response = $body;

    //get info for Zedity Premium
    $request = wp_remote_get("$this->zedityServerBaseUrl/plugin/wppinfo?ask=info");
    if (is_wp_error($request) || wp_remote_retrieve_response_code($request)!=200) return false;
    $body = wp_remote_retrieve_body($request);
    $body = unserialize($body);

    unset($response->downloaded);
    unset($response->download_link);

    $response->name = $this->plugindata['Name'];
    $response->slug = 'zedity-premium';
    $response->version = $body->version;
    $response->last_updated = $body->last_updated;
    $response->sections['changelog'] = $body->sections['changelog'];
    //$response->download_link = 'https://zedity.com/plugin/';

    return $response;
}

public function get_id(){
    return array(
        'key' => trim(@file_get_contents(sprintf("%s/data/key.txt", dirname(__FILE__)))),
        'uid' => get_current_user_id(),
        'uemail' => wp_get_current_user()->data->user_email,
        'site' => get_home_url(),
        'muls' => is_multisite()
    );
}

public function open_editor(){
    $id = $this->get_id();
    $response = wp_remote_post("$this->zedityServerBaseUrl/plugin/wpstae", array('body' => $id));
    $respCode = wp_remote_retrieve_response_code($response);
    if ($respCode===0 || is_wp_error($response)) {
        echo self::NETWORK_ERROR . '</body></html>';
        die;
    }
    if ($respCode === 200) {
        $data = wp_remote_retrieve_body($response);
        if (!empty($data)) {
            echo "<h3>$data</h3></body></html>";
            die;
        }
    }
}


//----------------------------------------------------------------------------------------------

public function add_head_css() {
    parent::add_head_css();
    $options = $this->get_options();
    if (isset($options['customfontscss'])) {
        echo "<style type=\"text/css\">{$options['customfontscss']}</style>";
    }
}

public function add_admin_js(){
    parent::add_admin_js();
    ?>
    <script type="text/javascript">
    jQuery(function(){
        if (!window.tinyMCE) return;
        var old_close = window.zedityLightbox.close;
        window.zedityLightbox.close = function(){
            jQuery.ajax({
                type: 'POST',
                url: '<?php echo "$this->zedityServerBaseUrl/plugin/wpstoe" ?>',
                data: <?php echo json_encode($this->get_id())?>
            });
            old_close.apply(this,arguments);
        };
    });
    </script>
    <?php
}

public function mce_config($init) {
    if (empty($init)) return;
    if (!current_user_can('unfiltered_html')) return $init;

    $init = parent::mce_config($init);
    //allow all elements to allow for svg (draw box)
    $init['valid_elements'] = '*[*]';
    $init['extended_valid_elements'] = '*[*]';
    return $init;
}


//--------------------------------------------------------------------------------

public function get_defaults() {
    $defaults = parent::get_defaults();
    $defaults = array_merge($defaults, array(
        'watermark' => 'bottomright',
        'responsive' => 1,
        'snap_to_page' => TRUE,
        'snap_to_boxes' => FALSE,
        'snap_to_grid' => TRUE,
        'grid_width' => 25,
        'grid_height' => 25,
    ));
    return $defaults;
}

public function get_options_name(){
    return 'zedity_premium_settings';
}

public function zedity_settings_validate($input) {
    $options = parent::zedity_settings_validate($input);

    $options['customfontscss'] = trim($input['customfontscss']);

    //parse code for @font-face defined fonts
    $ret = preg_match_all('/@font-face[^\}]*?font-family:\s*[\'\"]*(.*?)[\'\"]*\s*[;\}]/ims', $options['customfontscss'], $matches);
    if ($ret!==FALSE && $ret>0) {
        $options['customfonts'] = $matches[1];
    } else {
        $options['customfonts'] = array();
    }
    //parse code for @import (google fonts)
    $ret = preg_match_all('/@import\s*?url\(.*?[\?\&]family=(.*?)(?:[&:].*?)*[\'\"]*\);/ims', $options['customfontscss'], $matches);
    if ($ret!==FALSE && $ret>0) {
        $options['customfonts'] = array_merge(
            $options['customfonts'],
            array_map('urldecode',$matches[1])
        );
    }

    $options['responsive'] = $input['responsive'];
    $options['responsive_noconflict'] = ($input['responsive_noconflict'] == 1);

    $options['snap_to_page'] = isset($input['snap_to_page']);
    $options['snap_to_boxes'] = isset($input['snap_to_boxes']);
    $options['snap_to_grid'] = isset($input['snap_to_grid']);
    $options['grid_width'] = $input['grid_width'];
    $options['grid_height'] = $input['grid_height'];

    return $options;
}


public function additional_settings_page($options){
    $settings = $this->get_options_name();
    ?>
    <h3 class="title"><?php _e('Custom web fonts','zedity')?></h3>
    <p>
        <?php echo sprintf(__('Enter the CSS code for your custom web fonts or for additional Google web fonts using either %s or %s syntax.','zedity'),'<b>@font-face</b>','<b>@import</b>')?><br/>
        <?php _e('For example, to add the Hanalei Google web font you can simply copy/paste the code provided by Google:','zedity')?>
    </p>
    <p>@import url(http://fonts.googleapis.com/css?family=Hanalei);</p>

    <textarea id="txtCustomFonts" rows="10" cols="120" name="<?php echo $settings?>[customfontscss]"><?php echo $options['customfontscss'] ?></textarea><br/>
    <button class="button" id="btnCheckFonts"><?php _e('Check web fonts','zedity')?></button>
    <script type="text/javascript">
        //accept @font-face and @import as provided by google web fonts
        jQuery('#btnCheckFonts').on('click',function(){
            var val = jQuery.trim(jQuery('#txtCustomFonts').val());
            if (!val) {
                alert('<?php echo addslashes(__('Nothing to check.','zedity'))?>');
                return false;
            }
            var fonts = new Array();
            var found;
            var rx1 = new RegExp('@font-face[^}]*?font-family:\\s*[\'"]*(.*?)[\'"]*\s*[;}]','gi');
            var rx2 = new RegExp('@import\\s*?url\\(.*?[\\?&]family=(.*?)(?:[&:].*?)*[\'"]*\\);','gi');
            while (found=rx1.exec(val)) {
                fonts.push(decodeURIComponent(found[1].replace(/\+/g,'%20')));
            }
            while (found=rx2.exec(val)) {
                fonts.push(decodeURIComponent(found[1].replace(/\+/g,'%20')));
            }
            if (fonts.length>0) {
                alert('<?php echo addslashes(__('Detected web fonts:','zedity'))?>' +" \n" + fonts.join(', '));
            } else {
                alert('<?php echo addslashes(__('No web font detected. Please check your CSS syntax.','zedity'))?>');
            }
            return false;
        });
    </script>
    <hr/>

    <h3 class="title"><?php _e('Responsive content','zedity')?></h3>
    <p><?php _e('Set the desired responsivenss option (you can also change the setting while editing, from the bar at the top):','zedity')?></p>
    <table class="form-table"><tbody>
        <tr valign="top">
            <th scope="row"><label><?php _e('Responsive:','zedity')?></label></th>
            <td>
                <input type="radio" id="rbResponsiveNo" name="<?php echo $settings?>[responsive]" value="0" <?php echo $options['responsive']==0?'checked="checked"':'' ?> /><label for="rbResponsiveNo"> <?php _e('No','zedity')?></label><br/>
                <input type="radio" id="rbResponsiveScaling" name="<?php echo $settings?>[responsive]" value="1" <?php echo $options['responsive']==1?'checked="checked"':'' ?> /><label for="rbResponsiveScaling"> <?php _e('Scaling','zedity')?></label><br/>
                <input type="radio" id="rbResponsiveLayout" name="<?php echo $settings?>[responsive]" value="2" <?php echo $options['responsive']==2?'checked="checked"':'' ?> /><label for="rbResponsiveLayout"> <?php _e('Multiple layout','zedity')?></label><br/>
            </td>
        </tr>
    </tbody></table>
    <hr/>

    <h3 class="title"><?php _e('Snap boxes','zedity')?></h3>
    <p><?php _e('Snap boxes while arranging them with mouse drag (you can also change the setting while editing, from the menu "Edit->Snap boxes to"):','zedity')?></p>
    <table class="form-table"><tbody>
        <tr valign="top">
            <th scope="row"><label><?php _e('Snap:','zedity')?></label></th>
            <td>
                <input type="checkbox" id="cbSnapToPage" name="<?php echo $settings?>[snap_to_page]" value="1" <?php echo $options['snap_to_page']?'checked="checked"':'' ?> /><label for="cbSnapToPage"> <?php _e('Snap boxes to page.','zedity')?></label><br/>
                <input type="checkbox" id="cbSnapToBoxes" name="<?php echo $settings?>[snap_to_boxes]" value="1" <?php echo $options['snap_to_boxes']?'checked="checked"':'' ?> /><label for="cbSnapToBoxes"> <?php _e('Snap boxes to boxes.','zedity')?></label><br/>
                <input type="checkbox" id="cbSnapToGrid" name="<?php echo $settings?>[snap_to_grid]" value="1" <?php echo $options['snap_to_grid']?'checked="checked"':'' ?> /><label for="cbSnapToGrid"> <?php _e('Snap boxes to grid','zedity')?></label>
                    (<?php _e('Default grid size, width:','zedity')?>
                    <input id="zedity_grid_width" name="<?php echo $settings?>[grid_width]" size="5" maxlength="5" type="text" value="<?php echo $options['grid_width']?>" />,
                    <?php _e('height:','zedity')?>
                    <input id="zedity_grid_height" name="<?php echo $settings?>[grid_height]" size="5" maxlength="5" type="text" value="<?php echo $options['grid_height']?>" />).
            </td>
        </tr>
    </tbody></table>

    <?php
}

public function additional_editor_js($options){
    ?>
    <script type="text/javascript">
    var old_responsive = 0;
    zedityEditor.menu.add({
        tabs: {
            content: {
                groups: {
                    options: {
                        features: {
                            responsivepremiumlabel: {
                                type: 'smallpanel',
                                order: 100,
                                build: function($panel){
                                    $panel.css('margin','0 0 10px 5px').append('<span> <?php echo addslashes(__('Responsive:','zedity'))?></span>');
                                }
                            },
                            responsivepremium: {
                                type: 'menu',
                                width: 130,
                                order: 100,
                                items: [{
                                    value: 0,
                                    label: '<?php echo addslashes(__('No','zedity'))?>'
                                },{
                                    value: 1,
                                    label: '<?php echo addslashes(__('Scaling','zedity'))?>'
                                },{
                                    value: 2,
                                    label: '<?php echo addslashes(__('Multiple layout','zedity'))?>'
                                }],
                                onclick: function(val,e,ed,feat){
                                    old_responsive = content.responsive;
                                    content.responsive = val;
                                    if (val==2 && ed.responsive) {
                                        ed.responsive.start();
                                    } else if (ed.$this.hasClass('zedity-responsive-layout') && ed.responsive) {
                                        ed.responsive.revert();
                                        if (ed.$this.hasClass('zedity-responsive-layout')) {
                                            content.responsive = old_responsive;
                                        }
                                    }
                                    content.needsPublish = true;
                                    ed.menu.refresh('content','options','responsivepremium');
                                },
                                refresh: function(ed){
                                    this.$menu.val(content.responsive).selectmenu('refresh');
                                }
                            }
                        }
                    }
                }
            }
        },
        onadd: function(ed){
            //hide unsupported functions
            ed.menu._feature('content','options','responsivefreelabel').show = function(){return false};
            ed.menu._feature('content','options','responsivefree').show = function(){return false};
        }
    });

    //check for shortcodes in HTML box
    $(document).on('dialogcreate','.zedity-dialog-html',function(event,ui){
        $(this).parent().find('.zedity-button-ok').on('click.zedity',function(){
            var box = zedityEditor.boxes.selected();
            if (box) {
                var content = box.content();
                if (/\[[^\]]+\]/.test(content)) {
                    alert('<?php echo addslashes(__('It looks like you put some shortcodes in the box. If so, please make sure to save your content in Standard mode.','zedity'))?>');
                }
            }
        });
    });

    //update insert image dialog to keep track of images seleced from Media Library
    $(document).on('dialogcreate','.zedity-dialog-image',function(event,ui){
        var $dialog = $(this);
        var $parent = $dialog.parent();

        //insert image (OK button)
        $parent.find('.zedity-button-ok').on('click.zedity-premium',function(){
            var box = $dialog.data('box');
            var fileml = $dialog.data('fileml') || box._data.fileml;
            //if image was selected from ML, then automatically add link to the image
            if ($dialog.attr('data-ml')=='yes') {
                box.$this.addClass('zedity-wpml').attr('data-href',fileml.sizes.full.url);
                box._data.fileml = fileml;
                box._data.fileml.selected = $('#zedity-ddThumbML').val() || box._data.fileml.selected;
            } else {
                box.$this.removeClass('zedity-wpml');
                box._data.fileml = null;
            }
            $dialog.removeAttr('data-ml');
        });
        //don't insert image (Cancel button)
        $parent.find('zedity-button-cancel').on('click.zedity-premium',function(){
            $dialog.removeAttr('data-ml');
        });

        //add dropdown to choose which image size
        $('#tab-image-link').prepend(
            '<div id="zedity-pnlThumbML">'+
            '<?php echo addslashes(__('Select size format from Media Library:','zedity'))?><br/>'+
            '<select id="zedity-ddThumbML" style="width:170px">'+
                '<option value="full"><?php echo addslashes(__('Full size','zedity'))?></option>'+
                '<option value="large"><?php echo addslashes(__('Large','zedity'))?></option>'+
                '<option value="medium"><?php echo addslashes(__('Medium','zedity'))?></option>'+
                '<option value="thumbnail"><?php echo addslashes(__('Thumbnail','zedity'))?></option>'+
            '</select>'+
            '</div><br/>'
        );
        //select image size from dropdown
        $('#zedity-ddThumbML').on('change.zedity',function(){
            var box = $dialog.data('box');
            if (box) {
                //mark box as from ML
                box.$this.addClass('zedity-wpml');
                var fileml = $dialog.data('fileml') || box._data.fileml;
                if (fileml && fileml.sizes.thumbnail) {
                    //set image link to desired image size
                    $dialog.find('#zedity-txtImageLink').val(fileml.sizes[$('#zedity-ddThumbML').val()].url);
                }
            }
        });
        //change image url manually
        $('#zedity-txtImageLink').on('change.zedity-premium',function(){
            var box = $dialog.data('box');
            if (box) box.$this.removeClass('zedity-wpml');
        });
    });

    //on dialog open, show size selection dropdown if image is from ML
    $(document).on('dialogopen','.zedity-dialog-image',function(){
        $('#zedity-pnlThumbML').hide();
        var $this = $(this);
        var box = $this.data('box');
        if (box && box._data.fileml) {
            $this.attr('data-ml','yes').data('fileml',box._data.fileml);
            if (box._data.fileml.sizes.thumbnail) {
                $('#zedity-pnlThumbML').show()
                    .find('#zedity-ddThumbML').val(box._data.fileml.selected).focus();
            }
        }
    });

    $(document).on('dialogclose','.zedity-dialog-responsive',function(event,ui){
        //on dialog close, refresh editor
        content.responsive = zedityEditor.responsive.current ? 2 : old_responsive;
    });

    //on opening ML
    $(document).on('click.zedity-premium','.zedity-dialog-image .zedity-open-ML',function(){
        if (!zedity_ML_frame_image.mllink) {
            //on selecting an image from ML
            zedity_ML_frame_image.on('select',function(){
                //image was selected from ML
                var file = zedity_ML_frame_image.state().get('selection').first().toJSON();
                $('.zedity-dialog-image').attr('data-ml','yes').data('fileml',file);
                $('#zedity-pnlThumbML').show();
                var $dd = $('#zedity-ddThumbML');
                //disable unavailable thumbnails
                $dd.find('option').prop('disabled',true);
                for (var i in file.sizes) {
                    $dd.find('option[value='+i+']').prop('disabled',false);
                }
                $dd.val('full').focus();
            });
            zedity_ML_frame_image.mllink = true;
        }
    });

    (function(){
        //wrap images in anchors and remove link
        var old_save = content.save;
        content.save = function(){
            if (this.savemode==2) {
                //get images from ML
                zedityEditor.$this.find('.zedity-box-Image.zedity-wpml').each(function(idx,elem){
                    var $elem = $(elem);
                    var box = $elem.box();
                    //if box links to full image, make it WP style
                    if (box._data.fileml && box._data.fileml.sizes.full.url==$elem.attr('data-href')) {
                        $elem.find('img').wrap('<a href="'+box._data.fileml.sizes.full.url+'" target="'+($elem.attr('data-target')||'')+'" style="display:inline-block;width:100%;height:100%"/>');
                        $elem.removeAttr('data-href data-target');
                    } else {
                        $elem.removeClass('zedity-wpml');
                    }
                });
                //other images
                zedityEditor.$this.find('.zedity-box-Image:not(.zedity-wpml)').each(function(idx,elem){
                    var $elem = $(elem);
                    if ($elem.attr('data-href')) {
                        $elem.find('img').wrap('<a href="'+$elem.attr('data-href')+'" target="'+($elem.attr('data-target')||'')+'" style="display:inline-block;width:100%;height:100%"/>');
                        $elem.removeAttr('data-href data-target');
                    }
                });
            }
            zedityEditor._data.addClass = 'zedity-premium';
            old_save.call(this);
        };

        //update Image box to keep ML status on load
        //save old state
        var old_prototype = Zedity.Box.Image.prototype;
        var old_constructor = Zedity.Box.Image;
        var old_props = {};
        for (var i in Zedity.Box.Image) if (Zedity.Box.Image.hasOwnProperty(i)) old_props[i] = Zedity.Box.Image[i];
        //update constructor
        Zedity.Box.Image = function(){
            old_constructor.apply(this,arguments);
            if (this.$this.hasClass('zedity-wpml')) {
                //check if link is an accepted image, if not use the img src
                var accepted = $.map(Object.keys(Zedity.utils.fileTypes.types),function(key){
                    return Zedity.utils.fileTypes.types[key].mime;
                }).join(' ').indexOf((this.$this.attr('data-href')||'').split('.').pop())>-1;
                this._data.fileml = { sizes: { full: {
                    url: (accepted ? this.$this.attr('data-href') : null) || this.$this.find('img').attr('src')
                }}};
            }
        };
        //restore state
        Zedity.Box.Image.prototype = old_prototype;
        for (var i in old_props) if (old_props.hasOwnProperty(i)) Zedity.Box.Image[i] = old_props[i];

        //update responsive revert message
        var old_revert = Zedity.Responsive.prototype.revert;
        Zedity.Responsive.prototype.revert = function(){
            if (this.current) {
                var m1 = Zedity.t('<?php echo addslashes(__('By doing so the "%s" layout will be kept','zedity'))?>',this._options.layouts[this.current].short);
                var m2 = '<?php echo addslashes(__('and responsive scaling will be applied to it.','zedity'))?>';
                var m3 = '<?php echo addslashes(__('The other layouts will get discarded (and lost).','zedity'))?>';
                var val = zedityEditor.menu._feature('content','options','responsivepremium').$menu.val();
                if (val==0) {
                    this._options.revertmessage = m1 + '. ' + m3;
                } else if (val==1) {
                    this._options.revertmessage = m1 + ' ' + m2 + ' ' + m3;
                }
            }
            return old_revert.apply(this,arguments);
        };
    })();

    var zedity_ML_frame_video = null;
    $(document).on('dialogcreate','.zedity-dialog-video',function(event,ui){
        if (zedity_ML_frame_video) return;

        //add new tab for media library
        var $tabs = $('.zedity-dialog-video .tabs');
        $tabs.find('ul').prepend('<li><a href="#tab-video-ML"><?php echo addslashes(__('Media Library','zedity'))?></a></li>');
        $tabs.append(
            '<div id="tab-video-ML">'+
            '<p><?php echo addslashes(__('Insert a video from the WordPress Media Library.','zedity'))?></p>'+
            '<p><?php echo addslashes(__('You can choose among the videos you already have in your library, or upload a new one.','zedity'))?></p>'+
            '<p><?php echo addslashes(__('You can select multiple video sources (different encodings of the same video) and a picture as thumbnail.','zedity'))?></p>'+
            '<button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only zedity-open-ML"><span class="ui-button-text"><?php echo addslashes(__('Open Media Library...','zedity'))?></span></button>'+
            '</div>'
        );
        $tabs.tabs('refresh');
        $tabs.tabs('selected','tab-video-ML');
        $tabs.find('.zedity-open-ML').on('click.zedity',function(){
            zedity_ML_frame_video.open();
        });

        //create media library frame
        zedity_ML_frame_video = parent.wp.media.frames.zedity_media_frame_video = parent.wp.media({
            className: 'media-frame zedity-media-frame-video',
            title: jQuery(this).data('uploader_title'),
            button: {
                text: jQuery(this).data('uploader_button_text'),
            },
            library: {
                type: ['video','image']
            },
            multiple: true
        });
        zedity_ML_frame_video.on('select', function(){
            var $dialog = $('.zedity-dialog-video');
            var urls = [];
            var selection = zedity_ML_frame_video.state().get('selection');
            selection.map(function(file){
                file = file.toJSON();
                if (file.url) urls.push(file.url);
            });
            $dialog.find('.tabs').tabs('selected','tab-video-embed');
            $dialog.find('#zedity-txtVideoEmbed').val(urls.join('\n'));
        });
    });

    var zedity_ML_frame_audio = null;
    $(document).on('dialogcreate','.zedity-dialog-audio',function(event,ui){
        if (zedity_ML_frame_audio) return;

        //add new tab for media library
        var $tabs = $('.zedity-dialog-audio .tabs');
        $tabs.find('ul').prepend('<li><a href="#tab-audio-ML"><?php echo addslashes(__('Media Library','zedity'))?></a></li>');
        $tabs.append(
            '<div id="tab-audio-ML">'+
            '<p><?php echo addslashes(__('Insert an audio from the WordPress Media Library.','zedity'))?></p>'+
            '<p><?php echo addslashes(__('You can choose among the audios you already have in your library, or upload a new one.','zedity'))?></p>'+
            '<button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only zedity-open-ML"><span class="ui-button-text"><?php echo addslashes(__('Open Media Library...','zedity'))?></span></button>'+
            '</div>'
        );
        $tabs.tabs('refresh');
        $tabs.tabs('selected','tab-audio-ML');
        $tabs.find('.zedity-open-ML').on('click.zedity',function(){
            zedity_ML_frame_audio.open();
        });

        //create media library frame
        zedity_ML_frame_audio = parent.wp.media.frames.zedity_media_frame_audio = parent.wp.media({
            className: 'media-frame zedity-media-frame-audio',
            title: jQuery(this).data('uploader_title'),
            button: {
                text: jQuery(this).data('uploader_button_text'),
            },
            library: {
                type: 'audio'
            },
            multiple: true
        });
        zedity_ML_frame_audio.on('select', function(){
            var $dialog = $('.zedity-dialog-audio');
            var urls = [];
            var selection = zedity_ML_frame_audio.state().get('selection');
            selection.map(function(file){
                file = file.toJSON();
                if (file.url) urls.push(file.url);
            });
            $dialog.find('.tabs').tabs('selected','tab-audio-embed');
            $dialog.find('#zedity-txtAudioEmbed').val(urls.join('\n'));
        });
    });

    </script>
    <?php
}

public function additional_template_js(){
}


//--------------------------------------------------------------------------------

public function get_font_sizes(){
    return array('4','6','8','10','12','14','15','16','18','20','22','24','26','28','30','32','36','40','46','52','58','64','72','80','90','100','120','140','160','180','200','260','340');
}

public function get_webfonts() {
    $webfonts = parent::get_webfonts();

    $webfonts = array_unique(array_merge($webfonts, array(
        'Astloch,cursive',
        'Asul,serif',
        'Atomic Age,cursive',
        'Averia Serif Libre,serif',
        'Bad Script,cursive',
        'Baumans,sans-serif',
        'Berkshire Swash,cursive',
        'Bevan,serif',
        'Bitter,serif',
        'Bowlby One SC,sans-serif',
        'Cabin,sans-serif',
        'Carme,sans-serif',
        'Cherry Cream Soda,sans-serif',
        'Cinzel Decorative,serif',
        'Coda,sans-serif',
        'Codystar,cursive',
        'Comfortaa,sans-serif',
        'Coming Soon,cursive',
        'Crete Round,serif',
        'Crushed,cursive',
        'Della Respira,serif',
        'Devonshire,cursive',
        'Didact Gothic,sans-serif',
        'Eagle Lake,serif',
        'Elsie,serif',
        'Emblema One,cursive',
        'Expletus Sans,sans-serif',
        'Fauna One,serif',
        'Federant,cursive',
        'Fredericka the Great,cursive',
        'Fenix,serif',
        'Flavors,cursive',
        'Fredoka One,cursive',
        'Gentium Basic,sans-serif',
        'Geo,serif',
        'Geostar,cursive',
        'Germania One,serif',
        'Glass Antiqua,serif',
        'Goblin One,serif',
        'Gochi Hand,cursive',
        'Graduate,cursive',
        'Grand Hotel,cursive',
        'Gruppo,sans-serif',
        'Handlee,cursive',
        'Happy Monkey,cursive',
        'Holtwood One SC,serif',
        'IM Fell English,serif',
        'Jim Nightshade,cursive',
        'Josefin Slab,sans-serif',
        'Kavoon,cursive',
        'Keania One,cursive',
        'Knewave,cursive',
        'Limelight,serif',
        'Lobster,cursive',
        'Lusitana,serif',
        'Lustria,serif',
        'Macondo,cursive',
        'Marcellus SC,sans-serif',
        'MedievalSharp,cursive',
        'Milonga,serif',
        'Miltonian,cursive',
        'Miltonian Tattoo,cursive',
        'Monoton,cursive',
        'Mouse Memoirs,sans-serif',
        'Muli,sans-serif',
        'Nixie One,serif',
        'Nova Mono,sans-serif',
        'Nova Script,cursive',
        'Orbitron,sans-serif',
        'Original Surfer,serif',
        'Ovo,serif',
        'Oxygen,sans-serif',
        'Pinyon Script,cursive',
        'Playball,cursive',
        'Playfair Display,serif',
        'Poly,serif',
        'Port Lligat Slab,serif',
        'PT Sans Narrow,sans-serif',
        'Quattrocento,serif',
        'Quattrocento Sans,sans-serif',
        'Quicksand,sans-serif',
        'Raleway,sans-serif',
        'Revalia,cursive',
        'Risque,serif',
        'Roboto,sans-serif',
        'Roboto Slab,serif',
        'Rosario,sans-serif',
        'Ruslan Display,cursive',
        'Salsa,cursive',
        'Sancreek,cursive',
        'Shadows Into Light,cursive',
        'Shanti,sans-serif',
        'Syncopate,cursive',
        'Six Caps,sans-serif',
        'Smythe,cursive',
        'Smokum,serif',
        'Sonsie One,cursive',
        'Stoke,serif',
        'Supermercado One,cursive',
        'Tangerine,cursive',
        'Trocchi,serif',
        'Trochut,serif',
        'UnifrakturMaguntia,cursive',
        'Unkempt,cursive',
        'Varela,sans-serif',
        'VT323,cursive',
        'Yellowtail,cursive',
    )));
    asort($webfonts);

    return $webfonts;
}

public function get_videoembeds() {
    $vembeds = parent::get_videoembeds();
    return array_unique(array_merge($vembeds, array(
        'dailymotion' => 'http://www.dailymotion.com',
        'metacafe' => 'http://www.metacafe.com',
        'ustream' => 'http://www.ustream.tv',
        'myspace_video' => 'https://myspace.com/discover/videos',
        'veoh' => 'http://www.veoh.com',
        'metatube' => 'http://www.metatube.com',
        'vine' => 'http://vine.co',
        'snotr' => 'http://www.snotr.com',
        'bliptv' => 'http://blip.tv',
        '5min' => 'http://www.5minmedia.com/VideoLibrary/',
        'tunepk' => 'http://tune.pk/',
        'coub' => 'http://coub.com/',
    )));
}

public function get_audioembeds() {
    $aembeds = parent::get_audioembeds();
    return array_unique(array_merge($aembeds, array(
        'vocaroo' => 'http://vocaroo.com',
        'myspace_music' => 'https://myspace.com/discover/songs',
        'shoutcast' => 'http://www.shoutcast.com',
        'bandcamp' => 'http://bandcamp.com',
    )));
}

}