qsdklsqkdmqskdmlqskd azoepqikdomlqskdjmlqs qpfklqjsfmklqsjdmqlsjdsqd PKH\ .admin.phpnu[PKH\2unnaioseop_module_class.phpnu[strpos( $name, 'display_settings_page_' ) === 0 ) { return $this->display_settings_page( $this->substr( $name, 22 ) ); } $error = sprintf( __( "Method %s doesn't exist", 'all-in-one-seo-pack' ), $name ); if ( class_exists( 'BadMethodCallException' ) ) { throw new BadMethodCallException( $error ); } throw new Exception( $error ); } /** * All_in_One_SEO_Pack_Module constructor. */ function __construct() { if ( empty( $this->file ) ) { $this->file = __FILE__; } $this->plugin_name = AIOSEOP_PLUGIN_NAME; $this->plugin_path = array(); // $this->plugin_path['dir'] = plugin_dir_path( $this->file ); $this->plugin_path['basename'] = plugin_basename( $this->file ); $this->plugin_path['dirname'] = dirname( $this->plugin_path['basename'] ); $this->plugin_path['url'] = plugin_dir_url( $this->file ); $this->plugin_path['images_url'] = $this->plugin_path['url'] . 'images'; $this->script_data['plugin_path'] = $this->plugin_path; } /** * Get options for module, stored individually or together. */ function get_class_option() { $option_name = $this->get_option_name(); if ( $this->store_option || $option_name == $this->parent_option ) { return get_option( $option_name ); } else { $option = get_option( $this->parent_option ); if ( isset( $option['modules'] ) && isset( $option['modules'][ $option_name ] ) ) { return $option['modules'][ $option_name ]; } } return false; } /** * Update options for module, stored individually or together. * * @param $option_data * @param bool $option_name * * @return bool */ function update_class_option( $option_data, $option_name = false ) { if ( false == $option_name ) { $option_name = $this->get_option_name(); } if ( $this->store_option || $option_name == $this->parent_option ) { return update_option( $option_name, $option_data ); } else { $option = get_option( $this->parent_option ); if ( ! isset( $option['modules'] ) ) { $option['modules'] = array(); } $option['modules'][ $option_name ] = $option_data; return update_option( $this->parent_option, $option ); } } /** * Delete options for module, stored individually or together. * * @param bool $delete * * @return bool */ function delete_class_option( $delete = false ) { $option_name = $this->get_option_name(); if ( $this->store_option || $delete ) { delete_option( $option_name ); } else { $option = get_option( $this->parent_option ); if ( isset( $option['modules'] ) && isset( $option['modules'][ $option_name ] ) ) { unset( $option['modules'][ $option_name ] ); return update_option( $this->parent_option, $option ); } } return false; } /** * Get the option name with prefix. */ function get_option_name() { if ( ! isset( $this->option_name ) || empty( $this->option_name ) ) { $this->option_name = $this->prefix . 'options'; } return $this->option_name; } /** * Convenience function to see if an option is set. * * @param string $option * * @param null $location * * @return bool */ function option_isset( $option, $location = null ) { $prefix = $this->get_prefix( $location ); $opt = $prefix . $option; return ( isset( $this->options[ $opt ] ) && $this->options[ $opt ] ); } /** * Case conversion; handle non UTF-8 encodings and fallback ** * * @param $str * @param string $mode * * @return string */ function convert_case( $str, $mode = 'upper' ) { static $charset = null; if ( null == $charset ) { $charset = get_bloginfo( 'charset' ); } $str = (string) $str; if ( 'title' == $mode ) { if ( function_exists( 'mb_convert_case' ) ) { return mb_convert_case( $str, MB_CASE_TITLE, $charset ); } else { return ucwords( $str ); } } if ( 'UTF-8' == $charset ) { // phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase global $UTF8_TABLES; include_once( AIOSEOP_PLUGIN_DIR . 'inc/aioseop_UTF8.php' ); if ( is_array( $UTF8_TABLES ) ) { if ( 'upper' == $mode ) { return strtr( $str, $UTF8_TABLES['strtoupper'] ); } if ( 'lower' == $mode ) { return strtr( $str, $UTF8_TABLES['strtolower'] ); } } // phpcs:enable } if ( 'upper' == $mode ) { if ( function_exists( 'mb_strtoupper' ) ) { return mb_strtoupper( $str, $charset ); } else { return strtoupper( $str ); } } if ( 'lower' == $mode ) { if ( function_exists( 'mb_strtolower' ) ) { return mb_strtolower( $str, $charset ); } else { return strtolower( $str ); } } return $str; } /** * Convert a string to lower case * Compatible with mb_strtolower(), an UTF-8 friendly replacement for strtolower() * * @param $str * * @return string */ function strtolower( $str ) { return $this->convert_case( $str, 'lower' ); } /** * Convert a string to upper case * Compatible with mb_strtoupper(), an UTF-8 friendly replacement for strtoupper() * * @param $str * * @return string */ function strtoupper( $str ) { return $this->convert_case( $str, 'upper' ); } /** * Convert a string to title case * Compatible with mb_convert_case(), an UTF-8 friendly replacement for ucwords() * * @param $str * * @return string */ function ucwords( $str ) { return $this->convert_case( $str, 'title' ); } /** * Wrapper for strlen() - uses mb_strlen() if possible. * * @param $string * * @return int */ function strlen( $string ) { if ( function_exists( 'mb_strlen' ) ) { return mb_strlen( $string, 'UTF-8' ); } return strlen( $string ); } /** * Wrapper for substr() - uses mb_substr() if possible. * * @param $string * @param int $start * @param int $length * * @return mixed */ function substr( $string, $start = 0, $length = 2147483647 ) { $args = func_get_args(); if ( function_exists( 'mb_substr' ) ) { return call_user_func_array( 'mb_substr', $args ); } return call_user_func_array( 'substr', $args ); } /** * Wrapper for strpos() - uses mb_strpos() if possible. * * @param $haystack * @param string $needle * * @param int $offset * * @return bool|int */ function strpos( $haystack, $needle, $offset = 0 ) { if ( function_exists( 'mb_strpos' ) ) { return mb_strpos( $haystack, $needle, $offset, 'UTF-8' ); } return strpos( $haystack, $needle, $offset ); } /** * Wrapper for strrpos() - uses mb_strrpos() if possible. * * @param $haystack * @param string $needle * * @param int $offset * * @return bool|int */ function strrpos( $haystack, $needle, $offset = 0 ) { if ( function_exists( 'mb_strrpos' ) ) { return mb_strrpos( $haystack, $needle, $offset, 'UTF-8' ); } return strrpos( $haystack, $needle, $offset ); } /** * Convert html string to php array - useful to get a serializable value. * * @param string $xmlstr * * @return array */ function html_string_to_array( $htmlstr ) { if ( ! class_exists( 'DOMDocument' ) ) { return array(); } else { $doc = new DOMDocument(); $doc->loadXML( $htmlstr ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase return $this->domnode_to_array( $doc->documentElement ); } } /** * DOM Node to Array * * @since ? * * @param DOMElement $node * @return array|string */ function domnode_to_array( $node ) { // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase switch ( $node->nodeType ) { case XML_CDATA_SECTION_NODE: case XML_TEXT_NODE: return trim( $node->textContent ); break; case XML_ELEMENT_NODE: $output = array(); for ( $i = 0, $m = $node->childNodes->length; $i < $m; $i ++ ) { $child = $node->childNodes->item( $i ); $v = $this->domnode_to_array( $child ); if ( isset( $child->tagName ) ) { $t = $child->tagName; if ( ! isset( $output[ $t ] ) ) { $output[ $t ] = array(); } if ( is_array( $output ) ) { $output[ $t ][] = $v; } } elseif ( $v || '0' === $v ) { $output = (string) $v; } } // Has attributes but isn't an array. if ( $node->attributes->length && ! is_array( $output ) ) { $output = array( '@content' => $output ); } //Change output into an array. if ( is_array( $output ) ) { if ( $node->attributes->length ) { $a = array(); foreach ( $node->attributes as $attr_name => $attr_node ) { $a[ $attr_name ] = (string) $attr_node->value; } $output['@attributes'] = $a; } foreach ( $output as $t => $v ) { if ( is_array( $v ) && 1 == count( $v ) && '@attributes' != $t ) { $output[ $t ] = $v[0]; } } } } // phpcs:enable if ( empty( $output ) ) { return ''; } return $output; } /** * Apply Custom Fields * * Adds support for using %cf_(name of field)% for using * custom fields / Advanced Custom Fields in titles / descriptions etc. ** * * @since ? * * @param $format * @return mixed */ function apply_cf_fields( $format ) { return preg_replace_callback( '/%cf_([^%]*?)%/', array( $this, 'cf_field_replace' ), $format ); } /** * (ACF) Custom Field Replace * * @since ? * * @param $matches * @return bool|mixed|string */ function cf_field_replace( $matches ) { $result = ''; if ( ! empty( $matches ) ) { if ( ! empty( $matches[1] ) ) { if ( function_exists( 'get_field' ) ) { $result = get_field( $matches[1] ); } if ( empty( $result ) ) { global $post; if ( ! empty( $post ) ) { $result = get_post_meta( $post->ID, $matches[1], true ); } } } else { $result = $matches[0]; } } $result = strip_tags( $result ); return $result; } /** * Returns child blogs of parent in a multisite. */ function get_child_blogs() { global $wpdb, $blog_id; $site_id = $wpdb->siteid; if ( is_multisite() ) { if ( $site_id != $blog_id ) { return false; } // @codingStandardsIgnoreStart return $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = %d AND site_id != blog_id", $blog_id ) ); // @codingStandardsIgnoreEnd } return false; } /** * Is AIOSEOP Active Blog * * Checks if the plugin is active on a given blog by blogid on a multisite. * * @since ? * * @param bool $bid * @return bool */ function is_aioseop_active_on_blog( $bid = false ) { global $blog_id; if ( empty( $bid ) || ( $bid == $blog_id ) || ! is_multisite() ) { return true; } if ( ! function_exists( 'is_plugin_active_for_network' ) ) { require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); } if ( is_plugin_active_for_network( AIOSEOP_PLUGIN_BASENAME ) ) { return true; } return in_array( AIOSEOP_PLUGIN_BASENAME, (array) get_blog_option( $bid, 'active_plugins', array() ) ); } /** * Quote List for Regex * * @since ? * * @param $list * @param string $quote * @return string */ function quote_list_for_regex( $list, $quote = '/' ) { $regex = ''; $cont = 0; foreach ( $list as $l ) { $trim_l = trim( $l ); if ( ! empty( $trim_l ) ) { if ( $cont ) { $regex .= '|'; } $cont = 1; $regex .= preg_quote( trim( $l ), $quote ); } } return $regex; } /** * Is Good Bot * * @see Original code, thanks to Sean M. Brown. * @link http://smbrown.wordpress.com/2009/04/29/verify-googlebot-forward-reverse-dns/ * * @return bool */ function is_good_bot() { $botlist = array( 'Yahoo! Slurp' => 'crawl.yahoo.net', 'googlebot' => '.googlebot.com', 'msnbot' => 'search.msn.com', ); $botlist = apply_filters( $this->prefix . 'botlist', $botlist ); if ( ! empty( $botlist ) ) { if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) { return false; } $ua = $_SERVER['HTTP_USER_AGENT']; $uas = $this->quote_list_for_regex( $botlist ); if ( preg_match( '/' . $uas . '/i', $ua ) ) { $ip = $_SERVER['REMOTE_ADDR']; $hostname = gethostbyaddr( $ip ); $ip_by_hostname = gethostbyname( $hostname ); if ( $ip_by_hostname == $ip ) { $hosts = array_values( $botlist ); foreach ( $hosts as $k => $h ) { $hosts[ $k ] = preg_quote( $h ) . '$'; } $hosts = join( '|', $hosts ); if ( preg_match( '/' . $hosts . '/i', $hostname ) ) { return true; } } } return false; } } /** * Default Bad Bots * * @since ? * * @return array */ function default_bad_bots() { $botlist = array( 'Abonti', 'aggregator', 'AhrefsBot', 'asterias', 'BDCbot', 'BLEXBot', 'BuiltBotTough', 'Bullseye', 'BunnySlippers', 'ca-crawler', 'CCBot', 'Cegbfeieh', 'CheeseBot', 'CherryPicker', 'CopyRightCheck', 'cosmos', 'Crescent', 'discobot', 'DittoSpyder', 'DotBot', 'Download Ninja', 'EasouSpider', 'EmailCollector', 'EmailSiphon', 'EmailWolf', 'EroCrawler', 'ExtractorPro', 'Fasterfox', 'FeedBooster', 'Foobot', 'Genieo', 'grub-client', 'Harvest', 'hloader', 'httplib', 'HTTrack', 'humanlinks', 'ieautodiscovery', 'InfoNaviRobot', 'IstellaBot', 'Java/1.', 'JennyBot', 'k2spider', 'Kenjin Spider', 'Keyword Density/0.9', 'larbin', 'LexiBot', 'libWeb', 'libwww', 'LinkextractorPro', 'linko', 'LinkScan/8.1a Unix', 'LinkWalker', 'LNSpiderguy', 'lwp-trivial', 'magpie', 'Mata Hari', 'MaxPointCrawler', 'MegaIndex', 'Microsoft URL Control', 'MIIxpc', 'Mippin', 'Missigua Locator', 'Mister PiX', 'MJ12bot', 'moget', 'MSIECrawler', 'NetAnts', 'NICErsPRO', 'Niki-Bot', 'NPBot', 'Nutch', 'Offline Explorer', 'Openfind', 'panscient.com', 'PHP/5.{', 'ProPowerBot/2.14', 'ProWebWalker', 'Python-urllib', 'QueryN Metasearch', 'RepoMonkey', 'SISTRIX', 'sitecheck.Internetseer.com', 'SiteSnagger', 'SnapPreviewBot', 'Sogou', 'SpankBot', 'spanner', 'spbot', 'Spinn3r', 'suzuran', 'Szukacz/1.4', 'Teleport', 'Telesoft', 'The Intraformant', 'TheNomad', 'TightTwatBot', 'Titan', 'toCrawl/UrlDispatcher', 'True_Robot', 'turingos', 'TurnitinBot', 'UbiCrawler', 'UnisterBot', 'URLy Warning', 'VCI', 'WBSearchBot', 'Web Downloader/6.9', 'Web Image Collector', 'WebAuto', 'WebBandit', 'WebCopier', 'WebEnhancer', 'WebmasterWorldForumBot', 'WebReaper', 'WebSauger', 'Website Quester', 'Webster Pro', 'WebStripper', 'WebZip', 'Wotbox', 'wsr-agent', 'WWW-Collector-E', 'Xenu', 'Zao', 'Zeus', 'ZyBORG', 'coccoc', 'Incutio', 'lmspider', 'memoryBot', 'serf', 'Unknown', 'uptime files', ); return $botlist; } /** * Is Bad Bot * * @since ? * * @return bool */ function is_bad_bot() { $botlist = $this->default_bad_bots(); $botlist = apply_filters( $this->prefix . 'badbotlist', $botlist ); if ( ! empty( $botlist ) ) { if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) { return false; } $ua = $_SERVER['HTTP_USER_AGENT']; $uas = $this->quote_list_for_regex( $botlist ); if ( preg_match( '/' . $uas . '/i', $ua ) ) { return true; } } return false; } /** * Default Bad Referers * * @since ? * * @return array */ function default_bad_referers() { $referlist = array( 'semalt.com', 'kambasoft.com', 'savetubevideo.com', 'buttons-for-website.com', 'sharebutton.net', 'soundfrost.org', 'srecorder.com', 'softomix.com', 'softomix.net', 'myprintscreen.com', 'joinandplay.me', 'fbfreegifts.com', 'openmediasoft.com', 'zazagames.org', 'extener.org', 'openfrost.com', 'openfrost.net', 'googlsucks.com', 'best-seo-offer.com', 'buttons-for-your-website.com', 'www.Get-Free-Traffic-Now.com', 'best-seo-solution.com', 'buy-cheap-online.info', 'site3.free-share-buttons.com', 'webmaster-traffic.com', ); return $referlist; } /** * Is Bad Referer * * @since ? * * @return bool */ function is_bad_referer() { $referlist = $this->default_bad_referers(); $referlist = apply_filters( $this->prefix . 'badreferlist', $referlist ); if ( ! empty( $referlist ) && ! empty( $_SERVER ) && ! empty( $_SERVER['HTTP_REFERER'] ) ) { $ref = $_SERVER['HTTP_REFERER']; $regex = $this->quote_list_for_regex( $referlist ); if ( preg_match( '/' . $regex . '/i', $ref ) ) { return true; } } return false; } /** * Allow Bot * * @since ? * * @return mixed|void */ function allow_bot() { $allow_bot = true; if ( ( ! $this->is_good_bot() ) && $this->is_bad_bot() && ! is_user_logged_in() ) { $allow_bot = false; } return apply_filters( $this->prefix . 'allow_bot', $allow_bot ); } /** * Displays tabs for tabbed locations on a settings page. * * @since ? * * @param $location */ function display_tabs( $location ) { if ( ( null != $location ) && isset( $locations[ $location ]['tabs'] ) ) { // TODO Fix undefined variable. $tabs = $locations['location']['tabs']; } else { $tabs = $this->tabs; } if ( ! empty( $tabs ) ) { ?>
label ) ) { $post_types[ $p ] = $post_objs[ $p ]->label; } else { $post_types[ $p ] = $p; } } return $post_types; } /** * Get Term Labels * * @since ? * * @param $post_objs * @return array */ function get_term_labels( $post_objs ) { $post_types = array(); foreach ( $post_objs as $p ) { if ( ! empty( $p->name ) ) { $post_types[ $p->term_id ] = $p->name; } } return $post_types; } /** * Get Post Type Titles * * @since ? * * @param array $args * @return array */ function get_post_type_titles( $args = array() ) { $object_labels = $this->get_object_labels( get_post_types( $args, 'objects' ) ); if ( isset( $object_labels['attachment'] ) ) { $object_labels['attachment'] = __( 'Media / Attachments', 'all-in-one-seo-pack' ); } return $object_labels; } /** * Get Taxonomy Titles * * @since ? * * @param array $args * @return array */ function get_taxonomy_titles( $args = array() ) { return $this->get_object_labels( get_taxonomies( $args, 'objects' ) ); } /** * Gets the category titles. * * @since 3.0 Changed function name from `get_category_titles` to `get_term_titles`. (#240) * @since 3.0 Changed `get_categories()` to `get_terms()` to fetch all (custom) terms. (#240) * * @see WP_Term_Query::__constructor() * @link https://developer.wordpress.org/reference/classes/wp_term_query/__construct/ * * @param array $args An array for arguments to query by. See WP_Term_Query::__constructor() for more info. * @return array */ function get_term_titles( $args = array() ) { return $this->get_term_labels( get_terms( $args ) ); } /** * Helper function for exporting settings on post data. * * @param string $prefix * @param array $query * * @return string */ function post_data_export( $prefix = '_aioseop', $query = array( 'posts_per_page' => - 1 ) ) { $buf = ''; $posts_query = new WP_Query( $query ); while ( $posts_query->have_posts() ) { $posts_query->the_post(); global $post; $guid = $post->guid; $type = $post->post_type; $title = $post->post_title; $date = $post->post_date; $data = ''; $post_custom_fields = get_post_custom( $post->ID ); $has_data = null; if ( is_array( $post_custom_fields ) ) { foreach ( $post_custom_fields as $field_name => $field ) { if ( ( $this->strpos( $field_name, $prefix ) === 0 ) && $field[0] ) { $has_data = true; $data .= $field_name . " = '" . $field[0] . "'\n"; } } } if ( ! empty( $data ) ) { $has_data = true; } if ( null != $has_data ) { $post_info = "\n[post_data]\n\n"; $post_info .= "post_title = '" . $title . "'\n"; $post_info .= "post_guid = '" . $guid . "'\n"; $post_info .= "post_date = '" . $date . "'\n"; $post_info .= "post_type = '" . $type . "'\n"; if ( $data ) { $buf .= $post_info . $data . "\n"; } } } wp_reset_postdata(); return $buf; } /** * Handles exporting settings data for a module. * * @since 2.4.13 Fixed bug on empty options. * * @param $buf * * @return string */ function settings_export( $buf ) { global $aiosp; $post_types = apply_filters( 'aioseop_export_settings_exporter_post_types', null ); $has_data = null; $general_settings = null; $exporter_choices = apply_filters( 'aioseop_export_settings_exporter_choices', '' ); if ( ! empty( $_REQUEST['aiosp_importer_exporter_export_choices'] ) ) { $exporter_choices = $_REQUEST['aiosp_importer_exporter_export_choices']; } if ( ! empty( $exporter_choices ) && is_array( $exporter_choices ) ) { foreach ( $exporter_choices as $ex ) { if ( 1 == $ex ) { $general_settings = true; } if ( 2 == $ex && isset( $_REQUEST['aiosp_importer_exporter_export_post_types'] ) ) { $post_types = $_REQUEST['aiosp_importer_exporter_export_post_types']; } } } if ( ( null != $post_types ) && ( $this === $aiosp ) ) { $buf .= $this->post_data_export( '_aioseop', array( 'posts_per_page' => - 1, 'post_type' => $post_types, 'post_status' => array( 'publish', 'pending', 'draft', 'future', 'private', 'inherit' ), ) ); } /* Add all active settings to settings file */ $name = $this->get_option_name(); $options = $this->get_class_option(); if ( ! empty( $options ) && null != $general_settings ) { $buf .= "\n[$name]\n\n"; foreach ( $options as $key => $value ) { if ( ( $name == $this->parent_option ) && ( 'modules' == $key ) ) { continue; } // don't re-export all module settings -- pdb if ( is_array( $value ) ) { $value = "'" . str_replace( array( "'", "\n", "\r" ), array( "\'", '\n', '\r', ), trim( serialize( $value ) ) ) . "'"; } else { $value = str_replace( array( "\n", "\r" ), array( '\n', '\r', ), trim( var_export( $value, true ) ) ); } $buf .= "$key = $value\n"; } } return $buf; } /** * Order for adding the menus for the aioseop_modules_add_menus hook. */ function menu_order() { return 10; } /** * Print a basic error message. * * @param $error * * @return bool */ function output_error( $error ) { $error = esc_html( $error ); echo "
$error
"; return false; } /** * * Backwards compatibility - see http://php.net/manual/en/function.str-getcsv.php * * @param $input * @param string $delimiter * @param string $enclosure * @param string $escape * * @return array */ function str_getcsv( $input, $delimiter = ',', $enclosure = '"', $escape = '\\' ) { $fp = fopen( 'php://memory', 'r+' ); fputs( $fp, $input ); rewind( $fp ); $data = fgetcsv( $fp, null, $delimiter, $enclosure ); // $escape only got added in 5.3.0 fclose( $fp ); return $data; } /** * * Helper function to convert csv in key/value pair format to an associative array. * * @param $csv * * @return array */ function csv_to_array( $csv ) { $args = array(); if ( version_compare( PHP_VERSION, '5.3', '>=' ) ) { $v = $this->str_getcsv( $csv ); } else { $v = str_getcsv( $csv ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.str_getcsvFound } $size = count( $v ); if ( is_array( $v ) && isset( $v[0] ) && $size >= 2 ) { for ( $i = 0; $i < $size; $i += 2 ) { $args[ $v[ $i ] ] = $v[ $i + 1 ]; } } return $args; } /** Allow modules to use WP Filesystem if available and desired, fall back to PHP filesystem access otherwise. * * @param string $method * @param bool $form_fields * @param string $url * @param bool $error * * @return bool */ function use_wp_filesystem( $method = '', $form_fields = false, $url = '', $error = false ) { if ( empty( $method ) ) { $this->credentials = request_filesystem_credentials( $url ); } else { $this->credentials = request_filesystem_credentials( $url, $method, $error, false, $form_fields ); } return $this->credentials; } /** * Wrapper function to get filesystem object. */ function get_filesystem_object() { $cred = get_transient( 'aioseop_fs_credentials' ); if ( ! empty( $cred ) ) { $this->credentials = $cred; } if ( function_exists( 'WP_Filesystem' ) && WP_Filesystem( $this->credentials ) ) { global $wp_filesystem; return $wp_filesystem; } else { require_once( ABSPATH . 'wp-admin/includes/template.php' ); require_once( ABSPATH . 'wp-admin/includes/screen.php' ); require_once( ABSPATH . 'wp-admin/includes/file.php' ); if ( ! WP_Filesystem( $this->credentials ) ) { $this->use_wp_filesystem(); } if ( ! empty( $this->credentials ) ) { set_transient( 'aioseop_fs_credentials', $this->credentials, 10800 ); } global $wp_filesystem; if ( is_object( $wp_filesystem ) ) { return $wp_filesystem; } } return false; } /** * See if a file exists using WP Filesystem. * * @param string $filename * * @return bool */ function file_exists( $filename ) { $wpfs = $this->get_filesystem_object(); if ( is_object( $wpfs ) ) { return $wpfs->exists( $filename ); } return $wpfs; } /** * See if the directory entry is a file using WP Filesystem. * * @param $filename * * @return bool */ function is_file( $filename ) { $wpfs = $this->get_filesystem_object(); if ( is_object( $wpfs ) ) { return $wpfs->is_file( $filename ); } return $wpfs; } /** * List files in a directory using WP Filesystem. * * @param $path * * @return array|bool */ function scandir( $path ) { $wpfs = $this->get_filesystem_object(); if ( is_object( $wpfs ) ) { $dirlist = $wpfs->dirlist( $path ); if ( empty( $dirlist ) ) { return $dirlist; } return array_keys( $dirlist ); } return $wpfs; } /** * Load a file through WP Filesystem; implement basic support for offset and maxlen. * * @param $filename * @param bool $use_include_path * @param null $context * @param int $offset * @param int $maxlen * * @return bool|mixed */ function load_file( $filename, $use_include_path = false, $context = null, $offset = - 1, $maxlen = - 1 ) { $wpfs = $this->get_filesystem_object(); if ( is_object( $wpfs ) ) { if ( ! $wpfs->exists( $filename ) ) { return false; } if ( ( $offset > 0 ) || ( $maxlen >= 0 ) ) { if ( 0 === $maxlen ) { return ''; } if ( 0 > $offset ) { $offset = 0; } $file = $wpfs->get_contents( $filename ); if ( ! is_string( $file ) || empty( $file ) ) { return $file; } if ( 0 > $maxlen ) { return $this->substr( $file, $offset ); } else { return $this->substr( $file, $offset, $maxlen ); } } else { return $wpfs->get_contents( $filename ); } } return false; } /** * Save a file through WP Filesystem. * * @param string $filename * * @param $contents * * @return bool */ function save_file( $filename, $contents ) { /* translators: %s is a placeholder and will be replaced with the name of the relevant file. */ $failed_str = sprintf( __( 'Failed to write file %s!', 'all-in-one-seo-pack' ) . "\n", $filename ); /* translators: %s is a placeholder and will be replaced with the name of the relevant file. */ $readonly_str = sprintf( __( 'File %s isn\'t writable!', 'all-in-one-seo-pack' ) . "\n", $filename ); $wpfs = $this->get_filesystem_object(); if ( is_object( $wpfs ) ) { $file_exists = $wpfs->exists( $filename ); if ( ! $file_exists || $wpfs->is_writable( $filename ) ) { if ( $wpfs->put_contents( $filename, $contents ) === false ) { return $this->output_error( $failed_str ); } } else { return $this->output_error( $readonly_str ); } return true; } return false; } /** * Delete a file through WP Filesystem. * * @param string $filename * * @return bool */ function delete_file( $filename ) { $wpfs = $this->get_filesystem_object(); if ( is_object( $wpfs ) ) { if ( $wpfs->exists( $filename ) ) { if ( $wpfs->delete( $filename ) === false ) { /* translators: %s is a placeholder and will be replaced with the name of the relevant file. */ $this->output_error( sprintf( __( 'Failed to delete file %s!', 'all-in-one-seo-pack' ) . "\n", $filename ) ); } else { return true; } } else { /* translators: %s is a placeholder and will be replaced with the name of the relevant file. */ $this->output_error( sprintf( __( "File %s doesn't exist!", 'all-in-one-seo-pack' ) . "\n", $filename ) ); } } return false; } /** * Rename a file through WP Filesystem. * * @param string $filename * @param string $newname * * @return bool */ function rename_file( $filename, $newname ) { $wpfs = $this->get_filesystem_object(); if ( is_object( $wpfs ) ) { $file_exists = $wpfs->exists( $filename ); $newfile_exists = $wpfs->exists( $newname ); if ( $file_exists && ! $newfile_exists ) { if ( $wpfs->move( $filename, $newname ) === false ) { /* translators: %s is a placeholder and will be replaced with the name of the relevant file. */ $this->output_error( sprintf( __( 'Failed to rename file %s!', 'all-in-one-seo-pack' ) . "\n", $filename ) ); } else { return true; } } else { if ( ! $file_exists ) { /* translators: %s is a placeholder and will be replaced with the name of the relevant file. */ $this->output_error( sprintf( __( "File %s doesn't exist!", 'all-in-one-seo-pack' ) . "\n", $filename ) ); } elseif ( $newfile_exists ) { /* translators: %s is a placeholder and will be replaced with the name of the relevant file. */ $this->output_error( sprintf( __( 'File %s already exists!', 'all-in-one-seo-pack' ) . "\n", $newname ) ); } } } return false; } /** * Load multiple files. * * @param $options * @param $opts * @param $prefix * * @return mixed */ function load_files( $options, $opts, $prefix ) { foreach ( $opts as $opt => $file ) { $opt = $prefix . $opt; $file = ABSPATH . $file; $contents = $this->load_file( $file ); if ( false !== $contents ) { $options[ $opt ] = $contents; } } return $options; } /** * Save multiple files. * * @param $opts * @param $prefix */ function save_files( $opts, $prefix ) { foreach ( $opts as $opt => $file ) { $opt = $prefix . $opt; if ( isset( $_POST[ $opt ] ) ) { $output = stripslashes_deep( $_POST[ $opt ] ); $file = ABSPATH . $file; $this->save_file( $file, $output ); } } } /** * Delete multiple files. * * @param $opts */ function delete_files( $opts ) { foreach ( $opts as $opt => $file ) { $file = ABSPATH . $file; $this->delete_file( $file ); } } /** * Returns available social seo images. * * @since 2.4 #1079 Fixes array_flip warning on opengraph module. * * @param array $options Plugin/module options. * @param object $p Post. * * @return array */ function get_all_images_by_type( $options = null, $p = null ) { $img = array(); if ( empty( $img ) ) { $size = apply_filters( 'post_thumbnail_size', 'large' ); global $aioseop_options, $wp_query, $aioseop_opengraph; if ( null === $p ) { global $post; } else { $post = $p; } $count = 1; if ( ! empty( $post ) ) { if ( ! is_object( $post ) ) { $post = get_post( $post ); } if ( is_object( $post ) && function_exists( 'get_post_thumbnail_id' ) ) { if ( 'attachment' == $post->post_type ) { $post_thumbnail_id = $post->ID; } else { $post_thumbnail_id = get_post_thumbnail_id( $post->ID ); } if ( ! empty( $post_thumbnail_id ) ) { $image = wp_get_attachment_image_src( $post_thumbnail_id, $size ); if ( is_array( $image ) ) { $img[] = array( 'type' => 'featured', 'id' => $post_thumbnail_id, 'link' => $image[0], ); } } } $post_id = $post->ID; $p = $post; $w = $wp_query; $meta_key = ''; if ( is_array( $options ) && isset( $options['meta_key'] ) ) { $meta_key = $options['meta_key']; } if ( ! empty( $meta_key ) && ! empty( $post ) ) { $image = $this->get_the_image_by_meta_key( array( 'post_id' => $post->ID, 'meta_key' => explode( ',', $meta_key ), ) ); if ( ! empty( $image ) ) { $img[] = array( 'type' => 'meta_key', 'id' => $meta_key, 'link' => $image, ); } } if ( '' != ! $post->post_modified_gmt ) { $wp_query = new WP_Query( array( 'p' => $post_id, 'post_type' => $post->post_type, ) ); } if ( 'page' == $post->post_type ) { $wp_query->is_page = true; } elseif ( 'attachment' == $post->post_type ) { $wp_query->is_attachment = true; } else { $wp_query->is_single = true; } if ( 'page' == get_option( 'show_on_front' ) && get_option( 'page_for_posts' ) == $post->ID ) { $wp_query->is_home = true; } $args['options']['type'] = 'html'; $args['options']['nowrap'] = false; $args['options']['save'] = false; $wp_query->queried_object = $post; $attachments = get_children( array( 'post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID', ) ); if ( ! empty( $attachments ) ) { foreach ( $attachments as $id => $attachment ) { $image = wp_get_attachment_image_src( $id, $size ); if ( is_array( $image ) ) { $img[] = array( 'type' => 'attachment', 'id' => $id, 'link' => $image[0], ); } } } $matches = array(); preg_match_all( '||i', get_post_field( 'post_content', $post->ID ), $matches ); if ( isset( $matches ) && ! empty( $matches[1] ) && ! empty( $matches[1][0] ) ) { foreach ( $matches[1] as $i => $m ) { $img[] = array( 'type' => 'post_content', 'id' => 'post' . $count ++, 'link' => $m, ); } } wp_reset_postdata(); $wp_query = $w; $post = $p; } } return $img; } /** * Get All Images * * @since ? * * @param null $options * @param null $p * @return array */ function get_all_images( $options = null, $p = null ) { $img = $this->get_all_images_by_type( $options, $p ); $legacy = array(); foreach ( $img as $k => $v ) { $v['link'] = set_url_scheme( $v['link'] ); if ( 'featured' == $v['type'] ) { $legacy[ $v['link'] ] = 1; } else { $legacy[ $v['link'] ] = $v['id']; } } return $legacy; } /** * Thanks to Justin Tadlock for the original get-the-image code - http://themehybrid.com/plugins/get-the-image ** * * @param null $options * @param null $p * * @return bool|mixed|string */ function get_the_image( $options = null, $p = null ) { if ( null === $p ) { global $post; } else { $post = $p; } $meta_key = ''; if ( is_array( $options ) && isset( $options['meta_key'] ) ) { $meta_key = $options['meta_key']; } if ( ! empty( $meta_key ) && ! empty( $post ) ) { $meta_key = explode( ',', $meta_key ); $image = $this->get_the_image_by_meta_key( array( 'post_id' => $post->ID, 'meta_key' => $meta_key, ) ); } if ( empty( $image ) ) { $image = $this->get_the_image_by_post_thumbnail( $post ); } if ( empty( $image ) ) { $image = $this->get_the_image_by_attachment( $post ); } if ( empty( $image ) ) { $image = $this->get_the_image_by_scan( $post ); } if ( empty( $image ) ) { $image = $this->get_the_image_by_default( $post ); } return $image; } /** * Get the Image by Default * * @since ? * * @param null $p * @return string */ function get_the_image_by_default( $p = null ) { return ''; } /** * Get the Image by Meta Key * * @since ? * * @param array $args * @return bool|mixed */ function get_the_image_by_meta_key( $args = array() ) { /* If $meta_key is not an array. */ if ( ! is_array( $args['meta_key'] ) ) { $args['meta_key'] = array( $args['meta_key'] ); } /* Loop through each of the given meta keys. */ foreach ( $args['meta_key'] as $meta_key ) { /* Get the image URL by the current meta key in the loop. */ $image = get_post_meta( $args['post_id'], $meta_key, true ); /* If a custom key value has been given for one of the keys, return the image URL. */ if ( ! empty( $image ) ) { return $image; } } return false; } /** * Get the Image by Post Thumbnail * * @since ? * @since 2.4.13 Fixes when content is taxonomy. * * @param null $p * @return bool */ function get_the_image_by_post_thumbnail( $p = null ) { if ( null === $p ) { global $post; } else { $post = $p; } if ( is_category() || is_tag() || is_tax() ) { return false; } $post_thumbnail_id = null; if ( function_exists( 'get_post_thumbnail_id' ) ) { $post_thumbnail_id = get_post_thumbnail_id( $post->ID ); } if ( empty( $post_thumbnail_id ) ) { return false; } // Check if someone is using built-in WP filter. $size = apply_filters( 'aioseop_thumbnail_size', apply_filters( 'post_thumbnail_size', 'large' ) ); $image = wp_get_attachment_image_src( $post_thumbnail_id, $size ); return $image[0]; } /** * Get the Image by Attachment * * @since ? * * @param null $p * @return bool */ function get_the_image_by_attachment( $p = null ) { if ( null === $p ) { global $post; } else { $post = $p; } $attachments = get_children( array( 'post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID', ) ); if ( empty( $attachments ) && 'attachment' == get_post_type( $post->ID ) ) { $size = apply_filters( 'aioseop_attachment_size', 'large' ); $image = wp_get_attachment_image_src( $post->ID, $size ); } /* If no attachments or image is found, return false. */ if ( empty( $attachments ) && empty( $image ) ) { return false; } /* Set the default iterator to 0. */ $i = 0; /* Loop through each attachment. Once the $order_of_image (default is '1') is reached, break the loop. */ foreach ( $attachments as $id => $attachment ) { if ( 1 == ++ $i ) { $size = apply_filters( 'aioseop_attachment_size', 'large' ); $image = wp_get_attachment_image_src( $id, $size ); $alt = trim( strip_tags( get_post_field( 'post_excerpt', $id ) ) ); break; } } /* Return the image URL. */ return $image[0]; } /** * Get the Image by Scan * * @since ? * * @param null $p * @return bool */ function get_the_image_by_scan( $p = null ) { if ( null === $p ) { global $post; } else { $post = $p; } /* Search the post's content for the tag and get its URL. */ preg_match_all( '||i', get_post_field( 'post_content', $post->ID ), $matches ); /* If there is a match for the image, return its URL. */ if ( isset( $matches ) && ! empty( $matches[1][0] ) ) { return $matches[1][0]; } return false; } /** * Load scripts and styles for metaboxes. * edit-tags exists only for pre 4.5 support... remove when we drop 4.5 support. * Also, that check and others should be pulled out into their own functions. * * @todo is it possible to migrate this to \All_in_One_SEO_Pack_Module::add_page_hooks? Or refactor? Both function about the same. * * @since 2.4.14 Added term as screen base. */ function enqueue_metabox_scripts() { $screen = ''; if ( function_exists( 'get_current_screen' ) ) { $screen = get_current_screen(); } $bail = false; if ( empty( $screen ) ) { $bail = true; } if ( true != $bail ) { if ( ( 'post' != $screen->base ) && ( 'term' != $screen->base ) && ( 'edit-tags' != $screen->base ) && ( 'toplevel_page_shopp-products' != $screen->base ) ) { $bail = true; } } $prefix = $this->get_prefix(); $bail = apply_filters( $prefix . 'bail_on_enqueue', $bail, $screen ); if ( $bail ) { return; } $this->form = 'post'; if ( 'term' == $screen->base || 'edit-tags' == $screen->base ) { $this->form = 'edittag'; } if ( 'toplevel_page_shopp-products' == $screen->base ) { $this->form = 'product'; } $this->form = apply_filters( $prefix . 'set_form_on_enqueue', $this->form, $screen ); foreach ( $this->locations as $k => $v ) { if ( 'metabox' === $v['type'] && isset( $v['display'] ) && ! empty( $v['display'] ) ) { $enqueue_scripts = false; $enqueue_scripts = ( ( 'toplevel_page_shopp-products' == $screen->base ) && in_array( 'shopp_product', $v['display'] ) ) || in_array( $screen->post_type, $v['display'] ) || 'edit-category' == $screen->base || 'edit-post_tag' == $screen->base || 'term' == $screen->base; $enqueue_scripts = apply_filters( $prefix . 'enqueue_metabox_scripts', $enqueue_scripts, $screen, $v ); if ( $enqueue_scripts ) { add_filter( 'aioseop_localize_script_data', array( $this, 'localize_script_data' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 20 ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_styles' ), 20 ); } } } } /** * Load styles for module. * * Add hook in \All_in_One_SEO_Pack_Module::enqueue_metabox_scripts - Bails adding hook if not on target valid screen. * Add hook in \All_in_One_SEO_Pack_Module::add_page_hooks - Function itself is hooked based on the screen_id/page. * * @since 2.9 * @since 3.0 Added jQuery UI CSS missing from WP. #1850 * * @see 'admin_enqueue_scripts' hook * @link https://developer.wordpress.org/reference/hooks/admin_enqueue_scripts/ * @uses wp_scripts() Gets the Instance of WP Scripts. * @link https://developer.wordpress.org/reference/functions/wp_scripts/ * * @param string $hook_suffix */ function admin_enqueue_styles( $hook_suffix ) { wp_enqueue_style( 'thickbox' ); if ( ! empty( $this->pointers ) ) { wp_enqueue_style( 'wp-pointer' ); } wp_enqueue_style( 'aioseop-module-style', AIOSEOP_PLUGIN_URL . 'css/modules/aioseop_module.css', array(), AIOSEOP_VERSION ); if ( function_exists( 'is_rtl' ) && is_rtl() ) { wp_enqueue_style( 'aioseop-module-style-rtl', AIOSEOP_PLUGIN_URL . 'css/modules/aioseop_module-rtl.css', array( 'aioseop-module-style' ), AIOSEOP_VERSION ); } if ( ! wp_style_is( 'aioseop-jquery-ui', 'registered' ) && ! wp_style_is( 'aioseop-jquery-ui', 'enqueued' ) ) { wp_enqueue_style( 'aioseop-jquery-ui', AIOSEOP_PLUGIN_URL . 'css/aioseop-jquery-ui.css', array(), AIOSEOP_VERSION ); } } /** * Admin Enqueue Scripts * * Hook function to enqueue scripts and localize data to scripts. * * Add hook in \All_in_One_SEO_Pack_Module::enqueue_metabox_scripts - Bails adding hook if not on target valid screen. * Add hook in \All_in_One_SEO_Pack_Module::add_page_hooks - Function itself is hooked based on the screen_id/page. * * @since ? * @since 2.3.12.3 Add missing wp_enqueue_media. * @since 2.9 Switch to admin_enqueue_scripts; both the hook and function name. * @since 3.0 Add enqueue footer JS for jQuery UI Compatibility. #1850 * * @see 'admin_enqueue_scripts' hook * @link https://developer.wordpress.org/reference/hooks/admin_enqueue_scripts/ * @global WP_Post $post Used to set the post ID in wp_enqueue_media(). * * @param string $hook_suffix */ public function admin_enqueue_scripts( $hook_suffix ) { wp_enqueue_script( 'sack' ); wp_enqueue_script( 'jquery' ); wp_enqueue_script( 'jquery-ui-tabs' ); wp_enqueue_script( 'media-upload' ); wp_enqueue_script( 'thickbox' ); wp_enqueue_script( 'common' ); wp_enqueue_script( 'wp-lists' ); wp_enqueue_script( 'postbox' ); if ( ! empty( $this->pointers ) ) { wp_enqueue_script( 'wp-pointer', false, array( 'jquery' ) ); } global $post; if ( ! empty( $post->ID ) ) { wp_enqueue_media( array( 'post' => $post->ID ) ); } else { wp_enqueue_media(); } $helper_dep = array( 'jquery', 'jquery-ui-core', 'jquery-ui-widget', 'jquery-ui-position', 'jquery-ui-tooltip', ); // AIOSEOP Script enqueue. wp_enqueue_script( 'aioseop-module-script', AIOSEOP_PLUGIN_URL . 'js/modules/aioseop_module.js', array(), AIOSEOP_VERSION ); wp_enqueue_script( 'aioseop-helper-js', AIOSEOP_PLUGIN_URL . 'js/aioseop-helper.js', $helper_dep, AIOSEOP_VERSION, true ); // Localize aiosp_data in JS. if ( ! empty( $this->script_data ) ) { aioseop_localize_script_data(); } } /** * Localize Script Data * * @since ? * * @param $data * @return array */ function localize_script_data( $data ) { if ( ! is_array( $data ) ) { $data = array( 0 => $data ); } if ( empty( $this->script_data ) ) { $this->script_data = array(); } if ( ! empty( $this->pointers ) ) { $this->script_data['pointers'] = $this->pointers; } if ( empty( $data[0]['condshow'] ) ) { $data[0]['condshow'] = array(); } if ( empty( $this->script_data['condshow'] ) ) { $this->script_data['condshow'] = array(); } $condshow = $this->script_data['condshow']; $data[0]['condshow'] = array_merge( $data[0]['condshow'], $condshow ); unset( $this->script_data['condshow'] ); $data[0] = array_merge( $this->script_data, $data[0] ); $this->script_data['condshow'] = $condshow; return $data; } /** * Override this to run code at the beginning of the settings page. */ function settings_page_init() { } /** * Filter out admin pointers that have already been clicked. */ function filter_pointers() { if ( ! empty( $this->pointers ) ) { $dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ); foreach ( $dismissed as $d ) { if ( isset( $this->pointers[ $d ] ) ) { unset( $this->pointers[ $d ] ); } } } } /** * Add basic hooks when on the module's page. */ function add_page_hooks() { $hookname = current_filter(); if ( $this->strpos( $hookname, 'load-' ) === 0 ) { $this->pagehook = $this->substr( $hookname, 5 ); } add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_styles' ) ); add_filter( 'aioseop_localize_script_data', array( $this, 'localize_script_data' ) ); add_action( $this->prefix . 'settings_header', array( $this, 'display_tabs' ) ); } /** * Get Admin Links * * @since ? * * @return array */ function get_admin_links() { if ( ! empty( $this->menu_name ) ) { $name = $this->menu_name; } else { $name = $this->name; } $hookname = plugin_basename( $this->file ); $links = array(); $url = ''; if ( function_exists( 'menu_page_url' ) ) { $url = menu_page_url( $hookname, 0 ); } if ( empty( $url ) ) { $url = esc_url( admin_url( 'admin.php?page=' . $hookname ) ); } if ( null === $this->locations ) { array_unshift( $links, array( 'parent' => AIOSEOP_PLUGIN_DIRNAME, 'title' => $name, 'id' => $hookname, 'href' => $url, 'order' => $this->menu_order(), ) ); } else { foreach ( $this->locations as $k => $v ) { if ( 'settings' === $v['type'] ) { if ( 'default' === $k ) { array_unshift( $links, array( 'parent' => AIOSEOP_PLUGIN_DIRNAME, 'title' => $name, 'id' => $hookname, 'href' => $url, 'order' => $this->menu_order(), ) ); } else { if ( ! empty( $v['menu_name'] ) ) { $name = $v['menu_name']; } else { $name = $v['name']; } array_unshift( $links, array( 'parent' => AIOSEOP_PLUGIN_DIRNAME, 'title' => $name, 'id' => $this->get_prefix( $k ) . $k, 'href' => esc_url( admin_url( 'admin.php?page=' . $this->get_prefix( $k ) . $k ) ), 'order' => $this->menu_order(), ) ); } } } } return $links; } function add_admin_bar_submenu() { global $aioseop_admin_menu, $wp_admin_bar; if ( $aioseop_admin_menu ) { $links = $this->get_admin_links(); if ( ! empty( $links ) ) { foreach ( $links as $l ) { $wp_admin_bar->add_menu( $l ); } } } } /** * Collect metabox data together for tabbed metaboxes. * * @param $args * * @return array */ function filter_return_metaboxes( $args ) { return array_merge( $args, $this->post_metaboxes ); } /** Add submenu for module, call page hooks, set up metaboxes. * * @param $parent_slug * * @return bool */ function add_menu( $parent_slug ) { if ( ! empty( $this->menu_name ) ) { $name = $this->menu_name; } else { $name = $this->name; } if ( null === $this->locations ) { $hookname = add_submenu_page( $parent_slug, $name, $name, apply_filters( 'manage_aiosp', 'aiosp_manage_seo' ), plugin_basename( $this->file ), array( $this, 'display_settings_page', ) ); add_action( "load-{$hookname}", array( $this, 'add_page_hooks' ) ); return true; } foreach ( $this->locations as $k => $v ) { if ( 'settings' === $v['type'] ) { if ( 'default' === $k ) { if ( ! empty( $this->menu_name ) ) { $name = $this->menu_name; } else { $name = $this->name; } $hookname = add_submenu_page( $parent_slug, $name, $name, apply_filters( 'manage_aiosp', 'aiosp_manage_seo' ), plugin_basename( $this->file ), array( $this, 'display_settings_page', ) ); } else { if ( ! empty( $v['menu_name'] ) ) { $name = $v['menu_name']; } else { $name = $v['name']; } $hookname = add_submenu_page( $parent_slug, $name, $name, apply_filters( 'manage_aiosp', 'aiosp_manage_seo' ), $this->get_prefix( $k ) . $k, array( $this, "display_settings_page_$k", ) ); } add_action( "load-{$hookname}", array( $this, 'add_page_hooks' ) ); } elseif ( 'metabox' === $v['type'] ) { // hack -- make sure this runs anyhow, for now -- pdb. $this->setting_options( $k ); $this->toggle_save_post_hooks( true ); if ( isset( $v['display'] ) && ! empty( $v['display'] ) ) { add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_metabox_scripts' ), 5 ); if ( $this->tabbed_metaboxes ) { add_filter( 'aioseop_add_post_metabox', array( $this, 'filter_return_metaboxes' ) ); } foreach ( $v['display'] as $posttype ) { $v['location'] = $k; $v['posttype'] = $posttype; if ( post_type_exists( $posttype ) ) { // Metabox priority/context on edit post screen. $v['context'] = apply_filters( 'aioseop_post_metabox_context', 'normal' ); $v['priority'] = apply_filters( 'aioseop_post_metabox_priority', 'high' ); } if ( false !== strpos( $posttype, 'edit-' ) ) { // Metabox priority/context on edit taxonomy screen. $v['context'] = 'advanced'; $v['priority'] = 'default'; } // Metabox priority for everything else. if ( ! isset( $v['context'] ) ) { $v['context'] = 'advanced'; } if ( ! isset( $v['priority'] ) ) { $v['priority'] = 'default'; } if ( $this->tabbed_metaboxes ) { $this->post_metaboxes[] = array( 'id' => $v['prefix'] . $k, 'title' => $v['name'], 'callback' => array( $this, 'display_metabox' ), 'post_type' => $posttype, 'context' => $v['context'], 'priority' => $v['priority'], 'callback_args' => $v, ); } else { $title = $v['name']; if ( $title != $this->plugin_name ) { $title = $this->plugin_name . ' - ' . $title; } if ( ! empty( $v['help_link'] ) ) { $title .= "" . /* translators: This string is used as an action link which users can click on to view the relevant documentation on our website. */ __( 'Help', 'all-in-one-seo-pack' ) . ''; } add_meta_box( $v['prefix'] . $k, $title, array( $this, 'display_metabox', ), $posttype, $v['context'], $v['priority'], $v ); } } } } } } /** * Adds or removes hooks that could be called while editing a post. * * TODO: Review if all these hooks are really required (save_post should be enough vs. edit_post and publish_post). */ private function toggle_save_post_hooks( $add ) { if ( $add ) { add_action( 'edit_post', array( $this, 'save_post_data' ) ); add_action( 'publish_post', array( $this, 'save_post_data' ) ); add_action( 'add_attachment', array( $this, 'save_post_data' ) ); add_action( 'edit_attachment', array( $this, 'save_post_data' ) ); add_action( 'save_post', array( $this, 'save_post_data' ) ); add_action( 'edit_page_form', array( $this, 'save_post_data' ) ); } else { remove_action( 'edit_post', array( $this, 'save_post_data' ) ); remove_action( 'publish_post', array( $this, 'save_post_data' ) ); remove_action( 'add_attachment', array( $this, 'save_post_data' ) ); remove_action( 'edit_attachment', array( $this, 'save_post_data' ) ); remove_action( 'save_post', array( $this, 'save_post_data' ) ); remove_action( 'edit_page_form', array( $this, 'save_post_data' ) ); } } /** * Update postmeta for metabox. * * @param $post_id */ function save_post_data( $post_id ) { $this->toggle_save_post_hooks( false ); if ( null !== $this->locations ) { foreach ( $this->locations as $k => $v ) { if ( isset( $v['type'] ) && ( 'metabox' === $v['type'] ) ) { $opts = $this->default_options( $k ); $options = array(); foreach ( $opts as $l => $o ) { if ( isset( $_POST[ $l ] ) ) { $options[ $l ] = stripslashes_deep( $_POST[ $l ] ); $options[ $l ] = esc_attr( $options[ $l ] ); } } $prefix = $this->get_prefix( $k ); $options = apply_filters( $prefix . 'filter_metabox_options', $options, $k, $post_id ); foreach ( $options as $option ) { $option = aioseop_sanitize( $option ); } update_post_meta( $post_id, '_' . $prefix . $k, $options ); } } } $this->toggle_save_post_hooks( true ); } /** * Outputs radio buttons, checkboxes, selects, multiselects, handles groups. * * @param $args * * @return string */ function do_multi_input( $args ) { $options = $args['options']; $value = $args['value']; $name = $args['name']; $attr = $args['attr']; $buf1 = ''; $type = $options['type']; $strings = array( 'block' => "\n", 'group' => "\t\n%s\t\n", 'item' => "\t\n", 'item_args' => array( 'sel', 'v', 'subopt' ), 'selected' => 'selected ', ); if ( ( 'radio' === $type ) || ( 'checkbox' === $type ) ) { $strings = array( 'block' => "%s\n", 'group' => "\t%s
\n%s\n", 'item' => "\t\n", 'item_args' => array( 'sel', 'name', 'v', 'attr', 'subopt' ), 'selected' => 'checked ', ); } $setsel = $strings['selected']; if ( isset( $options['initial_options'] ) && is_array( $options['initial_options'] ) ) { foreach ( $options['initial_options'] as $l => $option ) { $option_check = strip_tags( is_array( $option ) ? implode( ' ', $option ) : $option ); if ( empty( $l ) && empty( $option_check ) ) { continue; } $is_group = is_array( $option ); if ( ! $is_group ) { $option = array( $l => $option ); } $buf2 = ''; foreach ( $option as $v => $subopt ) { $sel = ''; $is_arr = is_array( $value ); if ( is_string( $v ) || is_string( $value ) ) { if ( is_string( $value ) ) { $cmp = ! strcmp( $v, $value ); } else { $cmp = ! strcmp( $v, '' ); } // $cmp = !strcmp( (string)$v, (string)$value ); } else { $cmp = ( $value == $v ); } if ( ( ! $is_arr && $cmp ) || ( $is_arr && in_array( $v, $value ) ) ) { $sel = $setsel; } $item_arr = array(); foreach ( $strings['item_args'] as $arg ) { $item_arr[] = $$arg; } $buf2 .= vsprintf( $strings['item'], $item_arr ); } if ( $is_group ) { $buf1 .= sprintf( $strings['group'], $l, $buf2 ); } else { $buf1 .= $buf2; } } $buf1 = sprintf( $strings['block'], $buf1 ); } return $buf1; } /** * Get Option HTML * * Outputs a setting item for settings pages and metaboxes. * * @since ? * @since 2.12 Add 'input' to allowed tags with 'html'. #2157 * * @param array $args { * Contains the admin option element values and attributes for rendering. * * @type string $attr The HTML element's attributes to render within the element. * @type string $name THE HTML element's name attribute. Used with form input elements. * @type string $prefix Optional. The AIOSEOP Module prefix. * @type string $value The HTML element's value attribute. * @type array $options { * Arguments used for this function/method operations and rendering. * * @type string $class Optional. The HTML element's class attribute. This is used if * `$options['count']` is not empty. * @type int $cols Optional. Character count length of column. * @type boolean $count Optional. Determines whether to add the character count for SEO. * @type string $count_desc Optional. The description/help text to rend to the admin. * @type string $name Optional. Used within the description/help text when it's for character count. * @type boolean $required Optional. Determines whether to require a value in the input element. * @type int $rows Optional. Number of rows to multiply with cols. * @type string $type Which Switch Case (HTML element) to use. * } * } * @return string */ function get_option_html( $args ) { static $n = 0; $options = $args['options']; $value = $args['value']; $name = $args['name']; $attr = $args['attr']; $prefix = isset( $args['prefix'] ) ? $args['prefix'] : ''; if ( 'custom' == $options['type'] ) { return apply_filters( "{$prefix}output_option", '', $args ); } if ( in_array( $options['type'], array( 'multiselect', 'select', 'multicheckbox', 'radio', 'checkbox', 'textarea', 'text', 'submit', 'hidden', 'date', ) ) && is_string( $value ) ) { $value = esc_attr( $value ); } $buf = ''; $onload = ''; if ( ! empty( $options['count'] ) ) { $n ++; $classes = isset( $options['class'] ) ? $options['class'] : ''; $classes .= ' aioseop_count_chars'; $attr .= " class='{$classes}' data-length-field='{$prefix}length$n'"; } if ( isset( $opts['id'] ) ) { $attr .= " id=\"{$opts['id']}\" "; } if ( isset( $options['required'] ) && true === $options['required'] ) { $attr .= ' required'; } switch ( $options['type'] ) { case 'multiselect': $attr .= ' MULTIPLE'; $args['attr'] = $attr; $name = "{$name}[]"; $args['name'] = $name; // fall through. case 'select': $buf .= $this->do_multi_input( $args ); break; case 'multicheckbox': $name = "{$name}[]"; $args['name'] = $name; $args['options']['type'] = 'checkbox'; $options['type'] = 'checkbox'; // fall through. case 'radio': $buf .= $this->do_multi_input( $args ); break; case 'checkbox': if ( $value ) { $attr .= ' CHECKED'; } $buf .= "\n"; break; case 'textarea': // #1363: prevent characters like ampersand in title and description (in social meta module) from getting changed to & if ( in_array( $name, array( 'aiosp_opengraph_hometitle', 'aiosp_opengraph_description' ), true ) ) { $value = htmlspecialchars_decode( $value, ENT_QUOTES ); } $buf .= ""; break; case 'image': $buf .= '' . "\n"; break; case 'html': $allowed_tags = wp_kses_allowed_html( 'post' ); $allowed_tags['input'] = array( 'name' => true, 'type' => true, 'value' => true, 'class' => true, 'placeholder' => true, ); $buf .= wp_kses( $value, $allowed_tags ); break; case 'esc_html': $buf .= '
' . esc_html( $value ) . "
\n"; break; case 'date': // firefox and IE < 11 do not have support for HTML5 date, so we will fall back to the datepicker. wp_enqueue_script( 'jquery-ui-datepicker' ); // fall through. default: $buf .= "\n"; } // TODO Maybe Change/Add a function for SEO character count. if ( ! empty( $options['count'] ) ) { $size = 60; if ( isset( $options['size'] ) ) { $size = $options['size']; } elseif ( isset( $options['rows'] ) && isset( $options['cols'] ) ) { $size = $options['rows'] * $options['cols']; } if ( isset( $options['count_desc'] ) ) { $count_desc = $options['count_desc']; } else { /* translators: %1$s and %2$s are placeholders and should not be translated. %1$s is replaced with a number, %2$s is replaced with the name of an meta tag field (e.g; "Title", "Description", etc.). */ $count_desc = __( ' characters. Most search engines use a maximum of %1$s chars for the %2$s.', 'all-in-one-seo-pack' ); } $buf .= "
" . sprintf( $count_desc, $size, trim( $this->strtolower( $options['name'] ), ':' ) ); if ( ! empty( $onload ) ) { $buf .= ""; } } return $buf; } /** * Format a row for an option on a settings page. * * @since ? * @since 3.0 Added Helper Class for jQuery Tooltips. #1850 * * @param $name * @param $opts * @param $args * * @return string */ function get_option_row( $name, $opts, $args ) { $label_text = ''; $input_attr = ''; $id_attr = ''; require_once( AIOSEOP_PLUGIN_DIR . 'admin/class-aioseop-helper.php' ); $info = new AIOSEOP_Helper( get_class( $this ) ); $align = 'right'; if ( 'top' == $opts['label'] ) { $align = 'left'; } if ( isset( $opts['id'] ) ) { $id_attr .= " id=\"{$opts['id']}_div\" "; } if ( 'none' != $opts['label'] ) { $tmp_help_text = $info->get_help_text( $name ); if ( isset( $tmp_help_text ) && ! empty( $tmp_help_text ) ) { $display_help = ''; $help_text = sprintf( $display_help, $info->get_help_text( $name ), $opts['name'] ); } else { $help_text = $opts['name']; } // TODO Possible remove text align. // Currently aligns to the right when everything is being aligned to the left; which is usually a workaround. $display_label_format = '%s'; $label_text = sprintf( $display_label_format, $align, $help_text ); } else { $input_attr .= ' aioseop_no_label '; } if ( 'top' == $opts['label'] ) { $label_text .= "
"; } $input_attr .= " aioseop_{$opts['type']}_type"; $display_row_template = '
%s
%s

'; return sprintf( $display_row_template, $input_attr, $name, $label_text, $id_attr, $this->get_option_html( $args ) ); } /** * Display options for settings pages and metaboxes, allows for filtering settings, custom display options. * * @param null $location * @param null $meta_args */ function display_options( $location = null, $meta_args = null ) { static $location_settings = array(); $defaults = null; $prefix = $this->get_prefix( $location ); $help_link = ''; if ( is_array( $meta_args['args'] ) && ! empty( $meta_args['args']['default_options'] ) ) { $defaults = $meta_args['args']['default_options']; } if ( ! empty( $meta_args['callback_args'] ) && ! empty( $meta_args['callback_args']['help_link'] ) ) { $help_link = $meta_args['callback_args']['help_link']; } if ( ! empty( $help_link ) ) { echo "" . __( 'Help', 'all-in-one-seo-pack' ) . ''; } if ( ! isset( $location_settings[ $prefix ] ) ) { $current_options = apply_filters( "{$this->prefix}display_options", $this->get_current_options( array(), $location, $defaults ), $location ); $settings = apply_filters( "{$this->prefix}display_settings", $this->setting_options( $location, $defaults ), $location, $current_options ); $current_options = apply_filters( "{$this->prefix}override_options", $current_options, $location, $settings ); $location_settings[ $prefix ]['current_options'] = $current_options; $location_settings[ $prefix ]['settings'] = $settings; } else { $current_options = $location_settings[ $prefix ]['current_options']; $settings = $location_settings[ $prefix ]['settings']; } // $opts["snippet"]["default"] = sprintf( $opts["snippet"]["default"], "foo", "bar", "moby" ); $container = "
"; if ( is_array( $meta_args['args'] ) && ! empty( $meta_args['args']['options'] ) ) { $args = array(); $arg_keys = array(); foreach ( $meta_args['args']['options'] as $a ) { if ( ! empty( $location ) ) { $key = $prefix . $location . '_' . $a; if ( ! isset( $settings[ $key ] ) ) { $key = $a; } } else { $key = $prefix . $a; } if ( isset( $settings[ $key ] ) ) { $arg_keys[ $key ] = 1; } elseif ( isset( $settings[ $a ] ) ) { $arg_keys[ $a ] = 1; } } $setting_keys = array_keys( $settings ); foreach ( $setting_keys as $s ) { if ( ! empty( $arg_keys[ $s ] ) ) { $args[ $s ] = $settings[ $s ]; } } } else { $args = $settings; } foreach ( $args as $name => $opts ) { // List of valid element attributes. $attr_list = array( 'class', 'style', 'readonly', 'disabled', 'size', 'placeholder', 'autocomplete' ); if ( 'textarea' == $opts['type'] ) { $attr_list = array_merge( $attr_list, array( 'rows', 'cols' ) ); } // Set element attribute values. $attr = ''; foreach ( $attr_list as $a ) { if ( isset( $opts[ $a ] ) ) { $attr .= ' ' . $a . '="' . esc_attr( $opts[ $a ] ) . '" '; } } $opt = ''; if ( isset( $current_options[ $name ] ) ) { $opt = $current_options[ $name ]; } if ( 'none' == $opts['label'] && 'submit' == $opts['type'] && false == $opts['save'] ) { $opt = $opts['name']; } if ( 'html' == $opts['type'] && empty( $opt ) && false == $opts['save'] ) { $opt = $opts['default']; } $args = array( 'name' => $name, 'options' => $opts, 'attr' => $attr, 'value' => $opt, 'prefix' => $prefix, ); if ( ! empty( $opts['nowrap'] ) ) { echo $this->get_option_html( $args ); } else { if ( $container ) { echo $container; $container = ''; } echo $this->get_option_row( $name, $opts, $args ); } } if ( ! $container ) { echo '
'; } } /** * Sanitize Domain * * @since ? * * @param $domain * @return mixed|string */ function sanitize_domain( $domain ) { $domain = trim( $domain ); $domain = $this->strtolower( $domain ); if ( 0 === $this->strpos( $domain, 'http://' ) ) { $domain = $this->substr( $domain, 7 ); } elseif ( 0 === $this->strpos( $domain, 'https://' ) ) { $domain = $this->substr( $domain, 8 ); } $domain = untrailingslashit( $domain ); return $domain; } /** Sanitize options * * @param null $location */ function sanitize_options( $location = null ) { foreach ( $this->setting_options( $location ) as $k => $v ) { if ( isset( $this->options[ $k ] ) ) { if ( ! empty( $v['sanitize'] ) ) { $type = $v['sanitize']; } else { $type = $v['type']; } switch ( $type ) { case 'multiselect': // fall through. case 'multicheckbox': $this->options[ $k ] = urlencode_deep( $this->options[ $k ] ); break; case 'textarea': // #1363: prevent characters like ampersand in title and description (in social meta module) from getting changed to & if ( ! ( 'opengraph' === $location && in_array( $k, array( 'aiosp_opengraph_hometitle', 'aiosp_opengraph_description' ), true ) ) ) { $this->options[ $k ] = wp_kses_post( $this->options[ $k ] ); } $this->options[ $k ] = htmlspecialchars( $this->options[ $k ], ENT_QUOTES, 'UTF-8' ); break; case 'filename': $this->options[ $k ] = sanitize_file_name( $this->options[ $k ] ); break; case 'url': // fall through. case 'text': $this->options[ $k ] = wp_kses_post( $this->options[ $k ] ); // fall through. case 'checkbox': // fall through. case 'radio': // fall through. case 'select': // fall through. default: if ( ! is_array( $this->options[ $k ] ) ) { $this->options[ $k ] = esc_attr( $this->options[ $k ] ); } } } } } /** * Display metaboxes with display_options() * * @param $post * @param $metabox */ function display_metabox( $post, $metabox ) { $this->display_options( $metabox['args']['location'], $metabox ); } /** * Handle resetting options to defaults. * * @param null $location * @param bool $delete */ function reset_options( $location = null, $delete = false ) { if ( true === $delete ) { $this->delete_class_option( $delete ); $this->options = array(); } $default_options = $this->default_options( $location ); foreach ( $default_options as $k => $v ) { $this->options[ $k ] = $v; } $this->update_class_option( $this->options ); } /** * Handle Settings Updates * * Handle option resetting and updating. * * @since ? * * @param null $location * @return mixed|string|void */ function handle_settings_updates( $location = null ) { $message = ''; if ( ( isset( $_POST['action'] ) && 'aiosp_update_module' == $_POST['action'] && ( isset( $_POST['Submit_Default'] ) || isset( $_POST['Submit_All_Default'] ) || ! empty( $_POST['Submit'] ) ) ) ) { $nonce = $_POST['nonce-aioseop']; if ( ! wp_verify_nonce( $nonce, 'aioseop-nonce' ) ) { die( __( 'Security Check - If you receive this in error, log out and back in to WordPress', 'all-in-one-seo-pack' ) ); } if ( isset( $_POST['Submit_Default'] ) || isset( $_POST['Submit_All_Default'] ) ) { /* translators: This message confirms that the options have been reset. */ $message = __( 'Options Reset.', 'all-in-one-seo-pack' ); if ( isset( $_POST['Submit_All_Default'] ) ) { $this->reset_options( $location, true ); do_action( 'aioseop_options_reset' ); } else { $this->reset_options( $location ); } } if ( ! empty( $_POST['Submit'] ) ) { /* translators: %s is a placeholder and will be replace with the name of the plugin. */ $message = sprintf( __( '%s Options Updated.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME ); $default_options = $this->default_options( $location ); foreach ( $default_options as $k => $v ) { if ( isset( $_POST[ $k ] ) ) { $this->options[ $k ] = stripslashes_deep( $_POST[ $k ] ); } else { $this->options[ $k ] = ''; } } $this->sanitize_options( $location ); $this->options = apply_filters( $this->prefix . 'update_options', $this->options, $location ); $this->update_class_option( $this->options ); wp_cache_flush(); } do_action( $this->prefix . 'settings_update', $this->options, $location ); } return $message; } /** Update / reset settings, printing options, sanitizing, posting back * * @param null $location */ function display_settings_page( $location = null ) { if ( null != $location ) { $location_info = $this->locations[ $location ]; } $name = null; if ( $location && isset( $location_info['name'] ) ) { $name = $location_info['name']; } if ( ! $name ) { $name = $this->name; } $message = $this->handle_settings_updates( $location ); $this->settings_page_init(); ?>
prefix . 'settings_header_errors', $location ); $errors = ob_get_clean(); echo $errors; ?>

$message

"; } ?>

prefix . 'settings_header', $location ); ?>
array( 'type' => 'hidden', 'value' => 'aiosp_update_module', ), 'module' => array( 'type' => 'hidden', 'value' => get_class( $this ), ), 'location' => array( 'type' => 'hidden', 'value' => $location, ), 'nonce-aioseop' => array( 'type' => 'hidden', 'value' => wp_create_nonce( 'aioseop-nonce' ), ), 'page_options' => array( 'type' => 'hidden', 'value' => 'aiosp_home_description', ), 'Submit' => array( 'type' => 'submit', 'class' => 'aioseop_update_options_button button-primary', 'value' => __( 'Update Options', 'all-in-one-seo-pack' ) . ' »', ), 'Submit_Default' => array( 'type' => 'submit', 'class' => 'aioseop_reset_settings_button button-secondary', /* translators: This is a button users can click to reset the settings of a specific module to their default values. %s is a placeholder and will be replaced with the name of a settings menu (e.g. "Performance"). */ 'value' => sprintf( __( 'Reset %s Settings to Defaults', 'all-in-one-seo-pack' ), $name ) . ' »', ), ); $submit_options = apply_filters( "{$this->prefix}submit_options", $submit_options, $location ); foreach ( $submit_options as $k => $s ) { if ( 'submit' == $s['type'] && 'Submit' != $k ) { continue; } $class = ''; if ( isset( $s['class'] ) ) { $class = " class='{$s['class']}' "; } echo $this->get_option_html( array( 'name' => $k, 'options' => $s, 'attr' => $class, 'value' => $s['value'], ) ); } ?>
get_class_option(); if ( false !== $opts ) { $this->options = $opts; } if ( is_array( $this->layout ) ) { foreach ( $this->layout as $l => $lopts ) { if ( ! isset( $lopts['tab'] ) || ( $this->current_tab == $lopts['tab'] ) ) { $title = $lopts['name']; if ( ! empty( $lopts['help_link'] ) ) { $title .= "" . __( 'Help', 'all-in-one-seo-pack' ) . ''; } add_meta_box( $this->get_prefix( $location ) . $l . '_metabox', $title, array( $this, 'display_options', ), "{$this->prefix}settings", 'advanced', 'default', $lopts ); } } } else { add_meta_box( $this->get_prefix( $location ) . 'metabox', $name, array( $this, 'display_options', ), "{$this->prefix}settings", 'advanced' ); } do_meta_boxes( "{$this->prefix}settings", 'advanced', $location ); ?>

$s ) { $class = ''; if ( isset( $s['class'] ) ) { $class = " class='{$s['class']}' "; } echo $this->get_option_html( array( 'name' => $k, 'options' => $s, 'attr' => $class, 'value' => $s['value'], ) ); } ?>

prefix . 'settings_footer', $location ); do_action( 'aioseop_global_settings_footer', $location ); ?>
locations[ $location ]['prefix'] ) ) { return $this->locations[ $location ]['prefix']; } return $this->prefix; } /** Sets up initial settings * * @param null $location * @param null $defaults * * @return array */ function setting_options( $location = null, $defaults = null ) { if ( null === $defaults ) { $defaults = $this->default_options; } $prefix = $this->get_prefix( $location ); $opts = array(); if ( null == $location || null === $this->locations[ $location ]['options'] ) { $options = $defaults; } else { $options = array(); $prefix = "{$prefix}{$location}_"; if ( ! empty( $this->locations[ $location ]['default_options'] ) ) { $options = $this->locations[ $location ]['default_options']; } foreach ( $this->locations[ $location ]['options'] as $opt ) { if ( isset( $defaults[ $opt ] ) ) { $options[ $opt ] = $defaults[ $opt ]; } } } if ( ! $prefix ) { $prefix = $this->prefix; } if ( ! empty( $options ) ) { foreach ( $options as $k => $v ) { if ( ! isset( $v['name'] ) ) { $v['name'] = $this->ucwords( strtr( $k, '_', ' ' ) ); } if ( ! isset( $v['type'] ) ) { $v['type'] = 'checkbox'; } if ( ! isset( $v['default'] ) ) { $v['default'] = null; } if ( ! isset( $v['initial_options'] ) ) { $v['initial_options'] = $v['default']; } if ( 'custom' == $v['type'] && ( ! isset( $v['nowrap'] ) ) ) { $v['nowrap'] = true; } elseif ( ! isset( $v['nowrap'] ) ) { $v['nowrap'] = null; } if ( isset( $v['condshow'] ) ) { if ( ! is_array( $this->script_data ) ) { $this->script_data = array(); } if ( ! isset( $this->script_data['condshow'] ) ) { $this->script_data['condshow'] = array(); } $this->script_data['condshow'][ $prefix . $k ] = $v['condshow']; } if ( 'submit' == $v['type'] ) { if ( ! isset( $v['save'] ) ) { $v['save'] = false; } if ( ! isset( $v['label'] ) ) { $v['label'] = 'none'; } if ( ! isset( $v['prefix'] ) ) { $v['prefix'] = false; } } else { if ( ! isset( $v['label'] ) ) { $v['label'] = null; } } if ( 'hidden' == $v['type'] ) { if ( ! isset( $v['label'] ) ) { $v['label'] = 'none'; } if ( ! isset( $v['prefix'] ) ) { $v['prefix'] = false; } } if ( ( 'text' == $v['type'] ) && ( ! isset( $v['size'] ) ) ) { $v['size'] = 57; } if ( 'textarea' == $v['type'] ) { if ( ! isset( $v['cols'] ) ) { $v['cols'] = 57; } if ( ! isset( $v['rows'] ) ) { $v['rows'] = 2; } } if ( ! isset( $v['save'] ) ) { $v['save'] = true; } if ( ! isset( $v['prefix'] ) ) { $v['prefix'] = true; } if ( $v['prefix'] ) { $opts[ $prefix . $k ] = $v; } else { $opts[ $k ] = $v; } } } return $opts; } /** * Generates just the default option names and values * * @since 2.4.13 Applies filter before final return. * * @param null $location * @param null $defaults * * @return array */ function default_options( $location = null, $defaults = null ) { $prefix = $this->get_prefix( $location ); $options = $this->setting_options( $location, $defaults ); $opts = array(); foreach ( $options as $k => $v ) { if ( $v['save'] ) { $opts[ $k ] = $v['default']; } } return apply_filters( $prefix . 'default_options', $opts, $location ); } /** * Gets the current options stored for a given location. * * @since 2.4.14 Added taxonomy options. * * @param array $opts * @param null $location * @param null $defaults * @param null $post * * @return array */ function get_current_options( $opts = array(), $location = null, $defaults = null, $post = null ) { $prefix = $this->get_prefix( $location ); $get_opts = ''; if ( empty( $location ) ) { $type = 'settings'; } else { $type = $this->locations[ $location ]['type']; } if ( 'settings' === $type ) { $get_opts = $this->get_class_option(); } elseif ( 'metabox' == $type ) { if ( null == $post ) { global $post; } if ( ( isset( $_GET['taxonomy'] ) && isset( $_GET['tag_ID'] ) ) || is_category() || is_tag() || is_tax() ) { $term_id = isset( $_GET['tag_ID'] ) ? (int) $_GET['tag_ID'] : 0; $term_id = $term_id ? $term_id : get_queried_object()->term_id; if ( AIOSEOPPRO ) { $get_opts = AIO_ProGeneral::getprotax( $get_opts ); $get_opts = get_term_meta( $term_id, '_' . $prefix . $location, true ); } } elseif ( isset( $post ) ) { $get_opts = get_post_meta( $post->ID, '_' . $prefix . $location, true ); } } if ( is_home() && ! is_front_page() ) { // If we're on the non-front page blog page, WP doesn't really know its post meta data so we need to get that manually for social meta. $get_opts = get_post_meta( get_option( 'page_for_posts' ), '_' . $prefix . $location, true ); } $defs = $this->default_options( $location, $defaults ); if ( empty( $get_opts ) ) { $get_opts = $defs; } else { $get_opts = wp_parse_args( $get_opts, $defs ); } $opts = wp_parse_args( $opts, $get_opts ); return $opts; } /** Updates the options array in the module; loads saved settings with get_option() or uses defaults * * @param array $opts * @param null $location * @param null $defaults */ function update_options( $opts = array(), $location = null, $defaults = null ) { if ( null === $location ) { $type = 'settings'; } else { $type = $this->locations[ $location ][ $type ]; } if ( 'settings' === $type ) { $get_opts = $this->get_class_option(); } if ( false === $get_opts ) { $get_opts = $this->default_options( $location, $defaults ); } else { $this->setting_options( $location, $defaults ); } // hack -- make sure this runs anyhow, for now -- pdb $this->options = wp_parse_args( $opts, $get_opts ); } } } PKH\Լ f.f.display/credits-content.phpnu[ PKH\display/notices/.notices.phpnu[PKH\\ff(display/notices/review-plugin-notice.phpnu[ 'review_plugin', 'delay_time' => 1036800, 'target' => 'user', 'screens' => array( 'aioseop' ), 'class' => 'notice-info', /* translators: %1$s is a placeholder, which means that it should not be translated. It will be replaced with the name of the plugin, All in One SEO Pack. */ 'message' => sprintf( __( 'You have been using %1$s for a while now. That is awesome! If you like %2$s, then please leave us a 5-star rating. Huge thanks in advance!', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME, AIOSEOP_PLUGIN_NAME ), 'action_options' => array( array( 'time' => 0, 'text' => __( 'Add a review', 'all-in-one-seo-pack' ), 'link' => 'https://wordpress.org/support/plugin/all-in-one-seo-pack/reviews?rate=5#new-post', 'dismiss' => false, 'class' => 'button-primary button-orange', ), array( 'text' => __( 'Remind me later', 'all-in-one-seo-pack' ), 'time' => 432000, 'dismiss' => false, 'class' => 'button-secondary', ), array( 'time' => 0, 'text' => __( 'No, thanks', 'all-in-one-seo-pack' ), 'dismiss' => true, 'class' => 'button-secondary', ), ), ); } // phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar // add_filter( 'aioseop_admin_notice-review_plugin', 'aioseop_notice_review_plugin' ); PKH\$$display/notices/index.phpnu[ 'woocommerce_detected', 'delay_time' => 0, /* translators: %s is a placeholder, which means that it should not be translated. It will be replaced with the name of the premium version of the plugin, All in One SEO Pack Pro. */ 'message' => sprintf( __( 'We have detected you are running WooCommerce. Upgrade to %s to unlock our advanced e-commerce features, including SEO for Product Categories and more.', 'all-in-one-seo-pack' ), 'All in One SEO Pack Pro' ), 'class' => 'notice-info', 'target' => 'site', 'screens' => array( 'aioseop' ), 'action_options' => array( array( 'time' => 0, 'text' => __( 'Upgrade', 'all-in-one-seo-pack' ), 'link' => 'https://semperplugins.com/plugins/all-in-one-seo-pack-pro-version/?loc=woo', 'dismiss' => false, 'class' => 'button-primary button-orange', ), array( 'time' => 2592000, // 30 days. 'text' => __( 'No Thanks', 'all-in-one-seo-pack' ), 'link' => '', 'dismiss' => false, 'class' => 'button-secondary', ), ), ); } add_filter( 'aioseop_admin_notice-woocommerce_detected', 'aioseop_notice_pro_promo_woocommerce' ); PKH\d +*display/notices/sitemap-indexes-notice.phpnu[ 'sitemap_max_warning', 'delay_time' => 0, 'message' => __( 'Notice: To avoid problems with your XML Sitemap, we strongly recommend you set the Maximum Posts per Sitemap Page to 1,000.', 'all-in-one-seo-pack' ), 'class' => 'notice-warning', 'target' => 'user', 'screens' => array(), 'action_options' => array( array( 'time' => 0, 'text' => __( 'Update Sitemap Settings', 'all-in-one-seo-pack' ), 'link' => esc_url( get_admin_url( null, 'admin.php?page=' . AIOSEOP_PLUGIN_DIRNAME . '/modules/aioseop_sitemap.php' ) ), 'dismiss' => false, 'class' => 'button-primary', ), array( 'time' => 86400, // 24 hours. 'text' => __( 'Remind me later', 'all-in-one-seo-pack' ), 'link' => '', 'dismiss' => false, 'class' => 'button-secondary', ), ), ); } add_filter( 'aioseop_admin_notice-sitemap_max_warning', 'aioseop_notice_sitemap_indexes' ); PKH\+ee*display/notices/blog-visibility-notice.phpnu[' . __( 'Reading Settings', 'all-in-one-seo-pack' ) . ''; return array( 'slug' => 'blog_public_disabled', 'delay_time' => 0, /* translators: %s is a placeholder, which means that it should not be translated. It will be replaced with the name of the plugin, All in One SEO Pack. "Settings > Reading" refers to the "Reading" submenu in WordPress Core. */ 'message' => sprintf( __( 'Warning: %s has detected that you are blocking access to search engines. You can change this in Settings > Reading if this was unintended.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME ), 'class' => 'notice-error', 'target' => 'site', 'screens' => array(), 'action_options' => array( array( 'time' => 0, 'text' => __( 'Update Reading Settings', 'all-in-one-seo-pack' ), 'link' => admin_url( 'options-reading.php' ), 'dismiss' => false, 'class' => 'button-primary', ), array( 'time' => 604800, 'text' => __( 'Remind me later', 'all-in-one-seo-pack' ), 'link' => '', 'dismiss' => false, 'class' => 'button-secondary', ), ), ); } add_filter( 'aioseop_admin_notice-blog_public_disabled', 'aioseop_notice_blog_visibility' ); PKH\vM50!0!display/general-metaboxes.phpnu["; switch ( $meta['id'] ) : case 'aioseop-about': ?>

ID; $ignore = get_user_meta( $user_id, 'aioseop_ignore_notice' ); if ( ! empty( $ignore ) ) { $qa = array(); wp_parse_str( $_SERVER['QUERY_STRING'], $qa ); $qa['aioseop_reset_notices'] = 1; $url = '?' . build_query( $qa ); echo '

' . __( 'Reset Dismissed Notices', 'all-in-one-seo-pack' ) . '

'; } ?>

percent_translated < 100 ) { if ( ! empty( $aiosp_trans->native_name ) ) { $maybe_native_name = $aiosp_trans->native_name; } else { $maybe_native_name = $aiosp_trans->name; } /* translators: %1$s, %2$s, etc. are placeholders and shouldn't be translated. %1$s expands to the number of languages All in One SEO Pack has been translated into, %2$s to the name of the plugin, $3%s to the percentage translated of the current language, $4%s to the language name, %5$s and %6$s to anchor tags with link to the translation page at translate.wordpress.org */ printf( __( '%1$s has been translated into %2$s languages, but currently the %3$s translation is only %4$s percent complete. %5$sClick here%6$s to help get it to 100 percent.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME, $aiosp_trans->translated_count, $maybe_native_name, $aiosp_trans->percent_translated, "translation_url\" target=\"_BLANK\">", '' ); } ?>
action="https://semperplugins.us1.list-manage.com/subscribe/post?u=794674d3d54fdd912f961ef14&id=b786958a9a" action="https://semperplugins.us1.list-manage.com/subscribe/post?u=794674d3d54fdd912f961ef14&id=af0a96d3d9" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank">

'; if ( class_exists( 'WooCommerce' ) ) { echo '
  • ' . __( 'Advanced support for WooCommerce', 'all-in-one-seo-pack' ) . '
  • '; } else { echo '
  • ' . __( 'Advanced support for e-commerce', 'all-in-one-seo-pack' ) . '
  • '; } echo '
  • ' . __( 'Video SEO Module', 'all-in-one-seo-pack' ) . '
  • '; echo '
  • ' . __( 'SEO for Categories, Tags and Custom Taxonomies', 'all-in-one-seo-pack' ) . '
  • '; echo '
  • ' . __( 'Social Meta for Categories, Tags and Custom Taxonomies', 'all-in-one-seo-pack' ) . '
  • '; echo '
  • ' . __( 'Advanced Google Analytics tracking', 'all-in-one-seo-pack' ) . '
  • '; echo '
  • ' . __( 'Greater control over display settings', 'all-in-one-seo-pack' ) . '
  • '; echo '
  • ' . __( 'Ad free (no banner adverts)', 'all-in-one-seo-pack' ) . '
  • '; echo '
  • ' . __( 'Access to Video Screencasts', 'all-in-one-seo-pack' ) . '
  • '; echo '
  • ' . __( 'Access to Premium Support Forums', 'all-in-one-seo-pack' ) . '
  • '; echo '
  • ' . __( 'Access to Knowledge Center', 'all-in-one-seo-pack' ) . '
  • '; echo ''; echo sprintf( __( '%1$sClick here%2$s to file a feature request/bug report.', 'all-in-one-seo-pack' ), '', '' ); } } PKH\FbE4display/notice-default.phpnu[notices[ $a_notice_slug ]; $notice_class = 'notice-info'; if ( isset( $notice['class'] ) && ! empty( $notice['class'] ) ) { $notice_class = $notice['class']; } ?>

    $action_option ) : ?>

    PKH\display/notice-aioseop.phpnu[get_notice[ $a_notice_slug ]; $notice_class = 'notice-info'; if ( isset( $notice['class'] ) && ! empty( $notice['class'] ) ) { $notice_class = $notice['class']; } ?>

    $action_option ) : ?>

    PKH\$$display/index.phpnu[ 'aioseop-about' ), admin_url( 'index.php' ) ) ); exit; } /** * Outputs the about screen. */ function about_screen() { aiosp_common::clear_wpe_cache(); $version = AIOSEOP_VERSION; ?>

    »

    PKH\d display/dashboard_widget.phpnu[show_widget() ) { wp_add_dashboard_widget( 'semperplugins-rss-feed', __( 'SEO News', 'all-in-one-seo-pack' ), array( $this, 'display_rss_dashboard_widget', ) ); } } /** * Show Widget * * @since 2.3.10.2 */ function show_widget() { $show = true; if ( apply_filters( 'aioseo_show_seo_news', true ) === false ) { // API filter hook to disable showing SEO News dashboard widget. return false; } global $aioseop_options; if ( AIOSEOPPRO && isset( $aioseop_options['aiosp_showseonews'] ) && ! $aioseop_options['aiosp_showseonews'] ) { return false; } return $show; } /** * Display RSS Dashboard Widget * * @since 2.3.10 */ function display_rss_dashboard_widget() { // check if the user has chosen not to display this widget through screen options. $current_screen = get_current_screen(); $hidden_widgets = get_user_meta( get_current_user_id(), 'metaboxhidden_' . $current_screen->id ); if ( $hidden_widgets && count( $hidden_widgets ) > 0 && is_array( $hidden_widgets[0] ) && in_array( 'semperplugins-rss-feed', $hidden_widgets[0], true ) ) { return; } include_once( ABSPATH . WPINC . '/feed.php' ); $rss_items = get_transient( 'aioseop_feed' ); if ( false === $rss_items ) { $rss = fetch_feed( 'https://www.semperplugins.com/feed/' ); if ( is_wp_error( $rss ) ) { echo __( '{Temporarily unable to load feed.}', 'all-in-one-seo-pack' ); return; } $rss_items = $rss->get_items( 0, 4 ); // Show four items. $cached = array(); foreach ( $rss_items as $item ) { $cached[] = array( 'url' => $item->get_permalink(), 'title' => $item->get_title(), 'date' => $item->get_date( 'M jS Y' ), 'content' => substr( strip_tags( $item->get_content() ), 0, 128 ) . '...', ); } $rss_items = $cached; set_transient( 'aioseop_feed', $cached, 12 * HOUR_IN_SECONDS ); } ?> $upgrade_text", 'manage_options', $url, ); } /* * Opens Upgrade to Pro links in WP Admin as new tab. * * Enqueued here because All_in_One_SEO_Pack_Module::admin_enqueue_scripts does not work. * * @param string $hook * * @since 3.0 */ function admin_enqueue_scripts( $hook ) { wp_enqueue_script( 'aioseop_menu_js', AIOSEOP_PLUGIN_URL . 'js/aioseop-menu.js', array( 'jquery' ), AIOSEOP_VERSION, true ); if ( 'plugins.php' === $hook ) { wp_enqueue_script( 'aioseop_plugins_menu_js', AIOSEOP_PLUGIN_URL . 'js/plugins-menu.js', array( 'jquery' ), AIOSEOP_VERSION, true ); } } } new AIOSEOPAdminMenus(); PKH\BWzzaioseop_module_manager.phpnu[modules['feature_manager'] = null; foreach ( $mod as $m ) { $this->modules[ $m ] = null; } $reset = false; $reset_all = ( isset( $_POST['Submit_All_Default'] ) && '' !== $_POST['Submit_All_Default'] ); $reset = ( ( isset( $_POST['Submit_Default'] ) && '' !== $_POST['Submit_Default'] ) || $reset_all ); $update = ( isset( $_POST['action'] ) && $_POST['action'] && ( ( isset( $_POST['Submit'] ) && '' !== $_POST['Submit'] ) || $reset ) ); if ( $update ) { if ( $reset ) { $this->settings_reset = true; } if ( $reset_all ) { $this->settings_reset_all = true; } if ( 'aiosp_update' === $_POST['action'] ) { $this->settings_update = true; } if ( 'aiosp_update_module' === $_POST['action'] ) { $this->module_settings_update = true; } } $this->do_load_module( 'feature_manager', $mod ); } /** * Return Module * * @since ? * * @param $class * @return $this|bool|mixed */ function return_module( $class ) { global $aiosp; /* This is such a strange comparison! Don't know what the intent is. */ if ( get_class( $aiosp ) === $class ) { return $aiosp; } if ( get_class( $aiosp ) === $class ) { return $this; } foreach ( $this->modules as $m ) { if ( is_object( $m ) && ( get_class( $m ) === $class ) ) { return $m; } } return false; } /** * Get Loaded Module List * * @since ? * * @return array */ function get_loaded_module_list() { $module_list = array(); if ( ! empty( $this->modules ) ) { foreach ( $this->modules as $k => $v ) { if ( ! empty( $v ) ) { $module_list[ $k ] = get_class( $v ); } } } return $module_list; } /** * Do Load Module * * @since ? * * @param $mod Module. * @param null $args * @return bool */ function do_load_module( $mod, $args = null ) { // Module name is used for these automatic settings: // The aiosp_enable_$module settings - whether each plugin is active or not. // The name of the .php file containing the module - aioseop_$module.php. // The name of the class - All_in_One_SEO_Pack_$Module. // The global $aioseop_$module. // $this->modules[$module]. $mod_path = apply_filters( "aioseop_include_$mod", AIOSEOP_PLUGIN_DIR . "modules/aioseop_$mod.php" ); if ( ! empty( $mod_path ) ) { require_once( $mod_path ); } $ref = "aioseop_$mod"; $classname = 'All_in_One_SEO_Pack_' . strtr( ucwords( strtr( $mod, '_', ' ' ) ), ' ', '_' ); $classname = apply_filters( "aioseop_class_$mod", $classname ); $module_class = new $classname( $args ); $GLOBALS[ $ref ] = $module_class; $this->modules[ $mod ] = $module_class; if ( is_user_logged_in() && is_admin_bar_showing() && current_user_can( 'aiosp_manage_seo' ) ) { add_action( 'admin_bar_menu', array( $module_class, 'add_admin_bar_submenu', ), 1001 + $module_class->menu_order() ); } if ( is_admin() ) { add_action( 'aioseop_modules_add_menus', array( $module_class, 'add_menu', ), $module_class->menu_order() ); add_action( 'aiosoep_options_reset', array( $module_class, 'reset_options' ) ); add_filter( 'aioseop_export_settings', array( $module_class, 'settings_export' ) ); } return true; } /** * Load Module * * @since ? * * @param $mod * @return bool */ function load_module( $mod ) { static $feature_options = null; static $feature_prefix = null; if ( ! is_array( $this->modules ) ) { return false; } $v = $this->modules[ $mod ]; if ( null !== $v ) { return false; } // Already loaded. if ( 'performance' === $mod && ! is_super_admin() ) { return false; } if ( ( 'file_editor' === $mod ) && ( ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ) || ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) || ! is_super_admin() ) ) { return false; } $mod_enable = false; $is_module_page = isset( $_REQUEST['page'] ) && trailingslashit( AIOSEOP_PLUGIN_DIRNAME ) . 'modules/aioseop_feature_manager.php' === $_REQUEST['page']; if ( defined( 'AIOSEOP_UNIT_TESTING' ) ) { // using $_REQUEST does not work because even if the parameter is set in $_POST or $_GET, it does not percolate to $_REQUEST. $is_module_page = ( isset( $_GET['page'] ) && trailingslashit( AIOSEOP_PLUGIN_DIRNAME ) . 'modules/aioseop_feature_manager.php' === $_GET['page'] ) || ( isset( $_POST['page'] ) && trailingslashit( AIOSEOP_PLUGIN_DIRNAME ) . 'modules/aioseop_feature_manager.php' === $_POST['page'] ); } $fm_page = $this->module_settings_update && wp_verify_nonce( $_POST['nonce-aioseop'], 'aioseop-nonce' ) && $is_module_page; if ( $fm_page && ! $this->settings_reset ) { if ( isset( $_POST[ "aiosp_feature_manager_enable_$mod" ] ) ) { $mod_enable = $_POST[ "aiosp_feature_manager_enable_$mod" ]; } else { $mod_enable = false; } } else { if ( null === $feature_prefix ) { $feature_prefix = $this->modules['feature_manager']->get_prefix(); } if ( $fm_page && $this->settings_reset ) { $feature_options = $this->modules['feature_manager']->default_options(); } if ( null === $feature_options ) { if ( $this->module_settings_update && $this->settings_reset_all && wp_verify_nonce( $_POST['nonce-aioseop'], 'aioseop-nonce' ) ) { $feature_options = $this->modules['feature_manager']->default_options(); } else { $feature_options = $this->modules['feature_manager']->get_current_options(); } } if ( isset( $feature_options[ "{$feature_prefix}enable_$mod" ] ) ) { $mod_enable = $feature_options[ "{$feature_prefix}enable_$mod" ]; } } if ( $mod_enable ) { return $this->do_load_module( $mod ); } return false; } function load_modules() { if ( is_array( $this->modules ) ) { foreach ( $this->modules as $k => $v ) { $this->load_module( $k ); } } } } } PKH\aioseop_screens, * array('CUSTOM') = specific screen(s). * } * } */ public $notices = array(); /** * List of notice slugs that are currently active. * NOTE: Amount is reduced by 1 second in order to display at exactly X amount of time. * * @todo Change name to $display_times for consistancy both conceptually and with usermeta structure. * * @since 3.0 * @access public * * @var array $active_notices { * @type string|int $slug => $display_time Contains the current active notices * that are scheduled to be displayed. * } */ public $active_notices = array(); /** * Dismissed Notices * * Stores notices that have been dismissed sitewide. Users are stored in usermeta data 'aioseop_notice_dismissed_{$slug}'. * * @since 3.0 * * @var array $dismissed { * @type boolean $notice_slug => $is_dismissed True if dismissed. * } */ public $dismissed = array(); /** * The default dismiss time. An anti-nag setting. * * @var int $default_dismiss_delay */ private $default_dismiss_delay = 180; /** * List of Screens used in AIOSEOP. * * @since 3.0 * * @var array $aioseop_screens { * @type string Screen ID. * } */ private $aioseop_screens = array(); /** * __constructor. * * @since 3.0 */ public function __construct() { // DirectoryIterator::getExtension() was added in PHP 5.3.6. We can remove this once we drop support < PHP 5.3. if ( version_compare( phpversion(), '5.3.6', '<' ) ) { return false; } $this->_requires(); $this->obj_load_options(); if ( current_user_can( 'aiosp_manage_seo' ) ) { $this->aioseop_screens[] = 'toplevel_page_' . AIOSEOP_PLUGIN_DIRNAME . '/aioseop_class'; $this->aioseop_screens[] = 'all-in-one-seo_page_' . AIOSEOP_PLUGIN_DIRNAME . '/modules/aioseop_performance'; $this->aioseop_screens[] = 'all-in-one-seo_page_' . AIOSEOP_PLUGIN_DIRNAME . '/modules/aioseop_sitemap'; $this->aioseop_screens[] = 'all-in-one-seo_page_aiosp_opengraph'; $this->aioseop_screens[] = 'all-in-one-seo_page_aiosp_robots_generator'; $this->aioseop_screens[] = 'all-in-one-seo_page_' . AIOSEOP_PLUGIN_DIRNAME . '/modules/aioseop_robots'; $this->aioseop_screens[] = 'all-in-one-seo_page_' . AIOSEOP_PLUGIN_DIRNAME . '/modules/aioseop_file_editor'; $this->aioseop_screens[] = 'all-in-one-seo_page_' . AIOSEOP_PLUGIN_DIRNAME . '/modules/aioseop_importer_exporter'; $this->aioseop_screens[] = 'all-in-one-seo_page_' . AIOSEOP_PLUGIN_DIRNAME . '/modules/aioseop_bad_robots'; $this->aioseop_screens[] = 'all-in-one-seo_page_' . AIOSEOP_PLUGIN_DIRNAME . '/modules/aioseop_feature_manager'; add_action( 'admin_init', array( $this, 'init' ) ); add_action( 'current_screen', array( $this, 'admin_screen' ) ); } } /** * _Requires * * Internal use only. Additional files required. * * @since 3.0 */ private function _requires() { $this->autoload_notice_files(); } /** * Autoload Notice Files * * @since 3.0 * * @see DirectoryIterator class * @link https://php.net/manual/en/class.directoryiterator.php * @see StackOverflow for getting all filenamess in a directory. * @link https://stackoverflow.com/a/25988433/1376780 */ private function autoload_notice_files() { foreach ( new DirectoryIterator( AIOSEOP_PLUGIN_DIR . 'admin/display/notices/' ) as $file ) { if ( $file->isFile() && 'php' === $file->getExtension() ) { $filename = $file->getFilename(); // Qualified file pattern; "*-notice.php". // Prevents any malicious files that may have spreaded. if ( array_search( 'notice', explode( '-', str_replace( '.php', '', $filename ) ), true ) ) { include_once AIOSEOP_PLUGIN_DIR . 'admin/display/notices/' . $filename; } } } } /** * Early operations required by the plugin. * * AJAX requires being added early before screens have been loaded. * * @since 3.0 */ public function init() { add_action( 'wp_ajax_aioseop_notice', array( $this, 'ajax_notice_action' ) ); } /** * Setup/Init Admin Screen * * Adds the initial actions to WP based on the Admin Screen being loaded. * The AIOSEOP and Other Screens have separate methods that are used, and * additional screens can be made exclusive/unique. * * @since 3.0 * * @param WP_Screen $current_screen The current screen object being loaded. */ public function admin_screen( $current_screen ) { $this->deregister_scripts(); if ( isset( $current_screen->id ) && in_array( $current_screen->id, $this->aioseop_screens, true ) ) { // AIOSEO Notice Content. add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); add_action( 'all_admin_notices', array( $this, 'display_notice_aioseop' ) ); } elseif ( isset( $current_screen->id ) ) { // Default WP Notice. add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); add_action( 'all_admin_notices', array( $this, 'display_notice_default' ) ); } } /** * Load AIOSEOP_Notice Options * * Gets the options for AIOSEOP_Notice to set its variables to. * * @since 3.0 * @access private * * @see self::notices * @see self::active_notices */ private function obj_load_options() { $notices_options = $this->obj_get_options(); $this->notices = $notices_options['notices']; $this->active_notices = $notices_options['active_notices']; } /** * Get AIOSEOP_Notice Options * * @since 3.0 * @access private * * @return array */ private function obj_get_options() { $defaults = array( 'notices' => array(), 'active_notices' => array(), ); // Prevent old data from being loaded instead. // Some notices are instant notifications. wp_cache_delete( 'aioseop_notices', 'options' ); $notices_options = get_option( 'aioseop_notices' ); if ( false === $notices_options ) { return $defaults; } return wp_parse_args( $notices_options, $defaults ); } /** * Update Notice Options * * @since 3.0 * @access private * * @return boolean True if successful, using update_option() return value. */ private function obj_update_options() { $notices_options = array( 'notices' => $this->notices, 'active_notices' => $this->active_notices, ); $old_notices_options = $this->obj_get_options(); $notices_options = wp_parse_args( $notices_options, $old_notices_options ); // Prevent old data from being loaded instead. // Some notices are instant notifications. wp_cache_delete( 'aioseop_notices', 'options' ); return update_option( 'aioseop_notices', $notices_options, false ); } /** * Notice Default Values * * Returns the default value for a variable to be used in self::notices[]. * * @since 3.0 * * @see AIOSEOP_Notices::notices Array variable that stores the collection of notices. * * @return array Notice variable in self::notices. */ public function notice_defaults() { return array_merge( $this->notice_defaults_server(), $this->notice_defaults_file() ); } /** * Notice Defaults Server * * @since 3.0 * * @return array */ public function notice_defaults_server() { return array( 'slug' => '', 'time_start' => time(), 'time_set' => time(), ); } /** * Notice Defaults File * * @since 3.0 * * @return array */ public function notice_defaults_file() { return array( 'slug' => '', 'delay_time' => 0, 'message' => '', 'action_options' => array(), 'class' => 'notice-info', 'target' => 'site', 'screens' => array(), ); } /** * Action Options Default Values * * Returns the default value for action_options in self::notices[$slug]['action_options']. * * @since 3.0 * * @return array Action_Options variable in self::notices[$slug]['action_options']. */ public function action_options_defaults() { return array( 'time' => 0, 'text' => __( 'Dismiss', 'all-in-one-seo-pack' ), 'link' => '#', 'dismiss' => true, 'class' => '', ); } /** * Add Notice * * Takes notice and adds it to object and saves to database. * * @since 3.0 * * @param array $notice See self::notices for more info. * @return boolean True on success. */ public function add_notice( $notice = array() ) { if ( empty( $notice['slug'] ) || isset( $this->notices[ $notice['slug'] ] ) ) { return false; } $this->notices[ $notice['slug'] ] = $this->prepare_notice( $notice ); return true; } /** * Prepare Insert/Undate Notice * * @since 3.0 * * @param array $notice The notice to prepare with the database. * @return array */ public function prepare_notice( $notice = array() ) { $notice_default = $this->notice_defaults_server(); $notice = wp_parse_args( $notice, $notice_default ); $new_notice = array(); foreach ( $notice_default as $key => $value ) { $new_notice[ $key ] = $notice[ $key ]; } return $new_notice; } /** * Used strictly for any notices that are deprecated/obsolete. To stop notices, * use notice_deactivate(). * * @since 3.0 * * @param string $slug Unique notice slug. * @return boolean True if successfully removed. */ public function remove_notice( $slug ) { if ( isset( $this->notices[ $slug ] ) ) { $this->deactivate_notice( $slug ); unset( $this->notices[ $slug ] ); $this->obj_update_options(); return true; } return false; } /** * Activate Notice * * Activates a notice, or Re-activates with a new display time. Used after * updating a notice that requires a hard reset. * * @since 3.0 * * @param string $slug Notice slug. * @return boolean */ public function activate_notice( $slug ) { if ( empty( $slug ) ) { return false; } $notice = $this->get_notice( $slug ); if ( 'site' === $notice['target'] && isset( $this->active_notices[ $slug ] ) ) { return true; } elseif ( 'user' === $notice['target'] && get_user_meta( get_current_user_id(), 'aioseop_notice_display_time_' . $slug, true ) ) { return true; } if ( ! isset( $this->notices[ $slug ] ) ) { $this->add_notice( $notice ); } $this->set_notice_delay( $slug, $notice['delay_time'] ); $this->obj_update_options(); return true; } /** * Deactivate Notice * * Deactivates a notice set as active and completely removes it from the * list of active notices. Used to prevent conflicting notices that may be * active at any given point in time. * * @since 3.0 * * @param string $slug Notice slug. * @return boolean */ public function deactivate_notice( $slug ) { if ( ! isset( $this->active_notices[ $slug ] ) ) { return false; } elseif ( ! isset( $this->notices[ $slug ] ) ) { return false; } delete_metadata( 'user', 0, 'aioseop_notice_display_time_' . $slug, '', true ); unset( $this->active_notices[ $slug ] ); $this->obj_update_options(); return true; } /** * Reset Notice * * @since 3.0 * * @param string $slug The notice's slug. * @return bool */ public function reset_notice( $slug ) { if ( empty( $slug ) || ( ! isset( $this->notices[ $slug ] ) && ! get_user_meta( get_current_user_id(), 'aioseop_notice_display_time_' . $slug, true ) && ! get_user_meta( get_current_user_id(), 'aioseop_notice_dismissed_' . $slug, true ) ) ) { return false; } $notice = $this->get_notice( $slug ); unset( $this->active_notices[ $slug ] ); unset( $this->dismissed[ $slug ] ); delete_metadata( 'user', 0, 'aioseop_notice_time_set_' . $slug, '', true ); delete_metadata( 'user', 0, 'aioseop_notice_display_time_' . $slug, '', true ); delete_metadata( 'user', 0, 'aioseop_notice_dismissed_' . $slug, '', true ); $this->set_notice_delay( $slug, $notice['delay_time'] ); $this->obj_update_options(); return true; } /** * Set Notice Delay * * @since 3.0 * * @param string $slug The notice's slug. * @param int $delay_time Amount of time to delay. * @return boolean */ public function set_notice_delay( $slug, $delay_time ) { if ( empty( $slug ) ) { return false; } $time_set = time(); // Display at exactly X time, not (X + 1) time. $display_time = $time_set + $delay_time - 1; $notice = $this->get_notice( $slug ); if ( 'user' === $notice['target'] ) { $current_user_id = get_current_user_id(); update_user_meta( $current_user_id, 'aioseop_notice_time_set_' . $slug, $time_set ); update_user_meta( $current_user_id, 'aioseop_notice_display_time_' . $slug, $display_time ); } $this->notices[ $slug ]['time_set'] = $time_set; $this->notices[ $slug ]['time_start'] = $display_time; $this->active_notices[ $slug ] = $display_time; return true; } /** * Set Notice Dismiss * * @since 3.0 * * @param string $slug The notice's slug. * @param boolean $dismiss Sets to dismiss a notice. */ public function set_notice_dismiss( $slug, $dismiss ) { $notice = $this->get_notice( $slug ); if ( 'site' === $notice['target'] ) { $this->dismissed[ $slug ] = $dismiss; } elseif ( 'user' === $notice['target'] ) { $current_user_id = get_current_user_id(); update_user_meta( $current_user_id, 'aioseop_notice_dismissed_' . $slug, $dismiss ); } } /** * Get Notice * * @since 3.0 * * @param string $slug The notice's slug. * @return array */ public function get_notice( $slug ) { // Set defaults for notice. $rtn_notice = $this->notice_defaults(); if ( isset( $this->notices[ $slug ] ) ) { // Get minimized (database) data. $rtn_notice = array_merge( $rtn_notice, $this->notices[ $slug ] ); } /** * Admin Notice {$slug} * * Applies the notice data values for a given notice slug. * `aioseop_admin_notice-{$slug}` with the slug being the individual notice. * * @since 3.0 * * @params array $notice_data See `\AIOSEOP_Notices::$notices` for structural documentation. */ $notice_data = apply_filters( 'aioseop_admin_notice-' . $slug, array() ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores if ( ! empty( $notice_data ) ) { $rtn_notice = array_merge( $rtn_notice, $notice_data ); foreach ( $rtn_notice['action_options'] as &$action_option ) { // Set defaults for `$notice['action_options']`. $action_option = array_merge( $this->action_options_defaults(), $action_option ); } } return $rtn_notice; } /*** DISPLAY Methods **************************************************/ /** * Deregister Scripts * * Initial Admin Screen action to remove aioseop script(s) from all screens; * which will be registered if executed on screen. * NOTE: As of 3.0, most of it is default layout, styling, & scripting * that is loaded on all pages. Which can later be different. * * @since 3.0 * @access private * * @see self::admin_screen() */ private function deregister_scripts() { wp_deregister_script( 'aioseop-admin-notice-js' ); wp_deregister_style( 'aioseop-admin-notice-css' ); } /** * (Register) Enqueue Scripts * * Used to register, enqueue, and localize any JS data. Styles can later be added. * * @since 3.0 */ public function admin_enqueue_scripts() { // Register. wp_register_script( 'aioseop-admin-notice-js', AIOSEOP_PLUGIN_URL . 'js/admin-notice.js', array( 'jquery' ), AIOSEOP_VERSION, true ); // Localization. $notice_actions = array(); foreach ( $this->active_notices as $notice_slug => $notice_display_time ) { $notice = $this->get_notice( $notice_slug ); foreach ( $notice['action_options'] as $action_index => $action_arr ) { $notice_actions[ $notice_slug ][] = $action_index; } } $admin_notice_localize = array( 'notice_nonce' => wp_create_nonce( 'aioseop_ajax_notice' ), 'notice_actions' => $notice_actions, ); wp_localize_script( 'aioseop-admin-notice-js', 'aioseop_notice_data', $admin_notice_localize ); // Enqueue. wp_enqueue_script( 'aioseop-admin-notice-js' ); wp_enqueue_style( 'aioseop-admin-notice-css', AIOSEOP_PLUGIN_URL . 'css/admin-notice.css', false, AIOSEOP_VERSION, false ); } /** * Display Notice as Default * * Method for default WP Admin notices. * NOTE: As of 3.0, display_notice_default() & display_notice_aioseop() * have the same functionality, but serves as a future development concept. * * @since 3.0 * * @uses AIOSEOP_PLUGIN_DIR . 'admin/display/notice-default.php' Template for default notices. * * @return void */ public function display_notice_default() { $this->display_notice( 'default' ); } /** * Display Notice as AIOSEOP Screens * * Method for Admin notices exclusive to AIOSEOP screens. * NOTE: As of 3.0, display_notice_default() & display_notice_aioseop() * have the same functionality, but serves as a future development concept. * * @since 3.0 * * @uses AIOSEOP_PLUGIN_DIR . 'admin/display/notice-aioseop.php' Template for notices. * * @return void */ public function display_notice_aioseop() { $this->display_notice( 'aioseop' ); } /** * Display Notice * * @since 2.8 * * @param string $template Slug name for template. */ public function display_notice( $template ) { if ( ! wp_script_is( 'aioseop-admin-notice-js', 'enqueued' ) || ! wp_style_is( 'aioseop-admin-notice-css', 'enqueued' ) ) { return; } elseif ( 'default' !== $template && 'aioseop' !== $template ) { return; } elseif ( ! current_user_can( 'aiosp_manage_seo' ) ) { return; } $current_screen = get_current_screen(); $current_user_id = get_current_user_id(); foreach ( $this->active_notices as $a_notice_slug => $a_notice_time_display ) { // vvv TEMP Avoid review notice. if ( 'review_plugin' === $a_notice_slug ) { continue; } // ^^^ TEMP Avoid review notice. $notice_show = true; $notice = $this->get_notice( $a_notice_slug ); // Screen Restriction. if ( ! empty( $notice['screens'] ) ) { // Checks if on aioseop screen. if ( in_array( 'aioseop', $notice['screens'], true ) ) { if ( ! in_array( $current_screen->id, $this->aioseop_screens, true ) ) { continue; } } // Checks the other screen restrictions by slug/id. if ( ! in_array( 'aioseop', $notice['screens'], true ) ) { if ( ! in_array( $current_screen->id, $notice['screens'], true ) ) { continue; } } } if ( isset( $this->dismissed[ $a_notice_slug ] ) && $this->dismissed[ $a_notice_slug ] ) { $notice_show = false; } // User Settings. if ( 'user' === $notice['target'] ) { $user_dismissed = get_user_meta( $current_user_id, 'aioseop_notice_dismissed_' . $a_notice_slug, true ); if ( ! $user_dismissed ) { $user_notice_time_display = get_user_meta( $current_user_id, 'aioseop_notice_display_time_' . $a_notice_slug, true ); if ( ! empty( $user_notice_time_display ) ) { $a_notice_time_display = intval( $user_notice_time_display ); } } else { $notice_show = false; } } // Display/Render. $important_admin_notices = array( 'notice-error', 'notice-warning', 'notice-do-nag', ); if ( defined( 'DISABLE_NAG_NOTICES' ) && true === DISABLE_NAG_NOTICES && ( ! in_array( $notice['class'], $important_admin_notices, true ) ) ) { // Skip if `DISABLE_NAG_NOTICES` is implemented (as true). // Important notices, WP's CSS `notice-error` & `notice-warning`, are still rendered. continue; } elseif ( time() > $a_notice_time_display && $notice_show ) { include AIOSEOP_PLUGIN_DIR . 'admin/display/notice-' . $template . '.php'; } } } /** * AJAX Notice Action * * Fires when a Action_Option is clicked and sent via AJAX. Also includes * WP Default Dismiss (rendered as a clickable button on upper-right). * * @since 3.0 * * @see AIOSEOP_PLUGIN_DIR . 'js/admin-notice.js' */ public function ajax_notice_action() { check_ajax_referer( 'aioseop_ajax_notice' ); if ( ! current_user_can( 'aiosp_manage_seo' ) ) { wp_send_json_error( __( "User doesn't have `aiosp_manage_seo` capabilities.", 'all-in-one-seo-pack' ) ); } // Notice (Slug) => (Action_Options) Index. $notice_slug = null; $action_index = null; if ( isset( $_POST['notice_slug'] ) ) { $notice_slug = filter_input( INPUT_POST, 'notice_slug', FILTER_SANITIZE_STRING ); // When PHPUnit is unable to use filter_input. if ( defined( 'AIOSEOP_UNIT_TESTING' ) && null === $notice_slug && ! empty( $_POST['notice_slug'] ) ) { $notice_slug = $_POST['notice_slug']; } } if ( isset( $_POST['action_index'] ) ) { $action_index = filter_input( INPUT_POST, 'action_index', FILTER_SANITIZE_STRING ); // When PHPUnit is unable to use filter_input. if ( defined( 'AIOSEOP_UNIT_TESTING' ) && null === $action_index && ( ! empty( $_POST['action_index'] ) || 0 === $_POST['action_index'] ) ) { $action_index = $_POST['action_index']; } } if ( empty( $notice_slug ) ) { /* Translators: Displays the hordcoded slug that missing. */ wp_send_json_error( sprintf( __( 'Missing values from `%s`.', 'all-in-one-seo-pack' ), 'notice_slug' ) ); } elseif ( empty( $action_index ) && 0 !== $action_index ) { /* Translators: Displays the hordcoded slug that missing. */ wp_send_json_error( sprintf( __( 'Missing values from `%s`.', 'all-in-one-seo-pack' ), 'action_index' ) ); } $action_options = $this->action_options_defaults(); $action_options['time'] = $this->default_dismiss_delay; $action_options['dismiss'] = false; $notice = $this->get_notice( $notice_slug ); if ( isset( $notice['action_options'][ $action_index ] ) ) { $action_options = array_merge( $action_options, $notice['action_options'][ $action_index ] ); } if ( $action_options['time'] ) { $this->set_notice_delay( $notice_slug, $action_options['time'] ); } if ( $action_options['dismiss'] ) { $this->set_notice_dismiss( $notice_slug, $action_options['dismiss'] ); } $this->obj_update_options(); wp_send_json_success( __( 'Notice updated successfully.', 'all-in-one-seo-pack' ) ); } } // CLASS INITIALIZATION. // Should this be a singleton class instead of a global? global $aioseop_notices; $aioseop_notices = new AIOSEOP_Notices(); } PKH\1a J Jclass-aioseop-helper.phpnu[_set_help_text( $module ); } } /** * Set this Help Text * * Sets the Help Text according to the module/class in use, but if there is * no class name in $module, then this Help Text will add all module help texts. * * @ignore * @since 3.0 * @access private * * @param string $module All_in_One_SEO_Pack module. */ private function _set_help_text( $module ) { switch ( $module ) { case 'All_in_One_SEO_Pack': $this->help_text = $this->help_text_general(); $this->help_text = array_merge( $this->help_text, $this->help_text_post_meta() ); break; case 'All_in_One_SEO_Pack_Performance': $this->help_text = $this->help_text_performance(); break; case 'All_in_One_SEO_Pack_Sitemap': $this->help_text = $this->help_text_sitemap(); break; case 'All_in_One_SEO_Pack_Opengraph': $this->help_text = $this->help_text_opengraph(); break; case 'All_in_One_SEO_Pack_Robots': $this->help_text = $this->help_text_robots_generator(); break; case 'All_in_One_SEO_Pack_File_Editor': $this->help_text = $this->help_text_file_editor(); break; case 'All_in_One_SEO_Pack_Importer_Exporter': $this->help_text = $this->help_text_importer_exporter(); break; case 'All_in_One_SEO_Pack_Bad_Robots': $this->help_text = $this->help_text_bad_robots(); break; } /** * Set Help Text * * @since 3.0 * * @param array $this->help_text Contains an array of help text for each setting. * @param string $module Shows which class module is using the function. */ $this->help_text = apply_filters( 'aioseop_helper_set_help_text', $this->help_text, $module ); } /** * Help Text General Settings * * @ignore * @since 2.4.2 * @access private * * @return array */ private function help_text_general() { /* * Consider changing the construction of the macros. * * The name of the macro should NOT be inside _e() or __() because it does not make sense as it * won't change with the language. * * Moreover, it will confuse WPCS and it will try to replace %c (as in %category%) to %$1c. * Placeholder %s (%something) has been bug fixed. * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/698 */ // phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment // phpcs:disable WordPress.WP.I18n.UnorderedPlaceholdersText $rtn_help_text = array( // General Settings. 'aiosp_can' => __( 'This option will automatically generate Canonical URLs for your entire WordPress installation. This will help to prevent duplicate content penalties by Google.', 'all-in-one-seo-pack' ), 'aiosp_no_paged_canonical_links' => __( 'Checking this option will set the Canonical URL for all paginated content to the first page.', 'all-in-one-seo-pack' ), 'aiosp_use_original_title' => __( 'Use wp_title to get the title used by the theme; this is disabled by default. If you use this option, set your title formats appropriately, as your theme might try to do its own title SEO as well.', 'all-in-one-seo-pack' ), 'aiosp_schema_markup' => __( 'This enables Schema.org structured data markup for rich snippets in search results.', 'all-in-one-seo-pack' ), /* translators: %s is a placeholder, which means that it should not be translated. It will be replaced with the name of the plugin, All in One SEO Pack. */ 'aiosp_do_log' => sprintf( __( 'Check this and %s will create a log of important events (all-in-one-seo-pack.log) in the wp-content directory which might help debugging. Make sure this directory is writable.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME ), // Home Page Settings. 'aiosp_home_title' => __( 'As the name implies, this will be the Meta Title of your homepage. This is independent of any other option. If not set, the default Site Title (found in WordPress under Settings, General, Site Title) will be used.', 'all-in-one-seo-pack' ), 'aiosp_home_description' => __( 'This will be the Meta Description for your homepage. This is independent of any other option. The default is no Meta Description at all if this is not set.', 'all-in-one-seo-pack' ), 'aiosp_home_keywords' => __( 'Enter a comma separated list of your most important keywords for your site that will be written as Meta Keywords on your homepage. Do not stuff everything in here.', 'all-in-one-seo-pack' ), 'aiosp_use_static_home_info' => __( 'Checking this option uses the title, description, and keywords set on your static Front Page.', 'all-in-one-seo-pack' ), // Title Settings. 'aiosp_home_page_title_format' => __( 'This controls the format of the title tag for your Homepage.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %page_title%
    ' . /* translators: %s is replaced with a content type such as Post, Page, etc. */ '
    ' . sprintf( __( 'The original title of the %s', 'all-in-one-seo-pack' ), __( 'Homepage', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_login%
    ' . /* translators: Example sentence: "The first name of the author of the Post" */ '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'username', 'all-in-one-seo-pack' ), __( 'Homepage', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_nicename%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), /* translators: The "nicename" is the sanitized version of a username. */ __( 'nicename', 'all-in-one-seo-pack' ), __( 'Homepage', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_firstname%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'first name', 'all-in-one-seo-pack' ), __( 'Homepage', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_lastname%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'last name', 'all-in-one-seo-pack' ), __( 'Homepage', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_date%
    ' . /* translators: %s is replaced with a time related term such as Date, Year, Month, etc. */ '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_year%
    ' . /* translators: %s is replaced with a time related term such as Date, Year, Month, etc. */ '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month_i18n%
    ' . /* translators: %s is replaced with a time related term such as Date, Year, Month, etc. */ '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %cf_fieldname%
    ' . '
    ' . __( 'The name of a custom field', 'all-in-one-seo-pack' ) . '
    ' . '
    ', 'aiosp_page_title_format' => __( 'This controls the format of the title tag for Pages.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %page_title%
    ' . '
    ' . sprintf( __( 'The original title of the %s', 'all-in-one-seo-pack' ), __( 'Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_login%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'username', 'all-in-one-seo-pack' ), __( 'Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_nicename%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'nicename', 'all-in-one-seo-pack' ), __( 'Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_firstname%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'first name', 'all-in-one-seo-pack' ), __( 'Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_lastname%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'last name', 'all-in-one-seo-pack' ), __( 'Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_date%
    ' . /* translators: %s is replaced with a time related term such as Date, Year, Month, etc. */ '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_year%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month_i18n%
    ' . '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_date%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ), __( 'Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_year%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ), __( 'Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_month%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ), __( 'Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %cf_fieldname%
    ' . '
    ' . __( 'The name of a custom field', 'all-in-one-seo-pack' ) . '
    ' . '
    ', 'aiosp_post_title_format' => __( 'This controls the format of the title tag for Posts.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %post_title%
    ' . '
    ' . sprintf( __( 'The original title of the %s', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %category_title%
    ' . /* translators: %s is replaced with a content type such as Post, Page, etc. */ '
    ' . sprintf( __( 'The (main) Category of the %s', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_login%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'username', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_nicename%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'nicename', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_firstname%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'first name', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %page_author_lastname%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'last name', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_date%
    ' . '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_year%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month_i18n%
    ' . '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_date%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_year%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_month%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %cf_fieldname%
    ' . '
    ' . __( 'The name of a custom field', 'all-in-one-seo-pack' ) . '
    ' . '
    ', 'aiosp_category_title_format' => __( 'This controls the format of the title tag for Category Archives.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %category_title%
    ' . '
    ' . sprintf( __( 'The original title of the %s', 'all-in-one-seo-pack' ), __( 'Category', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %category_description%
    ' . /* translators: %s is replaced with a content type such as Post, Page, etc. */ '
    ' . sprintf( __( 'The description of the %s', 'all-in-one-seo-pack' ), __( 'Category', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_year%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month_i18n%
    ' . '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    ', 'aiosp_archive_title_format' => __( 'This controls the format of the title tag for Custom Post Archives.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %archive_title%
    ' . '
    ' . sprintf( __( 'The original title of the %s', 'all-in-one-seo-pack' ), /* translators: "Archive" is used in the context of a WordPress archive page. */ __( 'Archive', 'all-in-one-seo-pack' ) ) . '
    ' . '
    ', 'aiosp_date_title_format' => __( 'This controls the format of the title tag for Date Archives.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %date%
    ' . '
    ' . __( 'The original archive title (localized), e.g. "2019" or "2019 August"', 'all-in-one-seo-pack' ) . '
    ' . '
    %day%
    ' . '
    ' . __( 'The original archive day, e.g. "17"', 'all-in-one-seo-pack' ) . '
    ' . '
    %month%
    ' . '
    ' . __( 'The original archive month (localized), e.g. "August"', 'all-in-one-seo-pack' ) . '
    ' . '
    %year%
    ' . '
    ' . __( 'The original archive year, e.g. "2019"', 'all-in-one-seo-pack' ) . '
    ' . '
    ', 'aiosp_author_title_format' => __( 'This controls the format of the title tag for Author Archives.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %author%
    ' . '
    ' . __( 'The original archive title, e.g. "Steve" or "John Smith"', 'all-in-one-seo-pack' ) . '
    ' . '
    ', 'aiosp_tag_title_format' => __( 'This controls the format of the title tag for Tag Archives.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %tag%
    ' . '
    ' . sprintf( __( 'The name of the %s', 'all-in-one-seo-pack' ), __( 'Tag', 'all-in-one-seo-pack' ) ) . '
    ' . '
    ', 'aiosp_search_title_format' => __( 'This controls the format of the title tag for the Search page.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %search%
    ' . '
    ' . __( 'The search term that was entered', 'all-in-one-seo-pack' ) . '
    ' . '
    ', 'aiosp_description_format' => __( 'This controls the format of Meta Descriptions. The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %description%
    ' . '
    ' . __( 'This outputs the description you write for each page/post or the autogenerated description, if enabled. Auto-generated descriptions are generated from the excerpt or the first 160 characters of the content if there is no excerpt.', 'all-in-one-seo-pack' ) . '
    ' . '
    %post_title%
    ' . '
    ' . sprintf( __( 'The original title of the %s', 'all-in-one-seo-pack' ), __( 'Post', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %wp_title%
    ' . '
    ' . __( 'The original WordPress title', 'all-in-one-seo-pack' ) . '
    ' . '
    %current_date%
    ' . '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_year%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month_i18n%
    ' . '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_date%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ), /* translators: "Post/Page" are the two main content types in WordPress. */ __( 'Post/Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_year%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ), __( 'Post/Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_month%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ), __( 'Post/Page', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %cf_fieldname%
    ' . '
    ' . __( 'The name of a custom field', 'all-in-one-seo-pack' ) . '
    ' . '
    ', 'aiosp_404_title_format' => __( 'This controls the format of the title tag for the 404 page.', 'all-in-one-seo-pack' ) . '
    ' . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %request_url%
    ' . '
    ' . __( 'The original URL path, like "/url-that-does-not-exist/"', 'all-in-one-seo-pack' ) . '
    ' . '
    %request_words%
    ' . '
    ' . __( 'The URL path in human readable form, like "Url That Does Not Exist"', 'all-in-one-seo-pack' ) . '
    ' . '
    %404_title%
    ' . '
    ' . __( 'Additional 404 title input', 'all-in-one-seo-pack' ) . '
    ' . '
    ', 'aiosp_paged_format' => __( 'This string gets appended/prepended to titles of paged index pages (like home or archive pages).', 'all-in-one-seo-pack' ) . __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . '
    %page%
    ' . '
    ' . __( 'The page number', 'all-in-one-seo-pack' ) . '
    ' . '
    ', //phpcs:enable // Custom Post Type Settings. /* translators: %s is a placeholder, which means that it should not be translated. It will be replaced with the name of the plugin, All in One SEO Pack. */ 'aiosp_cpostactive' => sprintf( __( 'Use these checkboxes to select which Content Types you want to use %s with.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME ), // Display Settings. 'aiosp_posttypecolumns' => __( 'This lets you select which screens display the SEO Title, SEO Keywords and SEO Description columns.', 'all-in-one-seo-pack' ), // Webmaster Verification. 'aiosp_google_verify' => __( 'Enter your verification code here to verify your site with Google Search Console.', 'all-in-one-seo-pack' ), 'aiosp_bing_verify' => __( 'Enter your verification code here to verify your site with Bing Webmaster Tools.', 'all-in-one-seo-pack' ), 'aiosp_pinterest_verify' => __( 'Enter your verification code here to verify your site with Pinterest.', 'all-in-one-seo-pack' ), 'aiosp_yandex_verify' => __( 'Enter your verification code here to verify your site with Yandex Webmaster Tools.', 'all-in-one-seo-pack' ), 'aiosp_baidu_verify' => __( 'Enter your verification code here to verify your site with Baidu Webmaster Tools.', 'all-in-one-seo-pack' ), // Google Analytics. 'aiosp_google_analytics_id' => __( 'Enter your Google Analytics ID here to track visitor behavior on your site using Google Analytics.', 'all-in-one-seo-pack' ), 'aiosp_ga_advanced_options' => __( 'Check to use advanced Google Analytics options.', 'all-in-one-seo-pack' ), 'aiosp_ga_domain' => __( 'Enter your domain name without the http:// to set your cookie domain.', 'all-in-one-seo-pack' ), 'aiosp_ga_multi_domain' => __( 'Use this option to enable tracking of multiple or additional domains.', 'all-in-one-seo-pack' ), 'aiosp_ga_addl_domains' => __( 'Add a list of additional domains to track here. Enter one domain name per line without the http://.', 'all-in-one-seo-pack' ), 'aiosp_ga_anonymize_ip' => __( 'This enables support for IP Anonymization in Google Analytics.', 'all-in-one-seo-pack' ), 'aiosp_ga_display_advertising' => __( 'This enables support for the Display Advertiser Features in Google Analytics.', 'all-in-one-seo-pack' ), 'aiosp_ga_exclude_users' => __( 'Exclude logged-in users from Google Analytics tracking by role.', 'all-in-one-seo-pack' ), 'aiosp_ga_track_outbound_links' => __( 'Check this if you want to track outbound links with Google Analytics.', 'all-in-one-seo-pack' ), 'aiosp_ga_link_attribution' => __( 'This enables support for the Enhanced Link Attribution in Google Analytics.', 'all-in-one-seo-pack' ), 'aiosp_ga_enhanced_ecommerce' => __( 'This enables support for the Enhanced Ecommerce in Google Analytics.', 'all-in-one-seo-pack' ), // Schema Settings. 'aiosp_schema_search_results_page' => __( 'Select this to output markup that notifies Google to display the Sitelinks Search Box within certain search results.', 'all-in-one-seo-pack' ), 'aiosp_schema_social_profile_links' => __( 'Add the URLs for your website\'s social profiles here (Facebook, Twitter, Instagram, LinkedIn, etc.), one per line. These may be used in rich search results such as Google Knowledge Graph.', 'all-in-one-seo-pack' ), 'aiosp_schema_site_represents' => __( 'Select whether your website is primarily for a person or an organization.', 'all-in-one-seo-pack' ), 'aiosp_schema_organization_name' => __( 'Enter your organization or business name.', 'all-in-one-seo-pack' ), 'aiosp_schema_organization_logo' => __( 'Add a logo that represents your organization or business. The image must be in PNG, JPG or GIF format and a minimum size of 112px by 112px. If no image is selected, then the plugin will try to use the logo in the Customizer settings.', 'all-in-one-seo-pack' ), 'aiosp_schema_person_user' => __( 'Select the primary owner for your site from the list of users. Only users with the role of Author, Editor or Administrator will be listed here. Alternatively, you can choose Manually Enter to manually enter the site owner\'s name.', 'all-in-one-seo-pack' ), 'aiosp_schema_person_manual_name' => __( 'Enter the name of the site owner here.', 'all-in-one-seo-pack' ), 'aiosp_schema_person_manual_image' => __( 'Upload or enter the URL for the site owner\'s image or avatar.', 'all-in-one-seo-pack' ), 'aiosp_schema_phone_number' => __( 'Enter the primary phone number your organization or business. You must include the country code and the phone number must use the standard format for your country, for example: 1-888-888-8888.', 'all-in-one-seo-pack' ), 'aiosp_schema_contact_type' => __( 'Select the type of contact for the phone number you have entered.', 'all-in-one-seo-pack' ), // Noindex Settings. 'aiosp_cpostnoindex' => __( 'Set the default NOINDEX setting for each Post Type.', 'all-in-one-seo-pack' ), 'aiosp_cpostnofollow' => __( 'Set the default NOFOLLOW setting for each Post Type.', 'all-in-one-seo-pack' ), 'aiosp_category_noindex' => __( 'Check this to ask search engines not to index Category Archives. Useful for avoiding duplicate content.', 'all-in-one-seo-pack' ), 'aiosp_archive_date_noindex' => __( 'Check this to ask search engines not to index Date Archives. Useful for avoiding duplicate content.', 'all-in-one-seo-pack' ), 'aiosp_archive_author_noindex' => __( 'Check this to ask search engines not to index Author Archives. Useful for avoiding duplicate content.', 'all-in-one-seo-pack' ), 'aiosp_tags_noindex' => __( 'Check this to ask search engines not to index Tag Archives. Useful for avoiding duplicate content.', 'all-in-one-seo-pack' ), 'aiosp_search_noindex' => __( 'Check this to ask search engines not to index the Search page. Useful for avoiding duplicate content.', 'all-in-one-seo-pack' ), 'aiosp_404_noindex' => __( 'Check this to ask search engines not to index the 404 page.', 'all-in-one-seo-pack' ), 'aiosp_paginated_noindex' => __( 'Check this to ask search engines not to index paginated pages/posts. Useful for avoiding duplicate content.', 'all-in-one-seo-pack' ), 'aiosp_paginated_nofollow' => __( 'Check this to ask search engines not to follow links from paginated pages/posts. Useful for avoiding duplicate content.', 'all-in-one-seo-pack' ), 'aiosp_tax_noindex' => __( 'Check this to ask search engines not to index custom Taxonomy archive pages. Useful for avoiding duplicate content.', 'all-in-one-seo-pack' ), // Advanced Settings. 'aiosp_generate_descriptions' => __( 'Check this and your Meta Descriptions for any Post Type will be auto-generated using the Post Excerpt, or the first 160 characters of the post content if there is no Post Excerpt. You can overwrite any auto-generated Meta Description by editing the post or page.', 'all-in-one-seo-pack' ), 'aiosp_skip_excerpt' => __( 'This option will auto generate your meta descriptions from your post content instead of your post excerpt. This is useful if you want to use your content for your autogenerated meta descriptions instead of the excerpt. WooCommerce users should read the documentation regarding this setting.', 'all-in-one-seo-pack' ), 'aiosp_run_shortcodes' => __( 'Check this and shortcodes will get executed for descriptions auto-generated from content.', 'all-in-one-seo-pack' ), 'aiosp_hide_paginated_descriptions' => __( 'Check this and your Meta Descriptions will be removed from page 2 or later of paginated content.', 'all-in-one-seo-pack' ), 'aiosp_dont_truncate_descriptions' => __( 'Check this to prevent your Description from being truncated regardless of its length.', 'all-in-one-seo-pack' ), 'aiosp_unprotect_meta' => __( "Check this to unprotect internal postmeta fields for use with XMLRPC. If you don't know what that is, leave it unchecked.", 'all-in-one-seo-pack' ), 'aiosp_redirect_attachement_parent' => __( 'Redirect attachment pages to post parent.', 'all-in-one-seo-pack' ), /* translators: %s is a placeholder, which means that it should not be translated. It will be replaced with the name of the plugin, All in One SEO Pack. */ 'aiosp_ex_pages' => sprintf( __( 'Enter a comma separated list of pages here to be excluded by %s. This is helpful when using plugins which generate their own non-WordPress dynamic pages. Ex: /forum/, /contact/
    For instance, if you want to exclude the virtual pages generated by a forum plugin, all you have to do is add "forum" or "/forum" or "/forum/" or any URL with the word "forum" in it here, such as "http://mysite.com/forum" or "http://mysite.com/forum/someforumpage", and it will be excluded.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME ), 'aiosp_post_meta_tags' => __( 'What you enter here will be copied verbatim to the header of all Posts. You can enter whatever additional headers you want here, even references to stylesheets.', 'all-in-one-seo-pack' ), 'aiosp_page_meta_tags' => __( 'What you enter here will be copied verbatim to the header of all Pages. You can enter whatever additional headers you want here, even references to stylesheets.', 'all-in-one-seo-pack' ), 'aiosp_front_meta_tags' => __( 'What you enter here will be copied verbatim to the header of the front page if you have set a static page in Settings, Reading, Front Page Displays. You can enter whatever additional headers you want here, even references to stylesheets. This will fall back to using Additional Page Headers if you have them set and nothing is entered here.', 'all-in-one-seo-pack' ), 'aiosp_home_meta_tags' => __( 'What you enter here will be copied verbatim to the header of the home page if you have Front page displays your latest posts selected in Settings, Reading.  It will also be copied verbatim to the header on the Posts page if you have one set in Settings, Reading. You can enter whatever additional headers you want here, even references to stylesheets.', 'all-in-one-seo-pack' ), // Keyword Settings. 'aiosp_togglekeywords' => __( 'This option allows you to toggle the use of Meta Keywords throughout the whole of the site.', 'all-in-one-seo-pack' ), 'aiosp_use_categories' => __( 'Check this if you want your categories for a given post used as the Meta Keywords for this post (in addition to any keywords you specify on the Edit Post screen).', 'all-in-one-seo-pack' ), 'aiosp_use_tags_as_keywords' => __( 'Check this if you want your tags for a given post used as the Meta Keywords for this post (in addition to any keywords you specify on the Edit Post screen).', 'all-in-one-seo-pack' ), 'aiosp_dynamic_postspage_keywords' => __( 'Check this if you want your keywords on your Posts page (set in WordPress under Settings, Reading, Front Page Displays) and your archive pages to be dynamically generated from the keywords of the posts showing on that page. If unchecked, it will use the keywords set in the edit page screen for the posts page.', 'all-in-one-seo-pack' ), ); // phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment $post_types = get_post_types( '', 'names' ); foreach ( $post_types as $v1_pt ) { if ( ! isset( $rtn_help_text[ 'aiosp_' . $v1_pt . '_title_format' ] ) ) { $name = ucwords( preg_replace( '/-|\_/', ' ', get_post_type_object( $v1_pt )->labels->singular_name ) ); $help_text_macros = '
    %site_title%
    ' . '
    ' . __( 'Your site title', 'all-in-one-seo-pack' ) . '
    ' . '
    %site_description%
    ' . '
    ' . __( 'Your site description', 'all-in-one-seo-pack' ) . '
    ' . '
    %post_title%
    ' . '
    ' . sprintf( __( 'The original title of the %s', 'all-in-one-seo-pack' ), $name ) . '
    '; $pt_obj_taxes = get_object_taxonomies( $v1_pt, 'objects' ); foreach ( $pt_obj_taxes as $k2_slug => $v2_tax_obj ) { if ( $v2_tax_obj->public ) { $help_text_macros .= sprintf( '
    %%tax_%1$s%%
    ' . /* translators: %2$s and %3$s are placeholders and should not be translated. These are replaced with the name of the taxonomy (%2$s) that is associated with (the name of) a custom post type (%2$s). */ __( 'The title of the %2$s taxonomy that is associated to this %3$s', 'all-in-one-seo-pack' ) . '
    ', $k2_slug, ucwords( $v2_tax_obj->label ), $name ); } } $help_text_macros .= '
    %page_author_login%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'username', 'all-in-one-seo-pack' ), $name ) . '
    ' . '
    %page_author_nicename%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'nicename', 'all-in-one-seo-pack' ), $name ) . '
    ' . '
    %page_author_firstname%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'first name', 'all-in-one-seo-pack' ), $name ) . '
    ' . '
    %page_author_lastname%
    ' . '
    ' . sprintf( __( 'The %1$s of the author of the %2$s', 'all-in-one-seo-pack' ), __( 'last name', 'all-in-one-seo-pack' ), $name ) . '
    ' . '
    %current_date%
    ' . '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_year%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month%
    ' . '
    ' . sprintf( __( 'The current %s', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %current_month_i18n%
    ' . '
    ' . sprintf( __( 'The current %s (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ) ) . '
    ' . '
    %post_date%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'date', 'all-in-one-seo-pack' ), $name ) . '
    ' . '
    %post_year%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'year', 'all-in-one-seo-pack' ), $name ) . '
    ' . '
    %post_month%
    ' . '
    ' . sprintf( __( 'The %1$s when the %2$s was published (localized)', 'all-in-one-seo-pack' ), __( 'month', 'all-in-one-seo-pack' ), $name ) . '
    '; $rtn_help_text[ 'aiosp_' . $v1_pt . '_title_format' ] = __( 'The following macros are supported:', 'all-in-one-seo-pack' ) . '
    ' . $help_text_macros . '
    ' . '
    ' . __( 'Click here for documentation on this setting', 'all-in-one-seo-pack' ) . ''; } } // phpcs:enable $help_doc_link = array( // General Settings. 'aiosp_can' => 'https://semperplugins.com/documentation/general-settings/#canonical-urls', 'aiosp_no_paged_canonical_links' => 'https://semperplugins.com/documentation/general-settings/#no-pagination-for-canonical-urls', 'aiosp_use_original_title' => 'https://semperplugins.com/documentation/general-settings/#use-original-title', 'aiosp_schema_markup' => 'https://semperplugins.com/documentation/schema-settings/#use-schema-markup', 'aiosp_do_log' => 'https://semperplugins.com/documentation/general-settings/#log-important-events', // Home Page Settings. 'aiosp_home_title' => 'https://semperplugins.com/documentation/home-page-settings/#home-title', 'aiosp_home_description' => 'https://semperplugins.com/documentation/home-page-settings/#home-description', 'aiosp_home_keywords' => 'https://semperplugins.com/documentation/home-page-settings/#home-keywords', 'aiosp_use_static_home_info' => 'https://semperplugins.com/documentation/home-page-settings/#use-static-front-page-instead', // Title Settings. 'aiosp_home_page_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_page_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_post_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_category_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_archive_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_date_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_author_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_tag_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_search_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_description_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_404_title_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', 'aiosp_paged_format' => 'https://semperplugins.com/documentation/title-settings/#title-format-fields', // Custom Post Type Settings. 'aiosp_cpostactive' => 'https://semperplugins.com/documentation/custom-post-type-settings/#seo-on-only-these-post-types', // Display Settings. 'aiosp_posttypecolumns' => 'https://semperplugins.com/documentation/display-settings/#show-column-labels-for-custom-post-types', // Webmaster Verification. 'aiosp_google_verify' => 'https://semperplugins.com/documentation/google-search-console-verification/', 'aiosp_bing_verify' => 'https://semperplugins.com/documentation/bing-webmaster-verification/', 'aiosp_pinterest_verify' => 'https://semperplugins.com/documentation/pinterest-site-verification/', 'aiosp_yandex_verify' => 'https://semperplugins.com/documentation/yandex-webmaster-verification/', 'aiosp_baidu_verify' => 'https://semperplugins.com/documentation/baidu-webmaster-tools-verification/', // Google Analytics. 'aiosp_google_analytics_id' => 'https://semperplugins.com/documentation/setting-up-google-analytics/', 'aiosp_ga_advanced_options' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/', 'aiosp_ga_domain' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#tracking-domain', 'aiosp_ga_multi_domain' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#track-multiple-domains-additional-domains', 'aiosp_ga_addl_domains' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#track-multiple-domains-additional-domains', 'aiosp_ga_anonymize_ip' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#anonymize-ip-addresses', 'aiosp_ga_display_advertising' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#display-advertiser-tracking', 'aiosp_ga_exclude_users' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#exclude-users-from-tracking', 'aiosp_ga_track_outbound_links' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#track-outbound-links', 'aiosp_ga_link_attribution' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#enhanced-link-attribution', 'aiosp_ga_enhanced_ecommerce' => 'https://semperplugins.com/documentation/advanced-google-analytics-settings/#enhanced-ecommerce', // Schema Settings. 'aiosp_schema_search_results_page' => 'https://semperplugins.com/documentation/schema-settings/#display-sitelinks-search-box', 'aiosp_schema_social_profile_links' => 'https://semperplugins.com/documentation/schema-settings/#social-profile-links', 'aiosp_schema_site_represents' => 'https://semperplugins.com/documentation/schema-settings/#person-or-organization', 'aiosp_schema_organization_name' => 'https://semperplugins.com/documentation/schema-settings/#organization-name', 'aiosp_schema_organization_logo' => 'https://semperplugins.com/documentation/schema-settings/#organization-logo', 'aiosp_schema_person_user' => 'https://semperplugins.com/documentation/schema-settings/#persons-username', 'aiosp_schema_phone_number' => 'https://semperplugins.com/documentation/schema-settings/#phone-number', 'aiosp_schema_contact_type' => 'https://semperplugins.com/documentation/schema-settings/#type-of-contact', // Noindex Settings. 'aiosp_cpostnoindex' => 'https://semperplugins.com/documentation/noindex-settings/#noindex', 'aiosp_cpostnofollow' => 'https://semperplugins.com/documentation/noindex-settings/#nofollow', 'aiosp_category_noindex' => 'https://semperplugins.com/documentation/noindex-settings/#noindex-settings', 'aiosp_archive_date_noindex' => 'https://semperplugins.com/documentation/noindex-settings/#noindex-settings', 'aiosp_archive_author_noindex' => 'https://semperplugins.com/documentation/noindex-settings/#noindex-settings', 'aiosp_tags_noindex' => 'https://semperplugins.com/documentation/noindex-settings/#noindex-settings', 'aiosp_search_noindex' => 'https://semperplugins.com/documentation/noindex-settings/#use-noindex-for-the-search-page', 'aiosp_404_noindex' => 'https://semperplugins.com/documentation/noindex-settings/#use-noindex-for-the-404-page', 'aiosp_paginated_noindex' => 'https://semperplugins.com/documentation/noindex-settings/#use-noindex-for-paginated-pages-posts', 'aiosp_paginated_nofollow' => 'https://semperplugins.com/documentation/noindex-settings/#use-nofollow-for-paginated-pages-posts', 'aiosp_tax_noindex' => 'https://semperplugins.com/documentation/noindex-settings/#use-noindex-for-the-taxonomy-archives', // Advanced Settings. 'aiosp_generate_descriptions' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#autogenerate-descriptions', 'aiosp_skip_excerpt' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#remove-descriptions-for-paginated-pages', 'aiosp_run_shortcodes' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#never-shorten-long-descriptions', 'aiosp_hide_paginated_descriptions' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#unprotect-post-meta-fields', 'aiosp_dont_truncate_descriptions' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#never-shorten-long-descriptions', 'aiosp_unprotect_meta' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#unprotect-post-meta-fields', 'aiosp_redirect_attachement_parent' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#redirect-attachments-to-post-parent', 'aiosp_ex_pages' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#exclude-pages', 'aiosp_post_meta_tags' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#additional-post-headers', 'aiosp_page_meta_tags' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#additional-page-headers', 'aiosp_front_meta_tags' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#additional-front-page-headers', 'aiosp_home_meta_tags' => 'https://semperplugins.com/documentation/all-in-one-seo-pack-advanced-settings/#additional-blog-page-headers', // Keyword Settings. 'aiosp_togglekeywords' => 'https://semperplugins.com/documentation/keyword-settings/#use-keywords', 'aiosp_use_categories' => 'https://semperplugins.com/documentation/keyword-settings/#use-categories-for-meta-keywords', 'aiosp_use_tags_as_keywords' => 'https://semperplugins.com/documentation/keyword-settings/#use-tags-for-meta-keywords', 'aiosp_dynamic_postspage_keywords' => 'https://semperplugins.com/documentation/keyword-settings/#dynamically-generate-keywords-for-posts-page', ); foreach ( $help_doc_link as $k1_slug => $v1_url ) { // Any help text that ends with a ul or ol element will cause text to start at the next line. $tooltips_with_ul = array( 'aiosp_home_page_title_format', 'aiosp_page_title_format', 'aiosp_post_title_format', 'aiosp_category_title_format', 'aiosp_archive_title_format', 'aiosp_date_title_format', 'aiosp_author_title_format', 'aiosp_tag_title_format', 'aiosp_search_title_format', 'aiosp_description_format', 'aiosp_404_title_format', 'aiosp_paged_format', ); $br = '

    '; if ( in_array( $k1_slug, $tooltips_with_ul, true ) ) { $br = '
    '; } $rtn_help_text[ $k1_slug ] .= $br . '' . __( 'Click here for documentation on this setting.', 'all-in-one-seo-pack' ) . ''; } return $rtn_help_text; } /** * Help Text Performance Module * * @ignore * @since 2.4.2 * @access private * * @return array */ private function help_text_performance() { $rtn_help_text = array( 'aiosp_performance_memory_limit' => __( 'This setting allows you to raise your PHP memory limit to a reasonable value. Note: WordPress core and other WordPress plugins may also change the value of the memory limit.', 'all-in-one-seo-pack' ), 'aiosp_performance_execution_time' => __( 'This setting allows you to raise your PHP execution time to a reasonable value.', 'all-in-one-seo-pack' ), 'aiosp_performance_force_rewrites' => __( 'Use output buffering to ensure that the title gets rewritten. Enable this option if you run into issues with the title tag being set by your theme or another plugin.', 'all-in-one-seo-pack' ), ); $help_doc_link = array( 'aiosp_performance_memory_limit' => 'https://semperplugins.com/documentation/performance-settings/#raise-memory-limit', 'aiosp_performance_execution_time' => 'https://semperplugins.com/documentation/performance-settings/#raise-execution-time', 'aiosp_performance_force_rewrites' => 'https://semperplugins.com/documentation/performance-settings/#force-rewrites', ); foreach ( $help_doc_link as $k1_slug => $v1_url ) { $rtn_help_text[ $k1_slug ] .= '

    ' . __( 'Click here for documentation on this setting.', 'all-in-one-seo-pack' ) . ''; } return $rtn_help_text; } /** * Help Text Sitemap Module * * @ignore * @since 2.4.2 * @access private * * @return array */ private function help_text_sitemap() { $rtn_help_text = array( // XML Sitemap. 'aiosp_sitemap_rss_sitemap' => __( 'Generate an RSS sitemap in addition to the regular XML Sitemap.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_daily_cron' => __( 'Notify search engines based on the selected schedule, and also update static sitemap daily if in use. (this uses WP-Cron, so make sure this is working properly on your server as well)', 'all-in-one-seo-pack' ), 'aiosp_sitemap_indexes' => __( 'Organize sitemap entries into distinct files in your sitemap. We recommend you enable this setting if your sitemap contains more than 1,000 URLs.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_max_posts' => __( 'Allows you to specify the maximum number of posts in a sitemap (up to 50,000).', 'all-in-one-seo-pack' ), 'aiosp_sitemap_posttypes' => __( 'Select which Post Types appear in your sitemap.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_taxonomies' => __( 'Select which taxonomy archives appear in your sitemap', 'all-in-one-seo-pack' ), 'aiosp_sitemap_archive' => __( 'Include Date Archives in your sitemap.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_author' => __( 'Include Author Archives in your sitemap.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_images' => __( 'Exclude Images in your sitemap.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_robots' => __( 'Places a link to your Sitemap.xml into your virtual Robots.txt file.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_rewrite' => __( 'Dynamically creates the XML sitemap instead of using a static file.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_addl_url' => __( 'URL to the page. This field only accepts absolute URLs with the protocol specified.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_addl_prio' => __( 'The priority of the page.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_addl_freq' => __( 'The frequency of the page.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_addl_mod' => __( 'Last modified date of the page.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_excl_terms' => __( 'Exclude any category, tag or custom taxonomy from the XML sitemap. Start typing the name of a category, tag or taxonomy term in the field and a dropdown will populate with the matching terms for you to select from.

    This will also exclude any content belonging to the specified term. For example, if you exclude the "Uncategorized" category then all posts in that category will also be excluded from the sitemap.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_excl_pages' => __( 'Use page slugs or page IDs, separated by commas, to exclude pages from the sitemap.', 'all-in-one-seo-pack' ), // Priorities. 'aiosp_sitemap_prio_homepage' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'priority', 'all-in-one-seo-pack' ), __( 'Homepage', 'all-in-one-seo-pack' ) ), 'aiosp_sitemap_prio_post' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'priority', 'all-in-one-seo-pack' ), __( 'Posts', 'all-in-one-seo-pack' ) ), 'aiosp_sitemap_prio_taxonomies' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'priority', 'all-in-one-seo-pack' ), __( 'Taxonomies', 'all-in-one-seo-pack' ) ), 'aiosp_sitemap_prio_archive' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'priority', 'all-in-one-seo-pack' ), __( 'Archive Pages', 'all-in-one-seo-pack' ) ), 'aiosp_sitemap_prio_author' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'priority', 'all-in-one-seo-pack' ), __( 'Author Pages', 'all-in-one-seo-pack' ) ), // Frequencies. 'aiosp_sitemap_freq_homepage' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'frequency', 'all-in-one-seo-pack' ), __( 'Homepage', 'all-in-one-seo-pack' ) ), 'aiosp_sitemap_freq_post' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'frequency', 'all-in-one-seo-pack' ), __( 'Posts', 'all-in-one-seo-pack' ) ), 'aiosp_sitemap_freq_taxonomies' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'frequency', 'all-in-one-seo-pack' ), __( 'Taxonomies', 'all-in-one-seo-pack' ) ), 'aiosp_sitemap_freq_archive' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'frequency', 'all-in-one-seo-pack' ), __( 'Archive Pages', 'all-in-one-seo-pack' ) ), 'aiosp_sitemap_freq_author' => sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'frequency', 'all-in-one-seo-pack' ), __( 'Author Pages', 'all-in-one-seo-pack' ) ), ); $args = array( 'public' => true, ); $post_types = get_post_types( $args, 'names' ); foreach ( $post_types as $pt ) { $pt_obj = get_post_type_object( $pt ); $rtn_help_text[ 'aiosp_sitemap_prio_post_' . $pt ] = sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'priority', 'all-in-one-seo-pack' ), ucwords( $pt_obj->label ) ); $rtn_help_text[ 'aiosp_sitemap_freq_post_' . $pt ] = sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'frequency', 'all-in-one-seo-pack' ), ucwords( $pt_obj->label ) ); $help_doc_link[ 'aiosp_sitemap_prio_post_' . $pt ] = 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies'; $help_doc_link[ 'aiosp_sitemap_freq_post_' . $pt ] = 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies'; } $taxonomies = get_taxonomies( $args, 'object' ); foreach ( $taxonomies as $tax ) { $rtn_help_text[ 'aiosp_sitemap_prio_taxonomies_' . $tax->name ] = sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'priority', 'all-in-one-seo-pack' ), ucwords( $tax->label ) ); $rtn_help_text[ 'aiosp_sitemap_freq_taxonomies_' . $tax->name ] = sprintf( __( 'Manually set the %1$s of your %2$s.', 'all-in-one-seo-pack' ), __( 'frequency', 'all-in-one-seo-pack' ), ucwords( $tax->label ) ); $help_doc_link[ 'aiosp_sitemap_prio_taxonomies_' . $tax->name ] = 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies'; $help_doc_link[ 'aiosp_sitemap_freq_taxonomies_' . $tax->name ] = 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies'; } $help_doc_link = array( // XML Sitemap. 'aiosp_sitemap_rss_sitemap' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#create-rss_sitemap', 'aiosp_sitemap_daily_cron' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#schedule-updates', 'aiosp_sitemap_indexes' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#enable-sitemap-indexes', 'aiosp_sitemap_max_posts' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#enable-sitemap-indexes', 'aiosp_sitemap_posttypes' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#post-types-and-taxonomies', 'aiosp_sitemap_taxonomies' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#post-types-and-taxonomies', 'aiosp_sitemap_archive' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#include-archive-pages', 'aiosp_sitemap_author' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#include-archive-pages', 'aiosp_sitemap_images' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#exclude-images', 'aiosp_sitemap_robots' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#link-from-virtual-robots', 'aiosp_sitemap_rewrite' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#dynamically-generate-sitemap', // Additional Pages. 'aiosp_sitemap_addl_url' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#additional-pages', 'aiosp_sitemap_addl_prio' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#additional-pages', 'aiosp_sitemap_addl_freq' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#additional-pages', 'aiosp_sitemap_addl_mod' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#additional-pages', // Exclude Items. 'aiosp_sitemap_excl_terms' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#excluded-items', 'aiosp_sitemap_excl_pages' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#excluded-items', // Priorities. 'aiosp_sitemap_prio_homepage' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', 'aiosp_sitemap_prio_post' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', 'aiosp_sitemap_prio_taxonomies' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', 'aiosp_sitemap_prio_archive' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', 'aiosp_sitemap_prio_author' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', // Frequencies. 'aiosp_sitemap_freq_homepage' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', 'aiosp_sitemap_freq_post' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', 'aiosp_sitemap_freq_taxonomies' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', 'aiosp_sitemap_freq_archive' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', 'aiosp_sitemap_freq_author' => 'https://semperplugins.com/documentation/xml-sitemaps-module/#priorities-and-frequencies', ); /* * Currently has no links, but may be added later. foreach ( $post_types as $pt ) { $help_doc_link[ 'aiosp_sitemap_prio_post_' . $pt ] = ''; $help_doc_link[ 'aiosp_sitemap_freq_post_' . $pt ] = ''; } */ /* * Currently has no links, but may be added later. foreach ( $taxonomies as $tax ) { $help_doc_link[ 'aiosp_sitemap_prio_taxonomies_' . $tax->name ] = ''; $help_doc_link[ 'aiosp_sitemap_freq_taxonomies_' . $tax->name ] = ''; } */ foreach ( $help_doc_link as $k1_slug => $v1_url ) { $rtn_help_text[ $k1_slug ] .= '

    ' . __( 'Click here for documentation on this setting.', 'all-in-one-seo-pack' ) . ''; } return $rtn_help_text; } /** * Help Text Opengraph Module * * @ignore * @since 2.4.2 * @access private * * @return array */ private function help_text_opengraph() { $rtn_help_text = array( // Home Page Settings. /* translators: %s is a placeholder, which means that it should not be translated. It will be replaced with the name of the plugin, All in One SEO Pack. */ 'aiosp_opengraph_setmeta' => sprintf( __( 'Checking this box will use the Home Title and Home Description set in %s, General Settings as the Open Graph title and description for your home page.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME ), 'aiosp_opengraph_sitename' => __( 'The Site Name is the name that is used to identify your website.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_hometitle' => __( 'The Home Title is the Open Graph title for your home page.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_description' => __( 'The Home Description is the Open Graph description for your home page.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_homeimage' => __( 'The Home Image is the Open Graph image for your home page.', 'all-in-one-seo-pack' ), // Image Settings. 'aiosp_opengraph_defimg' => __( 'This option lets you choose which image will be displayed by default for the Open Graph image. You may override this on individual posts.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_fallback' => __( 'This option lets you fall back to the default image if no image could be found above.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_dimg' => __( 'This option sets a default image that can be used for the Open Graph image. You can upload an image, select an image from your Media Library or paste the URL of an image here.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_dimgwidth' => __( 'This option lets you set a default width for your images, where unspecified.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_dimgheight' => __( 'This option lets you set a default height for your images, where unspecified.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_meta_key' => __( 'Enter the name of a custom field (or multiple field names separated by commas) to use that field to specify the Open Graph image on Pages or Posts.', 'all-in-one-seo-pack' ), // Facebook Settings. 'aiosp_opengraph_key' => __( 'Enter your Facebook Admin ID here. You can enter multiple IDs separated by a comma. You can look up your Facebook ID using this tool http://findmyfbid.com/', 'all-in-one-seo-pack' ), 'aiosp_opengraph_appid' => __( 'Enter your Facebook App ID here. Information about how to get your Facebook App ID can be found at https://developers.facebook.com/docs/apps/register', 'all-in-one-seo-pack' ), 'aiosp_opengraph_gen_tags' => __( 'Automatically generate article tags for Facebook type article when not provided.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_gen_keywords' => __( 'Use keywords in generated article tags.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_gen_categories' => __( 'Use categories in generated article tags.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_gen_post_tags' => __( 'Use post tags in generated article tags.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_types' => __( 'Select which Post Types you want to set Open Graph meta values for.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_facebook_publisher' => __( 'Link articles to the Facebook page associated with your website.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_facebook_author' => __( 'Allows your authors to be identified by their Facebook pages as content authors on the Opengraph meta for their articles.', 'all-in-one-seo-pack' ), // Twitter Settings. 'aiosp_opengraph_defcard' => __( 'Select the default type of Twitter Card to display.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_twitter_site' => __( 'Enter the Twitter username associated with your website here.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_twitter_creator' => __( 'Allows your authors to be identified by their Twitter usernames as content creators on the Twitter cards for their posts.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_twitter_domain' => __( 'Enter the name of your website here.', 'all-in-one-seo-pack' ), // Advanced Settings. 'aiosp_opengraph_title_shortcodes' => __( 'Run shortcodes that appear in social title meta tags.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_description_shortcodes' => __( 'Run shortcodes that appear in social description meta tags.', 'all-in-one-seo-pack' ), 'aiosp_opengraph_generate_descriptions' => __( 'This option will auto generate your Open Graph descriptions from your post content instead of your post excerpt. WooCommerce users should read the documentation regarding this setting.', 'all-in-one-seo-pack' ), // POST META. 'aioseop_opengraph_settings_title' => __( 'This is the Open Graph title of this Page or Post.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_desc' => __( 'This is the Open Graph description of this Page or Post.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_image' => __( 'This option lets you select the Open Graph image that will be used for this Page or Post, overriding the default settings.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_customimg' => __( 'This option lets you upload an image to use as the Open Graph image for this Page or Post.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_imagewidth' => __( 'Enter the width for your Open Graph image in pixels (i.e. 600).', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_imageheight' => __( 'Enter the height for your Open Graph image in pixels (i.e. 600).', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_video' => __( 'This option lets you specify a link to the Open Graph video used on this Page or Post.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_videowidth' => __( 'Enter the width for your Open Graph video in pixels (i.e. 600).', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_videoheight' => __( 'Enter the height for your Open Graph video in pixels (i.e. 600).', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_category' => __( 'Select the Open Graph type that best describes the content of this Page or Post.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_facebook_debug' => __( 'Press this button to have Facebook re-fetch and debug this page.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_section' => __( 'This Open Graph meta allows you to add a general section name that best describes this content.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_tag' => __( 'This Open Graph meta allows you to add a list of keywords that best describe this content.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_setcard' => __( 'Select the Twitter Card type to use for this Page or Post, overriding the default setting.', 'all-in-one-seo-pack' ), 'aioseop_opengraph_settings_customimg_twitter' => __( 'This option lets you upload an image to use as the Twitter image for this Page or Post.', 'all-in-one-seo-pack' ), ); $args_1 = array( 'public' => true, ); $args_2 = array( 'public' => false, ); $post_types = array_merge( get_post_types( $args_1, 'names' ), get_post_types( $args_2, 'names' ) ); foreach ( $post_types as $pt ) { $rtn_help_text[ 'aiosp_opengraph_' . $pt . '_fb_object_type' ] = __( 'Choose a default value that best describes the content of your post type.', 'all-in-one-seo-pack' ); $rtn_help_text[ 'aiosp_opengraph_' . $pt . '_fb_object_type' ] .= '

    ' . __( 'Click here for documentation on this setting.', 'all-in-one-seo-pack' ) . ''; } $help_doc_link = array( // Home Page Settings. 'aiosp_opengraph_setmeta' => 'https://semperplugins.com/documentation/social-meta-module/#use-aioseo-title-and-description', 'aiosp_opengraph_sitename' => 'https://semperplugins.com/documentation/social-meta-module/#site-name', 'aiosp_opengraph_hometitle' => 'https://semperplugins.com/documentation/social-meta-module/#home-title-and-description', 'aiosp_opengraph_description' => 'https://semperplugins.com/documentation/social-meta-module/#home-title-and-description', 'aiosp_opengraph_homeimage' => 'https://semperplugins.com/documentation/social-meta-module/#home-image', // Image Settings. 'aiosp_opengraph_defimg' => 'https://semperplugins.com/documentation/social-meta-module/#select-og-image-source', 'aiosp_opengraph_fallback' => 'https://semperplugins.com/documentation/social-meta-module/#use-default-if-no-image-found', 'aiosp_opengraph_dimg' => 'https://semperplugins.com/documentation/social-meta-module/#default-og-image', 'aiosp_opengraph_dimgwidth' => 'https://semperplugins.com/documentation/social-meta-module/#default-image-width', 'aiosp_opengraph_dimgheight' => 'https://semperplugins.com/documentation/social-meta-module/#default-image-height', 'aiosp_opengraph_meta_key' => 'https://semperplugins.com/documentation/social-meta-module/#use-custom-field-for-image', // Facebook Settings. 'aiosp_opengraph_key' => 'https://semperplugins.com/documentation/social-meta-module/#facebook-admin-id', 'aiosp_opengraph_appid' => 'https://semperplugins.com/documentation/social-meta-module/#facebook-app-id', 'aiosp_opengraph_gen_tags' => 'https://semperplugins.com/documentation/social-meta-module/#automatically-generate-article-tags', 'aiosp_opengraph_gen_keywords' => 'https://semperplugins.com/documentation/social-meta-module/#use-keywords-in-article-tags', 'aiosp_opengraph_gen_categories' => 'https://semperplugins.com/documentation/social-meta-module/#use-categories-in-article-tags', 'aiosp_opengraph_gen_post_tags' => 'https://semperplugins.com/documentation/social-meta-module/#use-post-tags-in-article-tags', 'aiosp_opengraph_types' => 'https://semperplugins.com/documentation/social-meta-module/#enable-facebook-meta-for', 'aiosp_opengraph_facebook_publisher' => 'https://semperplugins.com/documentation/social-meta-module/#show-facebook-publisher-on-articles', 'aiosp_opengraph_facebook_author' => 'https://semperplugins.com/documentation/social-meta-module/#show-facebook-author-on-articles', // Twitter Settings. 'aiosp_opengraph_defcard' => 'https://semperplugins.com/documentation/social-meta-module/#default-twitter-card', 'aiosp_opengraph_twitter_site' => 'https://semperplugins.com/documentation/social-meta-module/#twitter-site', 'aiosp_opengraph_twitter_creator' => 'https://semperplugins.com/documentation/social-meta-module/#show-twitter-author', 'aiosp_opengraph_twitter_domain' => 'https://semperplugins.com/documentation/social-meta-module/#twitter-domain', // Advanced Settings. 'aiosp_opengraph_title_shortcodes' => 'https://semperplugins.com/documentation/social-meta-module/#run-shortcodes-in-title', 'aiosp_opengraph_description_shortcodes' => 'https://semperplugins.com/documentation/social-meta-module/#run-shortcodes-in-description', 'aiosp_opengraph_generate_descriptions' => 'https://semperplugins.com/documentation/social-meta-module/#auto-generate-og-descriptions', // POST META. 'aioseop_opengraph_settings_title' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#title', 'aioseop_opengraph_settings_desc' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#description', 'aioseop_opengraph_settings_image' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#image', 'aioseop_opengraph_settings_customimg' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#custom-image', 'aioseop_opengraph_settings_imagewidth' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#specify-image-width-height', 'aioseop_opengraph_settings_imageheight' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#specify-image-width-height', 'aioseop_opengraph_settings_video' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#custom-video', 'aioseop_opengraph_settings_videowidth' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#specify-video-width-height', 'aioseop_opengraph_settings_videoheight' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#specify-video-width-height', 'aioseop_opengraph_settings_category' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#facebook-object-type', 'aioseop_opengraph_settings_facebook_debug' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#facebook-debug', 'aioseop_opengraph_settings_section' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#article-section', 'aioseop_opengraph_settings_tag' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#article-tags', 'aioseop_opengraph_settings_setcard' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#twitter-card-type', 'aioseop_opengraph_settings_customimg_twitter' => 'https://semperplugins.com/documentation/social-meta-settings-individual-pagepost-settings/#custom-twitter-image', ); foreach ( $help_doc_link as $k1_slug => $v1_url ) { $rtn_help_text[ $k1_slug ] .= '

    ' . __( 'Click here for documentation on this setting.', 'all-in-one-seo-pack' ) . ''; } return $rtn_help_text; } /** * Help Text Robots Generator Module * * @ignore * @since 2.4.2 * @access private * * @return array */ private function help_text_robots_generator() { $rtn_help_text = array( 'aiosp_robots_type' => __( 'Use the dropdown to select whether you want to allow or block access to the specified directory or file.', 'all-in-one-seo-pack' ), 'aiosp_robots_agent' => __( 'Enter the name of a User Agent here. You can use the wildcard * to allow or block all robots. A list of User Agents can be found here.', 'all-in-one-seo-pack' ), 'aiosp_robots_path' => __( 'Enter a valid path to a directory or file, for example: /wp-admin/ or /wp-admin/admin-ajax.php', 'all-in-one-seo-pack' ), ); return $rtn_help_text; } /** * Help Text File Editor Module * * @ignore * @since 2.4.2 * @access private * * @return array */ private function help_text_file_editor() { return array( 'aiosp_file_editor_htaccfile' => __( '.htaccess editor', 'all-in-one-seo-pack' ), ); } /** * Help Text Importer Exporter Module * * @ignore * @since 2.4.2 * @access private * * @return array */ private function help_text_importer_exporter() { $rtn_help_text = array( // Possible HTML link concept IF links become usable inside jQuery UI Tooltips. /* translators: %1$s and 12$s are placeholders, which means these should not be translated. These will be replaced with the name of the plugin, All in One SEO Pack. */ 'aiosp_importer_exporter_import_submit' => sprintf( __( 'Choose a valid %1$s .ini file and click "Import" to import options from a previous state or install of %2$s.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME, AIOSEOP_PLUGIN_NAME ), 'aiosp_importer_exporter_export_choices' => __( 'You may choose to export settings from active modules, and content from post data.', 'all-in-one-seo-pack' ), /* translators: %s is a placeholder, which means that it should not be translated. It will be replaced with the name of the plugin, All in One SEO Pack. */ 'aiosp_importer_exporter_export_post_types' => sprintf( __( 'Select which Post Types you want to export your %s meta data for.', 'all-in-one-seo-pack' ), AIOSEOP_PLUGIN_NAME ), ); $help_doc_link = array( 'aiosp_importer_exporter_import_submit' => 'https://semperplugins.com/documentation/importer-exporter-module/', 'aiosp_importer_exporter_export_choices' => 'https://semperplugins.com/documentation/importer-exporter-module/', 'aiosp_importer_exporter_export_post_types' => 'https://semperplugins.com/documentation/importer-exporter-module/', ); foreach ( $help_doc_link as $k1_slug => $v1_url ) { $rtn_help_text[ $k1_slug ] .= '

    ' . __( 'Click here for documentation on this setting.', 'all-in-one-seo-pack' ) . ''; } return $rtn_help_text; } /** * Help Text Bad Robots Module * * @ignore * @since 2.4.2 * @access private * * @return array */ private function help_text_bad_robots() { return array( 'aiosp_bad_robots_block_bots' => __( 'Block requests from user agents that are known to misbehave with 503.', 'all-in-one-seo-pack' ), 'aiosp_bad_robots_block_refer' => __( 'Block Referral Spam using HTTP.', 'all-in-one-seo-pack' ), 'aiosp_bad_robots_track_blocks' => __( 'Log and show recent requests from blocked bots.', 'all-in-one-seo-pack' ), 'aiosp_bad_robots_edit_blocks' => __( 'Check this to edit the list of disallowed user agents for blocking bad bots.', 'all-in-one-seo-pack' ), 'aiosp_bad_robots_blocklist' => __( 'This is the list of disallowed user agents used for blocking bad bots.', 'all-in-one-seo-pack' ), 'aiosp_bad_robots_referlist' => __( 'This is the list of disallowed referers used for blocking bad bots.', 'all-in-one-seo-pack' ), 'aiosp_bad_robots_blocked_log' => __( 'Shows log of most recent requests from blocked bots. Note: this will not track any bots that were already blocked at the web server / .htaccess level.', 'all-in-one-seo-pack' ), ); } /** * Help Text Post Meta (Core Module) * * @ignore * @since 2.4.2 * @access private * * @see self::_help_text_opengraph() Also adds Post Meta info. * * @return array */ private function help_text_post_meta() { $rtn_help_text = array( 'aiosp_snippet' => __( 'A preview of what this page might look like in search engine results.', 'all-in-one-seo-pack' ), 'aiosp_title' => __( 'A custom title that shows up in the title tag for this page.', 'all-in-one-seo-pack' ), 'aiosp_description' => __( 'The META description for this page. This will override any autogenerated descriptions.', 'all-in-one-seo-pack' ), 'aiosp_keywords' => __( 'A comma separated list of your most important keywords for this page that will be written as META keywords.', 'all-in-one-seo-pack' ), 'aiosp_custom_link' => __( 'Override the canonical URLs for this post.', 'all-in-one-seo-pack' ), 'aiosp_noindex' => __( 'Check this box to ask search engines not to index this page.', 'all-in-one-seo-pack' ), 'aiosp_nofollow' => __( 'Check this box to ask search engines not to follow links from this page.', 'all-in-one-seo-pack' ), 'aiosp_sitemap_exclude' => __( 'Don\'t display this page in the sitemap.', 'all-in-one-seo-pack' ), 'aiosp_disable' => __( 'Disable SEO on this page.', 'all-in-one-seo-pack' ), 'aiosp_disable_analytics' => __( 'Disable Google Analytics on this page.', 'all-in-one-seo-pack' ), ); $help_doc_link = array( 'aiosp_snippet' => 'https://semperplugins.com/documentation/post-settings/#preview-snippet', 'aiosp_title' => 'https://semperplugins.com/documentation/post-settings/#title', 'aiosp_description' => 'https://semperplugins.com/documentation/post-settings/#description', 'aiosp_keywords' => 'https://semperplugins.com/documentation/post-settings/#keywords', 'aiosp_custom_link' => 'https://semperplugins.com/documentation/post-settings/#custom-canonical-url', 'aiosp_noindex' => 'https://semperplugins.com/documentation/post-settings/#robots-meta-noindex', 'aiosp_nofollow' => 'https://semperplugins.com/documentation/post-settings/#robots-meta-nofollow', 'aiosp_sitemap_exclude' => 'https://semperplugins.com/documentation/post-settings/#exclude-from-sitemap', 'aiosp_disable' => 'https://semperplugins.com/documentation/post-settings/#disable-on-this-post', 'aiosp_disable_analytics' => 'https://semperplugins.com/documentation/post-settings/#disable-google-analytics', ); foreach ( $help_doc_link as $k1_slug => $v1_url ) { $rtn_help_text[ $k1_slug ] .= '

    ' . __( 'Click here for documentation on this setting.', 'all-in-one-seo-pack' ) . ''; } return $rtn_help_text; } /** * Get Help Text * * Gets an individual help text if it exists, otherwise an error is returned * to notify the AIOSEOP Devs. * NOTE: Returning an empty string causes issues with the UI. * * @since 2.4.2 * * @param string $slug Module option slug. * @return string */ public function get_help_text( $slug ) { if ( isset( $this->help_text[ $slug ] ) ) { return esc_html( $this->help_text[ $slug ] ); } return 'DEV: Missing Help Text: ' . $slug; } } PKH\$$ index.phpnu[ wp_create_nonce( 'wpseo-import' ) ), admin_url( 'admin.php?page=wpseo_tools&tool=import-export&import=1&importaioseo=1#top#import-seo' ) ); $aiourl = add_query_arg( array( '_wpnonce' => wp_create_nonce( 'aiosp-import' ) ), admin_url( 'tools.php?page=aiosp_import' ) ); $aioseop_yst_detected_notice_dismissed = get_user_meta( get_current_user_id(), 'aioseop_yst_detected_notice_dismissed', true ); if ( empty( $aioseop_yst_detected_notice_dismissed ) ) { /* translators: %1$s, %2$s and %3$s are placeholders, which means these shouldn't be translated. The first two placeholders are used to add a link to anchor text and the third is replaced with the name of the plugin, All in One SEO Pack. */ echo '

    ', sprintf( esc_html__( 'The plugin Yoast SEO has been detected. Do you want to %1$simport its settings%2$s into %3$s', 'all-in-one-seo-pack' ), sprintf( '', esc_url( $aiourl ) ), '', AIOSEOP_PLUGIN_NAME ), '

    '; } // phpcs:disable WordPress.WP.I18n echo '

    ', sprintf( esc_html__( 'The plugin All-In-One-SEO has been detected. Do you want to %1$simport its settings%2$s?', 'wordpress-seo' ), sprintf( '', esc_url( $yoasturl ) ), '' ), '

    '; // phpcs:enable } public function show_deactivate_notice() { echo '

    ', esc_html__( 'All in One SEO has been deactivated', 'all-in-one-seo-pack' ), '

    '; } } } else { if ( is_admin() ) { add_action( 'init', 'mi_aioseop_yst_detected_notice_dismissed' ); } } /** * Deletes the stored dismissal of the notice. * * This should only happen after reactivating after being deactivated. */ function mi_aioseop_yst_detected_notice_dismissed() { delete_user_meta( get_current_user_id(), 'aioseop_yst_detected_notice_dismissed' ); } /** * Init for settings import class. * * At the moment we just register the admin menu page. */ function aiosp_seometa_settings_init() { global $_aiosp_seometa_admin_pagehook; // TODO Put this in with the rest of the import/export stuff. $_aiosp_seometa_admin_pagehook = add_submenu_page( 'tools.php', __( 'Import SEO Data', 'all-in-one-seo-pack' ), __( 'SEO Data Import', 'all-in-one-seo-pack' ), 'manage_options', 'aiosp_import', 'aiosp_seometa_admin' ); } add_action( 'admin_menu', 'aiosp_seometa_settings_init' ); /** * Intercept POST data from the form submission. * * Use the intercepted data to convert values in the postmeta table from one platform to another and display feedback to the user about compatible conversion * elements and the conversion process. */ function aiosp_seometa_action() { if ( empty( $_REQUEST['_wpnonce'] ) ) { return; } if ( empty( $_REQUEST['platform_old'] ) ) { printf( '

    %s

    ', __( 'Sorry, you can\'t do that. Please choose a platform and then click Analyze or Convert.', 'all-in-one-seo-pack' ) ); return; } if ( 'All in One SEO Pack' === $_REQUEST['platform_old'] ) { printf( '

    %s

    ', __( 'Sorry, you can\'t do that. Please choose a platform and then click Analyze or Convert.', 'all-in-one-seo-pack' ) ); return; } check_admin_referer( 'aiosp_nonce' ); // Verify nonce. TODO We should make this better. if ( ! empty( $_REQUEST['analyze'] ) ) { printf( '

    %s

    ', __( 'Analysis Results', 'all-in-one-seo-pack' ) ); $response = aiosp_seometa_post_meta_analyze( $_REQUEST['platform_old'], 'All in One SEO Pack' ); if ( is_wp_error( $response ) ) { printf( '

    %s

    ', __( 'Sorry, something went wrong. Please try again', 'all-in-one-seo-pack' ) ); return; } printf( __( '

    Analyzing records in a %1$s to %2$s conversion…', 'all-in-one-seo-pack' ), esc_html( $_POST['platform_old'] ), 'All in One SEO Pack' ); printf( '

    %d Compatible Records were identified

    ', $response->update ); // phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar // printf( '

    %d Compatible Records will be ignored

    ', $response->ignore ); printf( '

    %s

    ', __( 'Compatible data:', 'all-in-one-seo-pack' ) ); echo '
      '; foreach ( (array) $response->elements as $element ) { printf( '
    1. %s
    2. ', $element ); } echo '
    '; return; } printf( '

    %s

    ', __( 'Conversion Results', 'all-in-one-seo-pack' ) ); $result = aiosp_seometa_post_meta_convert( stripslashes( $_REQUEST['platform_old'] ), 'All in One SEO Pack' ); if ( is_wp_error( $result ) ) { printf( '

    %s

    ', __( 'Sorry, something went wrong. Please try again', 'all-in-one-seo-pack' ) ); return; } printf( '

    %d Records were updated

    ', isset( $result->updated ) ? $result->updated : 0 ); printf( '

    %d Records were ignored

    ', isset( $result->ignored ) ? $result->ignored : 0 ); } /** * The admin page output */ function aiosp_seometa_admin() { global $_aiosp_seometa_themes, $_aiosp_seometa_plugins, $_aiosp_seometa_platforms; ?>

    ', esc_url( 'https://semperfiwebdesign.com/backupbuddy/' ) ), '' ); ?>

    '; printf( '', __( 'Choose platform:', 'all-in-one-seo-pack' ) ); printf( '', __( 'Plugins', 'all-in-one-seo-pack' ) ); foreach ( $_aiosp_seometa_plugins as $platform => $data ) { if ( 'All in One SEO Pack' !== $platform ) { printf( '', $platform, selected( $platform, $platform_old, 0 ), $platform ); } } printf( '' ); printf( '', __( 'Themes', 'all-in-one-seo-pack' ) ); foreach ( $_aiosp_seometa_themes as $platform => $data ) { printf( '', $platform, selected( $platform, $platform_old, 0 ), $platform ); } printf( '' ); echo '' . "\n\n"; ?>
    WP_Error = 1; return $output; } // See which records we need to ignore, if any. $exclude = $wpdb->get_results( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s", $new ) ); // If no records to ignore, we'll do a basic UPDATE and DELETE. if ( ! $exclude ) { $output->updated = $wpdb->update( $wpdb->postmeta, array( 'meta_key' => $new ), array( 'meta_key' => $old ) ); $output->deleted = $delete_old ? $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = %s", $old ) ) : 0; $output->ignored = 0; } else { // Else, do a more complex UPDATE and DELETE. foreach ( (array) $exclude as $key => $value ) { $not_in[] = $value->post_id; } $not_in = implode( ', ', (array) $not_in ); // @codingStandardsIgnoreStart $output->updated = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_key = %s WHERE meta_key = %s AND post_id NOT IN ($not_in)", $new, $old ) ); $output->deleted = $delete_old ? $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = %s", $old ) ) : 0; // @codingStandardsIgnoreEnd $output->ignored = count( $exclude ); } do_action( 'aiosp_seometa_meta_key_convert', $output, $old, $new, $delete_old ); return $output; } /** * Convert old to new postmeta. * * Cycle through all compatible SEO entries of two platforms and aiosp_seometa_meta_key_convert conversion for each key. * * @param string $old_platform * @param string $new_platform * @param bool $delete_old * * @return stdClass Results object. */ function aiosp_seometa_post_meta_convert( $old_platform = '', $new_platform = 'All in One SEO Pack', $delete_old = false ) { do_action( 'pre_aiosp_seometa_post_meta_convert', $old_platform, $new_platform, $delete_old ); global $_aiosp_seometa_platforms; $output = new stdClass; if ( empty( $_aiosp_seometa_platforms[ $old_platform ] ) || empty( $_aiosp_seometa_platforms[ $new_platform ] ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $output->WP_Error = 1; return $output; } $output->updated = 0; $output->deleted = 0; $output->ignored = 0; foreach ( (array) $_aiosp_seometa_platforms[ $old_platform ] as $label => $meta_key ) { // Skip iterations where no $new analog exists. if ( empty( $_aiosp_seometa_platforms[ $new_platform ][ $label ] ) ) { continue; } // Set $old and $new meta_key values. $old = $_aiosp_seometa_platforms[ $old_platform ][ $label ]; $new = $_aiosp_seometa_platforms[ $new_platform ][ $label ]; // Convert. $result = aiosp_seometa_meta_key_convert( $old, $new, $delete_old ); // Error check. if ( is_wp_error( $result ) ) { continue; } // Update total updated/ignored count. $output->updated += (int) $result->updated; $output->ignored += (int) $result->ignored; } do_action( 'aiosp_seometa_post_meta_convert', $output, $old_platform, $new_platform, $delete_old ); return $output; } /** * Analyze two platforms to find shared and compatible elements. * * See what data can be converted from one to the other. * * @param string $old_platform * @param string $new_platform * * @return stdClass */ function aiosp_seometa_post_meta_analyze( $old_platform = '', $new_platform = 'All in One SEO Pack' ) { // TODO Figure out which elements to ignore. do_action( 'pre_aiosp_seometa_post_meta_analyze', $old_platform, $new_platform ); global $wpdb, $_aiosp_seometa_platforms; $output = new stdClass; if ( empty( $_aiosp_seometa_platforms[ $old_platform ] ) || empty( $_aiosp_seometa_platforms[ $new_platform ] ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase $output->WP_Error = 1; return $output; } $output->update = 0; $output->ignore = 0; $output->elements = ''; foreach ( (array) $_aiosp_seometa_platforms[ $old_platform ] as $label => $meta_key ) { // Skip iterations where no $new analog exists. if ( empty( $_aiosp_seometa_platforms[ $new_platform ][ $label ] ) ) { continue; } $elements[] = $label; // See which records to ignore, if any. $ignore = 0; // $ignore = $wpdb->get_results( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s", $meta_key ) ); // See which records to update, if any. $update = $wpdb->get_results( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = %s", $meta_key ) ); // Count items in returned arrays. // phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar // $ignore = count( (array)$ignore ); $update = count( (array) $update ); // Calculate update/ignore by comparison. // phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar // $update = ( (int)$update > (int)$ignore ) ? ( (int)$update - (int)$ignore ) : 0; // update output numbers. $output->update += (int) $update; $output->ignore += (int) $ignore; } $output->elements = $elements; do_action( 'aiosp_seometa_post_meta_analyze', $output, $old_platform, $new_platform ); return $output; } // phpcs:disable Squiz.Commenting.InlineComment.InvalidEndChar // define('aiosp_seometa_PLUGIN_DIR', dirname(__FILE__)); // add_action( 'plugins_loaded', 'aiosp_seometa_import' ); // phpcs:enable /** * Initialize the SEO Data Transporter plugin */ function aiosp_seometa_import() { global $_aiosp_seometa_themes, $_aiosp_seometa_plugins, $_aiosp_seometa_platforms; /** * The associative array of supported themes. */ $_aiosp_seometa_themes = array( // alphabatized. 'Builder' => array( 'Custom Doctitle' => '_builder_seo_title', 'META Description' => '_builder_seo_description', 'META Keywords' => '_builder_seo_keywords', ), 'Catalyst' => array( 'Custom Doctitle' => '_catalyst_title', 'META Description' => '_catalyst_description', 'META Keywords' => '_catalyst_keywords', 'noindex' => '_catalyst_noindex', 'nofollow' => '_catalyst_nofollow', 'noarchive' => '_catalyst_noarchive', ), 'Frugal' => array( 'Custom Doctitle' => '_title', 'META Description' => '_description', 'META Keywords' => '_keywords', 'noindex' => '_noindex', 'nofollow' => '_nofollow', ), 'Genesis' => array( 'Custom Doctitle' => '_genesis_title', 'META Description' => '_genesis_description', 'META Keywords' => '_genesis_keywords', 'noindex' => '_genesis_noindex', 'nofollow' => '_genesis_nofollow', 'noarchive' => '_genesis_noarchive', 'Canonical URI' => '_genesis_canonical_uri', 'Custom Scripts' => '_genesis_scripts', 'Redirect URI' => 'redirect', ), 'Headway' => array( 'Custom Doctitle' => '_title', 'META Description' => '_description', 'META Keywords' => '_keywords', ), 'Hybrid' => array( 'Custom Doctitle' => 'Title', 'META Description' => 'Description', 'META Keywords' => 'Keywords', ), 'Thesis 1.x' => array( 'Custom Doctitle' => 'thesis_title', 'META Description' => 'thesis_description', 'META Keywords' => 'thesis_keywords', 'Custom Scripts' => 'thesis_javascript_scripts', 'Redirect URI' => 'thesis_redirect', ), /* 'Thesis 2.x' => array( 'Custom Doctitle' => '_thesis_title_tag', 'META Description' => '_thesis_meta_description', 'META Keywords' => '_thesis_meta_keywords', 'Custom Scripts' => '_thesis_javascript_scripts', 'Canonical URI' => '_thesis_canonical_link', 'Redirect URI' => '_thesis_redirect', ), */ 'WooFramework' => array( 'Custom Doctitle' => 'seo_title', 'META Description' => 'seo_description', 'META Keywords' => 'seo_keywords', ), ); /** * The associative array of supported plugins. */ $_aiosp_seometa_plugins = array( // alphabatized. 'Add Meta Tags' => array( 'Custom Doctitle' => '_amt_title', 'META Description' => '_amt_description', 'META Keywords' => '_amt_keywords', ), 'All in One SEO Pack' => array( 'Custom Doctitle' => '_aioseop_title', 'META Description' => '_aioseop_description', 'META Keywords' => '_aioseop_keywords', 'Canonical URI' => '_aioseop_custom_link', ), 'Greg\'s High Performance SEO' => array( 'Custom Doctitle' => '_ghpseo_secondary_title', 'META Description' => '_ghpseo_alternative_description', 'META Keywords' => '_ghpseo_keywords', ), 'Headspace2' => array( 'Custom Doctitle' => '_headspace_page_title', 'META Description' => '_headspace_description', 'META Keywords' => '_headspace_keywords', 'Custom Scripts' => '_headspace_scripts', ), 'Infinite SEO' => array( 'Custom Doctitle' => '_wds_title', 'META Description' => '_wds_metadesc', 'META Keywords' => '_wds_keywords', 'noindex' => '_wds_meta-robots-noindex', 'nofollow' => '_wds_meta-robots-nofollow', 'Canonical URI' => '_wds_canonical', 'Redirect URI' => '_wds_redirect', ), 'Jetpack' => array( 'META Description' => 'advanced_seo_description', ), 'Meta SEO Pack' => array( 'META Description' => '_msp_description', 'META Keywords' => '_msp_keywords', ), 'Platinum SEO' => array( 'Custom Doctitle' => 'title', 'META Description' => 'description', 'META Keywords' => 'keywords', ), 'Rank Math' => array( 'Custom Doctitle' => 'rank_math_title', 'META Description' => 'rank_math_description', 'Canonical URI' => 'rank_math_canonical_url', ), 'SEOpressor' => array( 'Custom Doctitle' => '_seopressor_meta_title', 'META Description' => '_seopressor_meta_description', ), 'SEO Title Tag' => array( 'Custom Doctitle' => 'title_tag', 'META Description' => 'meta_description', ), 'SEO Ultimate' => array( 'Custom Doctitle' => '_su_title', 'META Description' => '_su_description', 'META Keywords' => '_su_keywords', 'noindex' => '_su_meta_robots_noindex', 'nofollow' => '_su_meta_robots_nofollow', ), 'Yoast SEO' => array( 'Custom Doctitle' => '_yoast_wpseo_title', 'META Description' => '_yoast_wpseo_metadesc', 'META Keywords' => '_yoast_wpseo_metakeywords', 'noindex' => '_yoast_wpseo_meta-robots-noindex', 'nofollow' => '_yoast_wpseo_meta-robots-nofollow', 'Canonical URI' => '_yoast_wpseo_canonical', 'Redirect URI' => '_yoast_wpseo_redirect', ), ); /** * The combined array of supported platforms. */ $_aiosp_seometa_platforms = array_merge( $_aiosp_seometa_themes, $_aiosp_seometa_plugins ); /** * Include the other elements of the plugin. */ // phpcs:disable Squiz.Commenting.InlineComment.InvalidEndChar // require_once( aiosp_seometa_PLUGIN_DIR . '/admin.php' ); // require_once( aiosp_seometa_PLUGIN_DIR . '/functions.php' ); // phpcs:enable /** * Init hook. * * Hook fires after plugin functions are loaded. * * @since 0.9.10 */ do_action( 'aiosp_seometa_import' ); } /** * Activation Hook * * @since 0.9.4 */ register_activation_hook( __FILE__, 'aiosp_seometa_activation_hook' ); function aiosp_seometa_activation_hook() { // phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar // require_once( aiosp_seometa_PLUGIN_DIR . '/functions.php' ); aiosp_seometa_meta_key_convert( '_yoast_seo_title', 'yoast_wpseo_title', true ); aiosp_seometa_meta_key_convert( '_yoast_seo_metadesc', 'yoast_wpseo_metadesc', true ); } PKR\= js/spectrum/redux-spectrum.jsnu[// Spectrum Colorpicker v1.3.3 // https://github.com/bgrins/spectrum // Author: Brian Grinstead // License: MIT (function (window, $, undefined) { var defaultOpts = { // Callbacks beforeShow: noop, move: noop, change: noop, show: noop, hide: noop, // Options color: false, flat: false, showInput: false, allowEmpty: false, showButtons: true, clickoutFiresChange: false, showInitial: false, showPalette: false, showPaletteOnly: false, showSelectionPalette: true, localStorageKey: false, appendTo: "body", maxSelectionSize: 7, cancelText: "cancel", chooseText: "choose", clearText: "Clear Color Selection", preferredFormat: false, className: "", // Deprecated - use containerClassName and replacerClassName instead. containerClassName: "", replacerClassName: "", showAlpha: false, theme: "sp-light", palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]], selectionPalette: [], disabled: false, inputText: '' }, spectrums = [], IE = !!/msie/i.exec( window.navigator.userAgent ), rgbaSupport = (function() { function contains( str, substr ) { return !!~('' + str).indexOf(substr); } var elem = document.createElement('div'); var style = elem.style; style.cssText = 'background-color:rgba(0,0,0,.5)'; return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla'); })(), inputTypeColorSupport = (function() { var colorInput = $("")[0]; return colorInput.type === "color" && colorInput.value !== "#ffffff"; })(), replaceInput = [ "
    ", "
    ", "
    ", //"
    " + opts.inputText + "
    ", "
    " ].join(''), markup = (function () { // IE does not support gradients with multiple stops, so we need to simulate // that for the rainbow slider with 8 divs that each have a single gradient var gradientFix = ""; if (IE) { for (var i = 1; i <= 6; i++) { gradientFix += "
    "; } } return [ "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", "
    ", gradientFix, "
    ", "
    ", "
    ", "
    ", "
    ", "", "
    ", "
    ", "
    ", "", "", "
    ", "
    ", "
    " ].join(""); })(); function paletteTemplate (p, color, className, tooltipFormat) { var html = []; for (var i = 0; i < p.length; i++) { var current = p[i]; if(current) { var tiny = tinycolor(current); var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light"; c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : ""; var formattedString = tiny.toString(tooltipFormat || "rgb"); var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter(); html.push(''); } else { var cls = 'sp-clear-display'; html.push(''); } } return "
    " + html.join('') + "
    "; } function hideAll() { for (var i = 0; i < spectrums.length; i++) { if (spectrums[i]) { spectrums[i].hide(); } } } function instanceOptions(o, callbackContext) { var opts = $.extend({}, defaultOpts, o); opts.callbacks = { 'move': bind(opts.move, callbackContext), 'change': bind(opts.change, callbackContext), 'show': bind(opts.show, callbackContext), 'hide': bind(opts.hide, callbackContext), 'beforeShow': bind(opts.beforeShow, callbackContext) }; return opts; } function spectrum(element, o) { var opts = instanceOptions(o, element), flat = opts.flat, showSelectionPalette = opts.showSelectionPalette, localStorageKey = opts.localStorageKey, theme = opts.theme, callbacks = opts.callbacks, resize = throttle(reflow, 10), visible = false, dragWidth = 0, dragHeight = 0, dragHelperHeight = 0, slideHeight = 0, slideWidth = 0, alphaWidth = 0, alphaSlideHelperWidth = 0, slideHelperHeight = 0, currentHue = 0, currentSaturation = 0, currentValue = 0, currentAlpha = 1, palette = [], paletteArray = [], paletteLookup = {}, selectionPalette = opts.selectionPalette.slice(0), maxSelectionSize = opts.maxSelectionSize, draggingClass = "sp-dragging", inputText = opts.inputText, shiftMovementDirection = null; var doc = element.ownerDocument, body = doc.body, boundElement = $(element), disabled = false, container = $(markup, doc).addClass(theme), dragger = container.find(".sp-color"), dragHelper = container.find(".sp-dragger"), slider = container.find(".sp-hue"), slideHelper = container.find(".sp-slider"), alphaSliderInner = container.find(".sp-alpha-inner"), alphaSlider = container.find(".sp-alpha"), alphaSlideHelper = container.find(".sp-alpha-handle"), textInput = container.find(".sp-input"), paletteContainer = container.find(".sp-palette"), initialColorContainer = container.find(".sp-initial"), cancelButton = container.find(".sp-cancel"), clearButton = container.find(".sp-clear"), chooseButton = container.find(".sp-choose"), isInput = boundElement.is("input"), isInputTypeColor = isInput && inputTypeColorSupport && boundElement.attr("type") === "color", shouldReplace = isInput && !flat, replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]), offsetElement = (shouldReplace) ? replacer : boundElement, previewElement = replacer.find(".sp-preview-inner"), initialColor = opts.color || (isInput && boundElement.val()), colorOnShow = false, preferredFormat = opts.preferredFormat, currentPreferredFormat = preferredFormat, clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange, isEmpty = !initialColor, allowEmpty = opts.allowEmpty && !isInputTypeColor; if (inputText !== '') { var x = $(offsetElement).find('div.sp-dd'); x.text(inputText); } function applyOptions() { if (opts.showPaletteOnly) { opts.showPalette = true; } if (opts.palette) { palette = opts.palette.slice(0); paletteArray = $.isArray(palette[0]) ? palette : [palette]; paletteLookup = {}; for (var i = 0; i < paletteArray.length; i++) { for (var j = 0; j < paletteArray[i].length; j++) { var rgb = tinycolor(paletteArray[i][j]).toRgbString(); paletteLookup[rgb] = true; } } } container.toggleClass("sp-flat", flat); container.toggleClass("sp-input-disabled", !opts.showInput); container.toggleClass("sp-alpha-enabled", opts.showAlpha); container.toggleClass("sp-clear-enabled", allowEmpty); container.toggleClass("sp-buttons-disabled", !opts.showButtons); container.toggleClass("sp-palette-disabled", !opts.showPalette); container.toggleClass("sp-palette-only", opts.showPaletteOnly); container.toggleClass("sp-initial-disabled", !opts.showInitial); container.addClass(opts.className).addClass(opts.containerClassName); reflow(); } function initialize() { if (IE) { container.find("*:not(input)").attr("unselectable", "on"); } applyOptions(); if (shouldReplace) { boundElement.after(replacer).hide(); } if (!allowEmpty) { clearButton.hide(); } if (flat) { boundElement.after(container).hide(); } else { var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo); if (appendTo.length !== 1) { appendTo = $("body"); } appendTo.append(container); } updateSelectionPaletteFromStorage(); offsetElement.bind("click.spectrum touchstart.spectrum", function (e) { if (!disabled) { toggle(); } e.stopPropagation(); if (!$(e.target).is("input")) { e.preventDefault(); } }); if(boundElement.is(":disabled") || (opts.disabled === true)) { disable(); } // Prevent clicks from bubbling up to document. This would cause it to be hidden. container.click(stopPropagation); // Handle user typed input textInput.change(setFromTextInput); textInput.bind("paste", function () { setTimeout(setFromTextInput, 1); }); textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } }); cancelButton.text(opts.cancelText); cancelButton.bind("click.spectrum", function (e) { e.stopPropagation(); e.preventDefault(); hide("cancel"); }); clearButton.attr("title", opts.clearText); clearButton.bind("click.spectrum", function (e) { e.stopPropagation(); e.preventDefault(); isEmpty = true; move(); if(flat) { //for the flat style, this is a change event updateOriginalInput(true); } }); chooseButton.text(opts.chooseText); chooseButton.bind("click.spectrum", function (e) { e.stopPropagation(); e.preventDefault(); if (isValid()) { updateOriginalInput(true); hide(); } }); draggable(alphaSlider, function (dragX, dragY, e) { currentAlpha = (dragX / alphaWidth); isEmpty = false; if (e.shiftKey) { currentAlpha = Math.round(currentAlpha * 10) / 10; } move(); }, dragStart, dragStop); draggable(slider, function (dragX, dragY) { currentHue = parseFloat(dragY / slideHeight); isEmpty = false; if (!opts.showAlpha) { currentAlpha = 1; } move(); }, dragStart, dragStop); draggable(dragger, function (dragX, dragY, e) { // shift+drag should snap the movement to either the x or y axis. if (!e.shiftKey) { shiftMovementDirection = null; } else if (!shiftMovementDirection) { var oldDragX = currentSaturation * dragWidth; var oldDragY = dragHeight - (currentValue * dragHeight); var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY); shiftMovementDirection = furtherFromX ? "x" : "y"; } var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x"; var setValue = !shiftMovementDirection || shiftMovementDirection === "y"; if (setSaturation) { currentSaturation = parseFloat(dragX / dragWidth); } if (setValue) { currentValue = parseFloat((dragHeight - dragY) / dragHeight); } isEmpty = false; if (!opts.showAlpha) { currentAlpha = 1; } move(); }, dragStart, dragStop); if (!!initialColor) { set(initialColor); // In case color was black - update the preview UI and set the format // since the set function will not run (default color is black). updateUI(); currentPreferredFormat = preferredFormat || tinycolor(initialColor).format; addColorToSelectionPalette(initialColor); } else { updateUI(); } if (flat) { show(); } function palletElementClick(e) { if (e.data && e.data.ignore) { set($(this).data("color")); move(); } else { set($(this).data("color")); move(); updateOriginalInput(true); hide(); } return false; } var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum"; paletteContainer.delegate(".sp-thumb-el", paletteEvent, palletElementClick); initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: true }, palletElementClick); } function updateSelectionPaletteFromStorage() { if (localStorageKey && window.localStorage) { // Migrate old palettes over to new format. May want to remove this eventually. try { var oldPalette = window.localStorage[localStorageKey].split(",#"); if (oldPalette.length > 1) { delete window.localStorage[localStorageKey]; $.each(oldPalette, function(i, c) { addColorToSelectionPalette(c); }); } } catch(e) { } try { selectionPalette = window.localStorage[localStorageKey].split(";"); } catch (e) { } } } function addColorToSelectionPalette(color) { if (showSelectionPalette) { var rgb = tinycolor(color).toRgbString(); if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) { selectionPalette.push(rgb); while(selectionPalette.length > maxSelectionSize) { selectionPalette.shift(); } } if (localStorageKey && window.localStorage) { try { window.localStorage[localStorageKey] = selectionPalette.join(";"); } catch(e) { } } } } function getUniqueSelectionPalette() { var unique = []; if (opts.showPalette) { for (i = 0; i < selectionPalette.length; i++) { var rgb = tinycolor(selectionPalette[i]).toRgbString(); if (!paletteLookup[rgb]) { unique.push(selectionPalette[i]); } } } return unique.reverse().slice(0, opts.maxSelectionSize); } function drawPalette() { var currentColor = get(); var html = $.map(paletteArray, function (palette, i) { return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts.preferredFormat); }); updateSelectionPaletteFromStorage(); if (selectionPalette) { html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts.preferredFormat)); } paletteContainer.html(html.join("")); } function drawInitial() { if (opts.showInitial) { var initial = colorOnShow; var current = get(); initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts.preferredFormat)); } } function dragStart() { if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) { reflow(); } container.addClass(draggingClass); shiftMovementDirection = null; boundElement.trigger('dragstart.spectrum', [ get() ]); } function dragStop() { container.removeClass(draggingClass); boundElement.trigger('dragstop.spectrum', [ get() ]); } function setFromTextInput() { var value = textInput.val(); if ((value === null || value === "") && allowEmpty) { set(null); updateOriginalInput(true); } else { var tiny = tinycolor(value); if (tiny.ok) { set(tiny); updateOriginalInput(true); } else { textInput.addClass("sp-validation-error"); } } } function toggle() { if (visible) { hide(); } else { show(); } } function show() { var event = $.Event('beforeShow.spectrum'); if (visible) { reflow(); return; } boundElement.trigger(event, [ get() ]); if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) { return; } hideAll(); visible = true; $(doc).bind("click.spectrum", hide); $(window).bind("resize.spectrum", resize); replacer.addClass("sp-active"); container.removeClass("sp-hidden"); reflow(); updateUI(); colorOnShow = get(); drawInitial(); callbacks.show(colorOnShow); boundElement.trigger('show.spectrum', [ colorOnShow ]); } function hide(e) { // Return on right click if (e && e.type == "click" && e.button == 2) { return; } // Return if hiding is unnecessary if (!visible || flat) { return; } visible = false; $(doc).unbind("click.spectrum", hide); $(window).unbind("resize.spectrum", resize); replacer.removeClass("sp-active"); container.addClass("sp-hidden"); var colorHasChanged = !tinycolor.equals(get(), colorOnShow); if (colorHasChanged) { if (clickoutFiresChange && e !== "cancel") { updateOriginalInput(true); } else { revert(); } } callbacks.hide(get()); boundElement.trigger('hide.spectrum', [ get() ]); } function revert() { set(colorOnShow, true); } function set(color, ignoreFormatChange) { if (tinycolor.equals(color, get())) { // Update UI just in case a validation error needs // to be cleared. updateUI(); return; } var newColor, newHsv; if (!color && allowEmpty) { isEmpty = true; } else { isEmpty = false; newColor = tinycolor(color); newHsv = newColor.toHsv(); currentHue = (newHsv.h % 360) / 360; currentSaturation = newHsv.s; currentValue = newHsv.v; currentAlpha = newHsv.a; } updateUI(); if (newColor && newColor.ok && !ignoreFormatChange) { currentPreferredFormat = preferredFormat || newColor.format; } } function get(opts) { opts = opts || { }; if (allowEmpty && isEmpty) { return null; } return tinycolor.fromRatio({ h: currentHue, s: currentSaturation, v: currentValue, a: Math.round(currentAlpha * 100) / 100 }, { format: opts.format || currentPreferredFormat }); } function isValid() { return !textInput.hasClass("sp-validation-error"); } function move() { updateUI(); callbacks.move(get()); boundElement.trigger('move.spectrum', [ get() ]); } function updateUI() { textInput.removeClass("sp-validation-error"); updateHelperLocations(); // Update dragger background color (gradients take care of saturation and value). var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 }); dragger.css("background-color", flatColor.toHexString()); // Get a format that alpha will be included in (hex and names ignore alpha) var format = currentPreferredFormat; if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) { if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") { format = "rgb"; } } var realColor = get({ format: format }), displayColor = ''; //reset background info for preview element previewElement.removeClass("sp-clear-display"); previewElement.css('background-color', 'transparent'); if (!realColor && allowEmpty) { // Update the replaced elements background with icon indicating no color selection previewElement.addClass("sp-clear-display"); } else { var realHex = realColor.toHexString(), realRgb = realColor.toRgbString(); // Update the replaced elements background color (with actual selected color) if (rgbaSupport || realColor.alpha === 1) { previewElement.css("background-color", realRgb); } else { previewElement.css("background-color", "transparent"); previewElement.css("filter", realColor.toFilter()); } if (opts.showAlpha) { var rgb = realColor.toRgb(); rgb.a = 0; var realAlpha = tinycolor(rgb).toRgbString(); var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")"; if (IE) { alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex)); } else { alphaSliderInner.css("background", "-webkit-" + gradient); alphaSliderInner.css("background", "-moz-" + gradient); alphaSliderInner.css("background", "-ms-" + gradient); // Use current syntax gradient on unprefixed property. alphaSliderInner.css("background", "linear-gradient(to right, " + realAlpha + ", " + realHex + ")"); } } displayColor = realColor.toString(format); } // Update the text entry input as it changes happen if (opts.showInput) { textInput.val(displayColor); } if (opts.showPalette) { drawPalette(); } drawInitial(); } function updateHelperLocations() { var s = currentSaturation; var v = currentValue; if(allowEmpty && isEmpty) { //if selected color is empty, hide the helpers alphaSlideHelper.hide(); slideHelper.hide(); dragHelper.hide(); } else { //make sure helpers are visible alphaSlideHelper.show(); slideHelper.show(); dragHelper.show(); // Where to show the little circle in that displays your current selected color var dragX = s * dragWidth; var dragY = dragHeight - (v * dragHeight); dragX = Math.max( -dragHelperHeight, Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight) ); dragY = Math.max( -dragHelperHeight, Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight) ); dragHelper.css({ "top": dragY + "px", "left": dragX + "px" }); var alphaX = currentAlpha * alphaWidth; alphaSlideHelper.css({ "left": (alphaX - (alphaSlideHelperWidth / 2)) + "px" }); // Where to show the bar that displays your current selected hue var slideY = (currentHue) * slideHeight; slideHelper.css({ "top": (slideY - slideHelperHeight) + "px" }); } } function updateOriginalInput(fireCallback) { var color = get(), displayColor = '', hasChanged = !tinycolor.equals(color, colorOnShow); if (color) { displayColor = color.toString(currentPreferredFormat); // Update the selection palette with the current color addColorToSelectionPalette(color); } if (isInput) { boundElement.val(displayColor); } colorOnShow = color; if (fireCallback && hasChanged) { callbacks.change(color); boundElement.trigger('change', [ color ]); } } function reflow() { dragWidth = dragger.width(); dragHeight = dragger.height(); dragHelperHeight = dragHelper.height(); slideWidth = slider.width(); slideHeight = slider.height(); slideHelperHeight = slideHelper.height(); alphaWidth = alphaSlider.width(); alphaSlideHelperWidth = alphaSlideHelper.width(); if (!flat) { container.css("position", "absolute"); container.offset(getOffset(container, offsetElement)); } updateHelperLocations(); if (opts.showPalette) { drawPalette(); } boundElement.trigger('reflow.spectrum'); } function destroy() { boundElement.show(); offsetElement.unbind("click.spectrum touchstart.spectrum"); container.remove(); replacer.remove(); spectrums[spect.id] = null; } function option(optionName, optionValue) { if (optionName === undefined) { return $.extend({}, opts); } if (optionValue === undefined) { return opts[optionName]; } opts[optionName] = optionValue; applyOptions(); } function enable() { disabled = false; boundElement.attr("disabled", false); offsetElement.removeClass("sp-disabled"); } function disable() { hide(); disabled = true; boundElement.attr("disabled", true); offsetElement.addClass("sp-disabled"); } initialize(); var spect = { show: show, hide: hide, toggle: toggle, reflow: reflow, option: option, enable: enable, disable: disable, set: function (c) { set(c); updateOriginalInput(); }, get: get, destroy: destroy, container: container }; spect.id = spectrums.push(spect) - 1; return spect; } /** * checkOffset - get the offset below/above and left/right element depending on screen position * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js */ function getOffset(picker, input) { var extraY = 0; var dpWidth = picker.outerWidth(); var dpHeight = picker.outerHeight(); var inputHeight = input.outerHeight(); var doc = picker[0].ownerDocument; var docElem = doc.documentElement; var viewWidth = docElem.clientWidth + $(doc).scrollLeft(); var viewHeight = docElem.clientHeight + $(doc).scrollTop(); var offset = input.offset(); offset.top += inputHeight; offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0); offset.top -= Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(dpHeight + inputHeight - extraY) : extraY)); return offset; } /** * noop - do nothing */ function noop() { } /** * stopPropagation - makes the code only doing this a little easier to read in line */ function stopPropagation(e) { e.stopPropagation(); } /** * Create a function bound to a given object * Thanks to underscore.js */ function bind(func, obj) { var slice = Array.prototype.slice; var args = slice.call(arguments, 2); return function () { return func.apply(obj, args.concat(slice.call(arguments))); }; } /** * Lightweight drag helper. Handles containment within the element, so that * when dragging, the x is within [0,element.width] and y is within [0,element.height] */ function draggable(element, onmove, onstart, onstop) { onmove = onmove || function () { }; onstart = onstart || function () { }; onstop = onstop || function () { }; var doc = element.ownerDocument || document; var dragging = false; var offset = {}; var maxHeight = 0; var maxWidth = 0; var hasTouch = ('ontouchstart' in window); var duringDragEvents = {}; duringDragEvents["selectstart"] = prevent; duringDragEvents["dragstart"] = prevent; duringDragEvents["touchmove mousemove"] = move; duringDragEvents["touchend mouseup"] = stop; function prevent(e) { if (e.stopPropagation) { e.stopPropagation(); } if (e.preventDefault) { e.preventDefault(); } e.returnValue = false; } function move(e) { if (dragging) { // Mouseup happened outside of window if (IE && document.documentMode < 9 && !e.button) { return stop(); } var touches = e.originalEvent.touches; var pageX = touches ? touches[0].pageX : e.pageX; var pageY = touches ? touches[0].pageY : e.pageY; var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth)); var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight)); if (hasTouch) { // Stop scrolling in iOS prevent(e); } onmove.apply(element, [dragX, dragY, e]); } } function start(e) { var rightclick = (e.which) ? (e.which == 3) : (e.button == 2); var touches = e.originalEvent.touches; if (!rightclick && !dragging) { if (onstart.apply(element, arguments) !== false) { dragging = true; maxHeight = $(element).height(); maxWidth = $(element).width(); offset = $(element).offset(); $(doc).bind(duringDragEvents); $(doc.body).addClass("sp-dragging"); if (!hasTouch) { move(e); } prevent(e); } } } function stop() { if (dragging) { $(doc).unbind(duringDragEvents); $(doc.body).removeClass("sp-dragging"); onstop.apply(element, arguments); } dragging = false; } $(element).bind("touchstart mousedown", start); } function throttle(func, wait, debounce) { var timeout; return function () { var context = this, args = arguments; var throttler = function () { timeout = null; func.apply(context, args); }; if (debounce) clearTimeout(timeout); if (debounce || !timeout) timeout = setTimeout(throttler, wait); }; } function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}} /** * Define a jQuery plugin */ var dataID = "spectrum.id"; $.fn.spectrum = function (opts, extra) { if (typeof opts == "string") { var returnValue = this; var args = Array.prototype.slice.call( arguments, 1 ); this.each(function () { var spect = spectrums[$(this).data(dataID)]; if (spect) { var method = spect[opts]; if (!method) { throw new Error( "Spectrum: no such method: '" + opts + "'" ); } if (opts == "get") { returnValue = spect.get(); } else if (opts == "container") { returnValue = spect.container; } else if (opts == "option") { returnValue = spect.option.apply(spect, args); } else if (opts == "destroy") { spect.destroy(); $(this).removeData(dataID); } else { method.apply(spect, args); } } }); return returnValue; } // Initializing a new instance of spectrum return this.spectrum("destroy").each(function () { var options = $.extend({}, opts, $(this).data()); var spect = spectrum(this, options); $(this).data(dataID, spect.id); }); }; $.fn.spectrum.load = true; $.fn.spectrum.loadOpts = {}; $.fn.spectrum.draggable = draggable; $.fn.spectrum.defaults = defaultOpts; $.spectrum = { }; $.spectrum.localization = { }; $.spectrum.palettes = { }; $.fn.spectrum.processNativeColorInputs = function () { if (!inputTypeColorSupport) { $("input[type=color]").spectrum({ preferredFormat: "hex6" }); } }; // TinyColor v0.9.17 // https://github.com/bgrins/TinyColor // 2013-08-10, Brian Grinstead, MIT License (function() { var trimLeft = /^[\s,#]+/, trimRight = /\s+$/, tinyCounter = 0, math = Math, mathRound = math.round, mathMin = math.min, mathMax = math.max, mathRandom = math.random; function tinycolor (color, opts) { color = (color) ? color : ''; opts = opts || { }; // If input is already a tinycolor, return itself if (typeof color == "object" && color.hasOwnProperty("_tc_id")) { return color; } var rgb = inputToRGB(color); var r = rgb.r, g = rgb.g, b = rgb.b, a = rgb.a, roundA = mathRound(100*a) / 100, format = opts.format || rgb.format; // Don't let the range of [0,255] come back in [0,1]. // Potentially lose a little bit of precision here, but will fix issues where // .5 gets interpreted as half of the total, instead of half of 1 // If it was supposed to be 128, this was already taken care of by `inputToRgb` if (r < 1) { r = mathRound(r); } if (g < 1) { g = mathRound(g); } if (b < 1) { b = mathRound(b); } return { ok: rgb.ok, format: format, _tc_id: tinyCounter++, alpha: a, getAlpha: function() { return a; }, setAlpha: function(value) { a = boundAlpha(value); roundA = mathRound(100*a) / 100; }, toHsv: function() { var hsv = rgbToHsv(r, g, b); return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: a }; }, toHsvString: function() { var hsv = rgbToHsv(r, g, b); var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); return (a == 1) ? "hsv(" + h + ", " + s + "%, " + v + "%)" : "hsva(" + h + ", " + s + "%, " + v + "%, "+ roundA + ")"; }, toHsl: function() { var hsl = rgbToHsl(r, g, b); return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: a }; }, toHslString: function() { var hsl = rgbToHsl(r, g, b); var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); return (a == 1) ? "hsl(" + h + ", " + s + "%, " + l + "%)" : "hsla(" + h + ", " + s + "%, " + l + "%, "+ roundA + ")"; }, toHex: function(allow3Char) { return rgbToHex(r, g, b, allow3Char); }, toHexString: function(allow3Char) { return '#' + this.toHex(allow3Char); }, toHex8: function() { return rgbaToHex(r, g, b, a); }, toHex8String: function() { return '#' + this.toHex8(); }, toRgb: function() { return { r: mathRound(r), g: mathRound(g), b: mathRound(b), a: a }; }, toRgbString: function() { return (a == 1) ? "rgb(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ")" : "rgba(" + mathRound(r) + ", " + mathRound(g) + ", " + mathRound(b) + ", " + roundA + ")"; }, toPercentageRgb: function() { return { r: mathRound(bound01(r, 255) * 100) + "%", g: mathRound(bound01(g, 255) * 100) + "%", b: mathRound(bound01(b, 255) * 100) + "%", a: a }; }, toPercentageRgbString: function() { return (a == 1) ? "rgb(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%)" : "rgba(" + mathRound(bound01(r, 255) * 100) + "%, " + mathRound(bound01(g, 255) * 100) + "%, " + mathRound(bound01(b, 255) * 100) + "%, " + roundA + ")"; }, toName: function() { if (a === 0) { return "transparent"; } return hexNames[rgbToHex(r, g, b, true)] || false; }, toFilter: function(secondColor) { var hex8String = '#' + rgbaToHex(r, g, b, a); var secondHex8String = hex8String; var gradientType = opts && opts.gradientType ? "GradientType = 1, " : ""; if (secondColor) { var s = tinycolor(secondColor); secondHex8String = s.toHex8String(); } return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"; }, toString: function(format) { var formatSet = !!format; format = format || this.format; var formattedString = false; var hasAlphaAndFormatNotSet = !formatSet && a < 1 && a > 0; var formatWithAlpha = hasAlphaAndFormatNotSet && (format === "hex" || format === "hex6" || format === "hex3" || format === "name"); if (format === "rgb") { formattedString = this.toRgbString(); } if (format === "prgb") { formattedString = this.toPercentageRgbString(); } if (format === "hex" || format === "hex6") { formattedString = this.toHexString(); } if (format === "hex3") { formattedString = this.toHexString(true); } if (format === "hex8") { formattedString = this.toHex8String(); } if (format === "name") { formattedString = this.toName(); } if (format === "hsl") { formattedString = this.toHslString(); } if (format === "hsv") { formattedString = this.toHsvString(); } if (formatWithAlpha) { return this.toRgbString(); } return formattedString || this.toHexString(); } }; } // If input is an object, force 1 into "1.0" to handle ratios properly // String input requires "1.0" as input, so 1 will be treated as 1 tinycolor.fromRatio = function(color, opts) { if (typeof color == "object") { var newColor = {}; for (var i in color) { if (color.hasOwnProperty(i)) { if (i === "a") { newColor[i] = color[i]; } else { newColor[i] = convertToPercentage(color[i]); } } } color = newColor; } return tinycolor(color, opts); }; // Given a string or object, convert that input to RGB // Possible string inputs: // // "red" // "#f00" or "f00" // "#ff0000" or "ff0000" // "#ff000000" or "ff000000" // "rgb 255 0 0" or "rgb (255, 0, 0)" // "rgb 1.0 0 0" or "rgb (1, 0, 0)" // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" // function inputToRGB(color) { var rgb = { r: 0, g: 0, b: 0 }; var a = 1; var ok = false; var format = false; if (typeof color == "string") { color = stringInputToObject(color); } if (typeof color == "object") { if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) { rgb = rgbToRgb(color.r, color.g, color.b); ok = true; format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; } else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) { color.s = convertToPercentage(color.s); color.v = convertToPercentage(color.v); rgb = hsvToRgb(color.h, color.s, color.v); ok = true; format = "hsv"; } else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) { color.s = convertToPercentage(color.s); color.l = convertToPercentage(color.l); rgb = hslToRgb(color.h, color.s, color.l); ok = true; format = "hsl"; } if (color.hasOwnProperty("a")) { a = color.a; } } a = boundAlpha(a); return { ok: ok, format: color.format || format, r: mathMin(255, mathMax(rgb.r, 0)), g: mathMin(255, mathMax(rgb.g, 0)), b: mathMin(255, mathMax(rgb.b, 0)), a: a }; } // Conversion Functions // -------------------- // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: // // `rgbToRgb` // Handle bounds / percentage checking to conform to CSS color spec // // *Assumes:* r, g, b in [0, 255] or [0, 1] // *Returns:* { r, g, b } in [0, 255] function rgbToRgb(r, g, b){ return { r: bound01(r, 255) * 255, g: bound01(g, 255) * 255, b: bound01(b, 255) * 255 }; } // `rgbToHsl` // Converts an RGB color value to HSL. // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] // *Returns:* { h, s, l } in [0,1] function rgbToHsl(r, g, b) { r = bound01(r, 255); g = bound01(g, 255); b = bound01(b, 255); var max = mathMax(r, g, b), min = mathMin(r, g, b); var h, s, l = (max + min) / 2; if(max == min) { h = s = 0; // achromatic } else { var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch(max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: h, s: s, l: l }; } // `hslToRgb` // Converts an HSL color value to RGB. // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] // *Returns:* { r, g, b } in the set [0, 255] function hslToRgb(h, s, l) { var r, g, b; h = bound01(h, 360); s = bound01(s, 100); l = bound01(l, 100); function hue2rgb(p, q, t) { if(t < 0) t += 1; if(t > 1) t -= 1; if(t < 1/6) return p + (q - p) * 6 * t; if(t < 1/2) return q; if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; return p; } if(s === 0) { r = g = b = l; // achromatic } else { var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; r = hue2rgb(p, q, h + 1/3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1/3); } return { r: r * 255, g: g * 255, b: b * 255 }; } // `rgbToHsv` // Converts an RGB color value to HSV // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] // *Returns:* { h, s, v } in [0,1] function rgbToHsv(r, g, b) { r = bound01(r, 255); g = bound01(g, 255); b = bound01(b, 255); var max = mathMax(r, g, b), min = mathMin(r, g, b); var h, s, v = max; var d = max - min; s = max === 0 ? 0 : d / max; if(max == min) { h = 0; // achromatic } else { switch(max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: h, s: s, v: v }; } // `hsvToRgb` // Converts an HSV color value to RGB. // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] // *Returns:* { r, g, b } in the set [0, 255] function hsvToRgb(h, s, v) { h = bound01(h, 360) * 6; s = bound01(s, 100); v = bound01(v, 100); var i = math.floor(h), f = h - i, p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s), mod = i % 6, r = [v, q, p, p, t, v][mod], g = [t, v, v, q, p, p][mod], b = [p, p, t, v, v, q][mod]; return { r: r * 255, g: g * 255, b: b * 255 }; } // `rgbToHex` // Converts an RGB color to hex // Assumes r, g, and b are contained in the set [0, 255] // Returns a 3 or 6 character hex function rgbToHex(r, g, b, allow3Char) { var hex = [ pad2(mathRound(r).toString(16)), pad2(mathRound(g).toString(16)), pad2(mathRound(b).toString(16)) ]; // Return a 3 character hex if possible if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); } return hex.join(""); } // `rgbaToHex` // Converts an RGBA color plus alpha transparency to hex // Assumes r, g, b and a are contained in the set [0, 255] // Returns an 8 character hex function rgbaToHex(r, g, b, a) { var hex = [ pad2(convertDecimalToHex(a)), pad2(mathRound(r).toString(16)), pad2(mathRound(g).toString(16)), pad2(mathRound(b).toString(16)) ]; return hex.join(""); } // `equals` // Can be called with any tinycolor input tinycolor.equals = function (color1, color2) { if (!color1 || !color2) { return false; } return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); }; tinycolor.random = function() { return tinycolor.fromRatio({ r: mathRandom(), g: mathRandom(), b: mathRandom() }); }; // Modification Functions // ---------------------- // Thanks to less.js for some of the basics here // tinycolor.desaturate = function (color, amount) { amount = (amount === 0) ? 0 : (amount || 10); var hsl = tinycolor(color).toHsl(); hsl.s -= amount / 100; hsl.s = clamp01(hsl.s); return tinycolor(hsl); }; tinycolor.saturate = function (color, amount) { amount = (amount === 0) ? 0 : (amount || 10); var hsl = tinycolor(color).toHsl(); hsl.s += amount / 100; hsl.s = clamp01(hsl.s); return tinycolor(hsl); }; tinycolor.greyscale = function(color) { return tinycolor.desaturate(color, 100); }; tinycolor.lighten = function(color, amount) { amount = (amount === 0) ? 0 : (amount || 10); var hsl = tinycolor(color).toHsl(); hsl.l += amount / 100; hsl.l = clamp01(hsl.l); return tinycolor(hsl); }; tinycolor.darken = function (color, amount) { amount = (amount === 0) ? 0 : (amount || 10); var hsl = tinycolor(color).toHsl(); hsl.l -= amount / 100; hsl.l = clamp01(hsl.l); return tinycolor(hsl); }; tinycolor.complement = function(color) { var hsl = tinycolor(color).toHsl(); hsl.h = (hsl.h + 180) % 360; return tinycolor(hsl); }; // Combination Functions // --------------------- // Thanks to jQuery xColor for some of the ideas behind these // tinycolor.triad = function(color) { var hsl = tinycolor(color).toHsl(); var h = hsl.h; return [ tinycolor(color), tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) ]; }; tinycolor.tetrad = function(color) { var hsl = tinycolor(color).toHsl(); var h = hsl.h; return [ tinycolor(color), tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) ]; }; tinycolor.splitcomplement = function(color) { var hsl = tinycolor(color).toHsl(); var h = hsl.h; return [ tinycolor(color), tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) ]; }; tinycolor.analogous = function(color, results, slices) { results = results || 6; slices = slices || 30; var hsl = tinycolor(color).toHsl(); var part = 360 / slices; var ret = [tinycolor(color)]; for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { hsl.h = (hsl.h + part) % 360; ret.push(tinycolor(hsl)); } return ret; }; tinycolor.monochromatic = function(color, results) { results = results || 6; var hsv = tinycolor(color).toHsv(); var h = hsv.h, s = hsv.s, v = hsv.v; var ret = []; var modification = 1 / results; while (results--) { ret.push(tinycolor({ h: h, s: s, v: v})); v = (v + modification) % 1; } return ret; }; // Readability Functions // --------------------- // // `readability` // Analyze the 2 colors and returns an object with the following properties: // `brightness`: difference in brightness between the two colors // `color`: difference in color/hue between the two colors tinycolor.readability = function(color1, color2) { var a = tinycolor(color1).toRgb(); var b = tinycolor(color2).toRgb(); var brightnessA = (a.r * 299 + a.g * 587 + a.b * 114) / 1000; var brightnessB = (b.r * 299 + b.g * 587 + b.b * 114) / 1000; var colorDiff = ( Math.max(a.r, b.r) - Math.min(a.r, b.r) + Math.max(a.g, b.g) - Math.min(a.g, b.g) + Math.max(a.b, b.b) - Math.min(a.b, b.b) ); return { brightness: Math.abs(brightnessA - brightnessB), color: colorDiff }; }; // `readable` // http://www.w3.org/TR/AERT#color-contrast // Ensure that foreground and background color combinations provide sufficient contrast. // *Example* // tinycolor.readable("#000", "#111") => false tinycolor.readable = function(color1, color2) { var readability = tinycolor.readability(color1, color2); return readability.brightness > 125 && readability.color > 500; }; // `mostReadable` // Given a base color and a list of possible foreground or background // colors for that base, returns the most readable color. // *Example* // tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000" tinycolor.mostReadable = function(baseColor, colorList) { var bestColor = null; var bestScore = 0; var bestIsReadable = false; for (var i=0; i < colorList.length; i++) { // We normalize both around the "acceptable" breaking point, // but rank brightness constrast higher than hue. var readability = tinycolor.readability(baseColor, colorList[i]); var readable = readability.brightness > 125 && readability.color > 500; var score = 3 * (readability.brightness / 125) + (readability.color / 500); if ((readable && ! bestIsReadable) || (readable && bestIsReadable && score > bestScore) || ((! readable) && (! bestIsReadable) && score > bestScore)) { bestIsReadable = readable; bestScore = score; bestColor = tinycolor(colorList[i]); } } return bestColor; }; // Big List of Colors // ------------------ // var names = tinycolor.names = { aliceblue: "f0f8ff", antiquewhite: "faebd7", aqua: "0ff", aquamarine: "7fffd4", azure: "f0ffff", beige: "f5f5dc", bisque: "ffe4c4", black: "000", blanchedalmond: "ffebcd", blue: "00f", blueviolet: "8a2be2", brown: "a52a2a", burlywood: "deb887", burntsienna: "ea7e5d", cadetblue: "5f9ea0", chartreuse: "7fff00", chocolate: "d2691e", coral: "ff7f50", cornflowerblue: "6495ed", cornsilk: "fff8dc", crimson: "dc143c", cyan: "0ff", darkblue: "00008b", darkcyan: "008b8b", darkgoldenrod: "b8860b", darkgray: "a9a9a9", darkgreen: "006400", darkgrey: "a9a9a9", darkkhaki: "bdb76b", darkmagenta: "8b008b", darkolivegreen: "556b2f", darkorange: "ff8c00", darkorchid: "9932cc", darkred: "8b0000", darksalmon: "e9967a", darkseagreen: "8fbc8f", darkslateblue: "483d8b", darkslategray: "2f4f4f", darkslategrey: "2f4f4f", darkturquoise: "00ced1", darkviolet: "9400d3", deeppink: "ff1493", deepskyblue: "00bfff", dimgray: "696969", dimgrey: "696969", dodgerblue: "1e90ff", firebrick: "b22222", floralwhite: "fffaf0", forestgreen: "228b22", fuchsia: "f0f", gainsboro: "dcdcdc", ghostwhite: "f8f8ff", gold: "ffd700", goldenrod: "daa520", gray: "808080", green: "008000", greenyellow: "adff2f", grey: "808080", honeydew: "f0fff0", hotpink: "ff69b4", indianred: "cd5c5c", indigo: "4b0082", ivory: "fffff0", khaki: "f0e68c", lavender: "e6e6fa", lavenderblush: "fff0f5", lawngreen: "7cfc00", lemonchiffon: "fffacd", lightblue: "add8e6", lightcoral: "f08080", lightcyan: "e0ffff", lightgoldenrodyellow: "fafad2", lightgray: "d3d3d3", lightgreen: "90ee90", lightgrey: "d3d3d3", lightpink: "ffb6c1", lightsalmon: "ffa07a", lightseagreen: "20b2aa", lightskyblue: "87cefa", lightslategray: "789", lightslategrey: "789", lightsteelblue: "b0c4de", lightyellow: "ffffe0", lime: "0f0", limegreen: "32cd32", linen: "faf0e6", magenta: "f0f", maroon: "800000", mediumaquamarine: "66cdaa", mediumblue: "0000cd", mediumorchid: "ba55d3", mediumpurple: "9370db", mediumseagreen: "3cb371", mediumslateblue: "7b68ee", mediumspringgreen: "00fa9a", mediumturquoise: "48d1cc", mediumvioletred: "c71585", midnightblue: "191970", mintcream: "f5fffa", mistyrose: "ffe4e1", moccasin: "ffe4b5", navajowhite: "ffdead", navy: "000080", oldlace: "fdf5e6", olive: "808000", olivedrab: "6b8e23", orange: "ffa500", orangered: "ff4500", orchid: "da70d6", palegoldenrod: "eee8aa", palegreen: "98fb98", paleturquoise: "afeeee", palevioletred: "db7093", papayawhip: "ffefd5", peachpuff: "ffdab9", peru: "cd853f", pink: "ffc0cb", plum: "dda0dd", powderblue: "b0e0e6", purple: "800080", red: "f00", rosybrown: "bc8f8f", royalblue: "4169e1", saddlebrown: "8b4513", salmon: "fa8072", sandybrown: "f4a460", seagreen: "2e8b57", seashell: "fff5ee", sienna: "a0522d", silver: "c0c0c0", skyblue: "87ceeb", slateblue: "6a5acd", slategray: "708090", slategrey: "708090", snow: "fffafa", springgreen: "00ff7f", steelblue: "4682b4", tan: "d2b48c", teal: "008080", thistle: "d8bfd8", tomato: "ff6347", turquoise: "40e0d0", violet: "ee82ee", wheat: "f5deb3", white: "fff", whitesmoke: "f5f5f5", yellow: "ff0", yellowgreen: "9acd32" }; // Make it easy to access colors via `hexNames[hex]` var hexNames = tinycolor.hexNames = flip(names); // Utilities // --------- // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` function flip(o) { var flipped = { }; for (var i in o) { if (o.hasOwnProperty(i)) { flipped[o[i]] = i; } } return flipped; } // Return a valid alpha value [0,1] with all invalid values being set to 1 function boundAlpha(a) { a = parseFloat(a); if (isNaN(a) || a < 0 || a > 1) { a = 1; } return a; } // Take input from [0, n] and return it as [0, 1] function bound01(n, max) { if (isOnePointZero(n)) { n = "100%"; } var processPercent = isPercentage(n); n = mathMin(max, mathMax(0, parseFloat(n))); // Automatically convert percentage into number if (processPercent) { n = parseInt(n * max, 10) / 100; } // Handle floating point rounding errors if ((math.abs(n - max) < 0.000001)) { return 1; } // Convert into [0, 1] range if it isn't already return (n % max) / parseFloat(max); } // Force a number between 0 and 1 function clamp01(val) { return mathMin(1, mathMax(0, val)); } // Parse a base-16 hex value into a base-10 integer function parseIntFromHex(val) { return parseInt(val, 16); } // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 // function isOnePointZero(n) { return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; } // Check to see if string passed in is a percentage function isPercentage(n) { return typeof n === "string" && n.indexOf('%') != -1; } // Force a hex value to have 2 characters function pad2(c) { return c.length == 1 ? '0' + c : '' + c; } // Replace a decimal with it's percentage value function convertToPercentage(n) { if (n <= 1) { n = (n * 100) + "%"; } return n; } // Converts a decimal to a hex value function convertDecimalToHex(d) { return Math.round(parseFloat(d) * 255).toString(16); } // Converts a hex value to a decimal function convertHexToDecimal(h) { return (parseIntFromHex(h) / 255); } var matchers = (function() { // var CSS_INTEGER = "[-\\+]?\\d+%?"; // var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; // Actual matching. // Parentheses and commas are optional, but not required. // Whitespace can take the place of commas or opening paren var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; return { rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ }; })(); // `stringInputToObject` // Permissive string parsing. Take in a number of formats, and output an object // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` function stringInputToObject(color) { color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); var named = false; if (names[color]) { color = names[color]; named = true; } else if (color == 'transparent') { return { r: 0, g: 0, b: 0, a: 0, format: "name" }; } // Try to match string input using regular expressions. // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] // Just return an object and let the conversion functions handle that. // This way the result will be the same whether the tinycolor is initialized with string or object. var match; if ((match = matchers.rgb.exec(color))) { return { r: match[1], g: match[2], b: match[3] }; } if ((match = matchers.rgba.exec(color))) { return { r: match[1], g: match[2], b: match[3], a: match[4] }; } if ((match = matchers.hsl.exec(color))) { return { h: match[1], s: match[2], l: match[3] }; } if ((match = matchers.hsla.exec(color))) { return { h: match[1], s: match[2], l: match[3], a: match[4] }; } if ((match = matchers.hsv.exec(color))) { return { h: match[1], s: match[2], v: match[3] }; } if ((match = matchers.hex8.exec(color))) { return { a: convertHexToDecimal(match[1]), r: parseIntFromHex(match[2]), g: parseIntFromHex(match[3]), b: parseIntFromHex(match[4]), format: named ? "name" : "hex8" }; } if ((match = matchers.hex6.exec(color))) { return { r: parseIntFromHex(match[1]), g: parseIntFromHex(match[2]), b: parseIntFromHex(match[3]), format: named ? "name" : "hex" }; } if ((match = matchers.hex3.exec(color))) { return { r: parseIntFromHex(match[1] + '' + match[1]), g: parseIntFromHex(match[2] + '' + match[2]), b: parseIntFromHex(match[3] + '' + match[3]), format: named ? "name" : "hex" }; } return false; } // Expose tinycolor to window, does not need to run in non-browser context. window.tinycolor = tinycolor; })(); $(function () { if ($.fn.spectrum.load) { $.fn.spectrum.processNativeColorInputs(); } }); })(window, jQuery); PKR\^V _ _!js/spectrum/redux-spectrum.min.jsnu[!function(a,b,c){function d(a,b,c,d){for(var e=[],f=0;f')}else{var l="sp-clear-display";e.push('')}}return"
    "+e.join("")+"
    "}function e(){for(var a=0;aMath.abs(b-e);sa=f?"x":"y"}}else sa=null;var g=!sa||"x"===sa,h=!sa||"y"===sa;g&&(ia=parseFloat(a/_)),h&&(ja=parseFloat((aa-b)/aa)),Va=!1,T.showAlpha||(ka=1),K()},A,B),Qa?(H(Qa),L(),Ta=Sa||tinycolor(Qa).format,w(Qa)):L(),U&&E();var d=q?"mousedown.spectrum":"click.spectrum touchstart.spectrum";Fa.delegate(".sp-thumb-el",d,a),Ga.delegate(".sp-thumb-el:nth-child(1)",d,{ignore:!0},a)}function v(){if(W&&a.localStorage){try{var c=a.localStorage[W].split(",#");c.length>1&&(delete a.localStorage[W],b.each(c,function(a,b){w(b)}))}catch(d){}try{oa=a.localStorage[W].split(";")}catch(d){}}}function w(c){if(V){var d=tinycolor(c).toRgbString();if(!na[d]&&-1===b.inArray(d,oa))for(oa.push(d);oa.length>pa;)oa.shift();if(W&&a.localStorage)try{a.localStorage[W]=oa.join(";")}catch(e){}}}function x(){var a=[];if(T.showPalette)for(i=0;i=aa||0>=_||0>=ca)&&O(),wa.addClass(qa),sa=null,ua.trigger("dragstart.spectrum",[I()])}function B(){wa.removeClass(qa),ua.trigger("dragstop.spectrum",[I()])}function C(){var a=Ea.val();if(null!==a&&""!==a||!Wa){var b=tinycolor(a);b.ok?(H(b),N(!0)):Ea.addClass("sp-validation-error")}else H(null),N(!0)}function D(){$?F():E()}function E(){var c=b.Event("beforeShow.spectrum");return $?void O():(ua.trigger(c,[I()]),void(Y.beforeShow(I())===!1||c.isDefaultPrevented()||(e(),$=!0,b(ta).bind("click.spectrum",F),b(a).bind("resize.spectrum",Z),Na.addClass("sp-active"),wa.removeClass("sp-hidden"),O(),L(),Ra=I(),z(),Y.show(Ra),ua.trigger("show.spectrum",[Ra]))))}function F(c){if((!c||"click"!=c.type||2!=c.button)&&$&&!U){$=!1,b(ta).unbind("click.spectrum",F),b(a).unbind("resize.spectrum",Z),Na.removeClass("sp-active"),wa.addClass("sp-hidden");var d=!tinycolor.equals(I(),Ra);d&&(Ua&&"cancel"!==c?N(!0):G()),Y.hide(I()),ua.trigger("hide.spectrum",[I()])}}function G(){H(Ra,!0)}function H(a,b){if(tinycolor.equals(a,I()))return void L();var c,d;!a&&Wa?Va=!0:(Va=!1,c=tinycolor(a),d=c.toHsv(),ha=d.h%360/360,ia=d.s,ja=d.v,ka=d.a),L(),c&&c.ok&&!b&&(Ta=Sa||c.format)}function I(a){return a=a||{},Wa&&Va?null:tinycolor.fromRatio({h:ha,s:ia,v:ja,a:Math.round(100*ka)/100},{format:a.format||Ta})}function J(){return!Ea.hasClass("sp-validation-error")}function K(){L(),Y.move(I()),ua.trigger("move.spectrum",[I()])}function L(){Ea.removeClass("sp-validation-error"),M();var a=tinycolor.fromRatio({h:ha,s:1,v:1});xa.css("background-color",a.toHexString());var b=Ta;1>ka&&(0!==ka||"name"!==b)&&("hex"===b||"hex3"===b||"hex6"===b||"name"===b)&&(b="rgb");var c=I({format:b}),d="";if(Pa.removeClass("sp-clear-display"),Pa.css("background-color","transparent"),!c&&Wa)Pa.addClass("sp-clear-display");else{var e=c.toHexString(),f=c.toRgbString();if(r||1===c.alpha?Pa.css("background-color",f):(Pa.css("background-color","transparent"),Pa.css("filter",c.toFilter())),T.showAlpha){var g=c.toRgb();g.a=0;var h=tinycolor(g).toRgbString(),i="linear-gradient(left, "+h+", "+e+")";q?Ba.css("filter",tinycolor(h).toFilter({gradientType:1},e)):(Ba.css("background","-webkit-"+i),Ba.css("background","-moz-"+i),Ba.css("background","-ms-"+i),Ba.css("background","linear-gradient(to right, "+h+", "+e+")"))}d=c.toString(b)}T.showInput&&Ea.val(d),T.showPalette&&y(),z()}function M(){var a=ia,b=ja;if(Wa&&Va)Da.hide(),Aa.hide(),ya.hide();else{Da.show(),Aa.show(),ya.show();var c=a*_,d=aa-b*aa;c=Math.max(-ba,Math.min(_-ba,c-ba)),d=Math.max(-ba,Math.min(aa-ba,d-ba)),ya.css({top:d+"px",left:c+"px"});var e=ka*ea;Da.css({left:e-fa/2+"px"});var f=ha*ca;Aa.css({top:f-ga+"px"})}}function N(a){var b=I(),c="",d=!tinycolor.equals(b,Ra);b&&(c=b.toString(Ta),w(b)),Ka&&ua.val(c),Ra=b,a&&d&&(Y.change(b),ua.trigger("change",[b]))}function O(){_=xa.width(),aa=xa.height(),ba=ya.height(),da=za.width(),ca=za.height(),ga=Aa.height(),ea=Ca.width(),fa=Da.width(),U||(wa.css("position","absolute"),wa.offset(h(wa,Oa))),M(),T.showPalette&&y(),ua.trigger("reflow.spectrum")}function P(){ua.show(),Oa.unbind("click.spectrum touchstart.spectrum"),wa.remove(),Na.remove(),p[Ya.id]=null}function Q(a,d){return a===c?b.extend({},T):d===c?T[a]:(T[a]=d,void l())}function R(){va=!1,ua.attr("disabled",!1),Oa.removeClass("sp-disabled")}function S(){F(),va=!0,ua.attr("disabled",!0),Oa.addClass("sp-disabled")}var T=f(j,g),U=T.flat,V=T.showSelectionPalette,W=T.localStorageKey,X=T.theme,Y=T.callbacks,Z=n(O,10),$=!1,_=0,aa=0,ba=0,ca=0,da=0,ea=0,fa=0,ga=0,ha=0,ia=0,ja=0,ka=1,la=[],ma=[],na={},oa=T.selectionPalette.slice(0),pa=T.maxSelectionSize,qa="sp-dragging",ra=T.inputText,sa=null,ta=g.ownerDocument,ua=(ta.body,b(g)),va=!1,wa=b(u,ta).addClass(X),xa=wa.find(".sp-color"),ya=wa.find(".sp-dragger"),za=wa.find(".sp-hue"),Aa=wa.find(".sp-slider"),Ba=wa.find(".sp-alpha-inner"),Ca=wa.find(".sp-alpha"),Da=wa.find(".sp-alpha-handle"),Ea=wa.find(".sp-input"),Fa=wa.find(".sp-palette"),Ga=wa.find(".sp-initial"),Ha=wa.find(".sp-cancel"),Ia=wa.find(".sp-clear"),Ja=wa.find(".sp-choose"),Ka=ua.is("input"),La=Ka&&s&&"color"===ua.attr("type"),Ma=Ka&&!U,Na=Ma?b(t).addClass(X).addClass(T.className).addClass(T.replacerClassName):b([]),Oa=Ma?Na:ua,Pa=Na.find(".sp-preview-inner"),Qa=T.color||Ka&&ua.val(),Ra=!1,Sa=T.preferredFormat,Ta=Sa,Ua=!T.showButtons||T.clickoutFiresChange,Va=!Qa,Wa=T.allowEmpty&&!La;if(""!==ra){var Xa=b(Oa).find("div.sp-dd");Xa.text(ra)}o();var Ya={show:E,hide:F,toggle:D,reflow:O,option:Q,enable:R,disable:S,set:function(a){H(a),N()},get:I,destroy:P,container:wa};return Ya.id=p.push(Ya)-1,Ya}function h(a,c){var d=0,e=a.outerWidth(),f=a.outerHeight(),g=c.outerHeight(),h=a[0].ownerDocument,i=h.documentElement,j=i.clientWidth+b(h).scrollLeft(),k=i.clientHeight+b(h).scrollTop(),l=c.offset();return l.top+=g,l.left-=Math.min(l.left,l.left+e>j&&j>e?Math.abs(l.left+e-j):0),l.top-=Math.min(l.top,l.top+f>k&&k>f?Math.abs(f+g-d):d),l}function j(){}function k(a){a.stopPropagation()}function l(a,b){var c=Array.prototype.slice,d=c.call(arguments,2);return function(){return a.apply(b,d.concat(c.call(arguments)))}}function m(c,d,e,f){function g(a){a.stopPropagation&&a.stopPropagation(),a.preventDefault&&a.preventDefault(),a.returnValue=!1}function h(a){if(l){if(q&&document.documentMode<9&&!a.button)return j();var b=a.originalEvent.touches,e=b?b[0].pageX:a.pageX,f=b?b[0].pageY:a.pageY,h=Math.max(0,Math.min(e-m.left,o)),i=Math.max(0,Math.min(f-m.top,n));p&&g(a),d.apply(c,[h,i,a])}}function i(a){var d=a.which?3==a.which:2==a.button;a.originalEvent.touches;d||l||e.apply(c,arguments)!==!1&&(l=!0,n=b(c).height(),o=b(c).width(),m=b(c).offset(),b(k).bind(r),b(k.body).addClass("sp-dragging"),p||h(a),g(a))}function j(){l&&(b(k).unbind(r),b(k.body).removeClass("sp-dragging"),f.apply(c,arguments)),l=!1}d=d||function(){},e=e||function(){},f=f||function(){};var k=c.ownerDocument||document,l=!1,m={},n=0,o=0,p="ontouchstart"in a,r={};r.selectstart=g,r.dragstart=g,r["touchmove mousemove"]=h,r["touchend mouseup"]=j,b(c).bind("touchstart mousedown",i)}function n(a,b,c){var d;return function(){var e=this,f=arguments,g=function(){d=null,a.apply(e,f)};c&&clearTimeout(d),(c||!d)&&(d=setTimeout(g,b))}}var o={beforeShow:j,move:j,change:j,show:j,hide:j,color:!1,flat:!1,showInput:!1,allowEmpty:!1,showButtons:!0,clickoutFiresChange:!1,showInitial:!1,showPalette:!1,showPaletteOnly:!1,showSelectionPalette:!0,localStorageKey:!1,appendTo:"body",maxSelectionSize:7,cancelText:"cancel",chooseText:"choose",clearText:"Clear Color Selection",preferredFormat:!1,className:"",containerClassName:"",replacerClassName:"",showAlpha:!1,theme:"sp-light",palette:[["#ffffff","#000000","#ff0000","#ff8000","#ffff00","#008000","#0000ff","#4b0082","#9400d3"]],selectionPalette:[],disabled:!1,inputText:""},p=[],q=!!/msie/i.exec(a.navigator.userAgent),r=function(){function a(a,b){return!!~(""+a).indexOf(b)}var b=document.createElement("div"),c=b.style;return c.cssText="background-color:rgba(0,0,0,.5)",a(c.backgroundColor,"rgba")||a(c.backgroundColor,"hsla")}(),s=function(){var a=b("")[0];return"color"===a.type&&"#ffffff"!==a.value}(),t=["
    ","
    ","
    ","
    "].join(""),u=function(){var a="";if(q)for(var b=1;6>=b;b++)a+="
    ";return["
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ","
    ",a,"
    ","
    ","
    ","
    ","
    ","","
    ","
    ","
    ","","","
    ","
    ","
    "].join("")}(),v="spectrum.id";b.fn.spectrum=function(a,c){if("string"==typeof a){var d=this,e=Array.prototype.slice.call(arguments,1);return this.each(function(){var c=p[b(this).data(v)];if(c){var f=c[a];if(!f)throw new Error("Spectrum: no such method: '"+a+"'");"get"==a?d=c.get():"container"==a?d=c.container:"option"==a?d=c.option.apply(c,e):"destroy"==a?(c.destroy(),b(this).removeData(v)):f.apply(c,e)}}),d}return this.spectrum("destroy").each(function(){var c=b.extend({},a,b(this).data()),d=g(this,c);b(this).data(v,d.id)})},b.fn.spectrum.load=!0,b.fn.spectrum.loadOpts={},b.fn.spectrum.draggable=m,b.fn.spectrum.defaults=o,b.spectrum={},b.spectrum.localization={},b.spectrum.palettes={},b.fn.spectrum.processNativeColorInputs=function(){s||b("input[type=color]").spectrum({preferredFormat:"hex6"})},function(){function b(a,d){if(a=a?a:"",d=d||{},"object"==typeof a&&a.hasOwnProperty("_tc_id"))return a;var f=c(a),h=f.r,k=f.g,n=f.b,o=f.a,p=A(100*o)/100,q=d.format||f.format;return 1>h&&(h=A(h)),1>k&&(k=A(k)),1>n&&(n=A(n)),{ok:f.ok,format:q,_tc_id:y++,alpha:o,getAlpha:function(){return o},setAlpha:function(a){o=l(a),p=A(100*o)/100},toHsv:function(){var a=g(h,k,n);return{h:360*a.h,s:a.s,v:a.v,a:o}},toHsvString:function(){var a=g(h,k,n),b=A(360*a.h),c=A(100*a.s),d=A(100*a.v);return 1==o?"hsv("+b+", "+c+"%, "+d+"%)":"hsva("+b+", "+c+"%, "+d+"%, "+p+")"},toHsl:function(){var a=e(h,k,n);return{h:360*a.h,s:a.s,l:a.l,a:o}},toHslString:function(){var a=e(h,k,n),b=A(360*a.h),c=A(100*a.s),d=A(100*a.l);return 1==o?"hsl("+b+", "+c+"%, "+d+"%)":"hsla("+b+", "+c+"%, "+d+"%, "+p+")"},toHex:function(a){return i(h,k,n,a)},toHexString:function(a){return"#"+this.toHex(a)},toHex8:function(){return j(h,k,n,o)},toHex8String:function(){return"#"+this.toHex8()},toRgb:function(){return{r:A(h),g:A(k),b:A(n),a:o}},toRgbString:function(){return 1==o?"rgb("+A(h)+", "+A(k)+", "+A(n)+")":"rgba("+A(h)+", "+A(k)+", "+A(n)+", "+p+")"},toPercentageRgb:function(){return{r:A(100*m(h,255))+"%",g:A(100*m(k,255))+"%",b:A(100*m(n,255))+"%",a:o}},toPercentageRgbString:function(){return 1==o?"rgb("+A(100*m(h,255))+"%, "+A(100*m(k,255))+"%, "+A(100*m(n,255))+"%)":"rgba("+A(100*m(h,255))+"%, "+A(100*m(k,255))+"%, "+A(100*m(n,255))+"%, "+p+")"},toName:function(){return 0===o?"transparent":F[i(h,k,n,!0)]||!1},toFilter:function(a){var c="#"+j(h,k,n,o),e=c,f=d&&d.gradientType?"GradientType = 1, ":"";if(a){var g=b(a);e=g.toHex8String()}return"progid:DXImageTransform.Microsoft.gradient("+f+"startColorstr="+c+",endColorstr="+e+")"},toString:function(a){var b=!!a;a=a||this.format;var c=!1,d=!b&&1>o&&o>0,e=d&&("hex"===a||"hex6"===a||"hex3"===a||"name"===a);return"rgb"===a&&(c=this.toRgbString()),"prgb"===a&&(c=this.toPercentageRgbString()),("hex"===a||"hex6"===a)&&(c=this.toHexString()),"hex3"===a&&(c=this.toHexString(!0)),"hex8"===a&&(c=this.toHex8String()),"name"===a&&(c=this.toName()),"hsl"===a&&(c=this.toHslString()),"hsv"===a&&(c=this.toHsvString()),e?this.toRgbString():c||this.toHexString()}}}function c(a){var b={r:0,g:0,b:0},c=1,e=!1,g=!1;return"string"==typeof a&&(a=v(a)),"object"==typeof a&&(a.hasOwnProperty("r")&&a.hasOwnProperty("g")&&a.hasOwnProperty("b")?(b=d(a.r,a.g,a.b),e=!0,g="%"===String(a.r).substr(-1)?"prgb":"rgb"):a.hasOwnProperty("h")&&a.hasOwnProperty("s")&&a.hasOwnProperty("v")?(a.s=s(a.s),a.v=s(a.v),b=h(a.h,a.s,a.v),e=!0,g="hsv"):a.hasOwnProperty("h")&&a.hasOwnProperty("s")&&a.hasOwnProperty("l")&&(a.s=s(a.s),a.l=s(a.l),b=f(a.h,a.s,a.l),e=!0,g="hsl"),a.hasOwnProperty("a")&&(c=a.a)),c=l(c),{ok:e,format:a.format||g,r:B(255,C(b.r,0)),g:B(255,C(b.g,0)),b:B(255,C(b.b,0)),a:c}}function d(a,b,c){return{r:255*m(a,255),g:255*m(b,255),b:255*m(c,255)}}function e(a,b,c){a=m(a,255),b=m(b,255),c=m(c,255);var d,e,f=C(a,b,c),g=B(a,b,c),h=(f+g)/2;if(f==g)d=e=0;else{var i=f-g;switch(e=h>.5?i/(2-f-g):i/(f+g),f){case a:d=(b-c)/i+(c>b?6:0);break;case b:d=(c-a)/i+2;break;case c:d=(a-b)/i+4}d/=6}return{h:d,s:e,l:h}}function f(a,b,c){function d(a,b,c){return 0>c&&(c+=1),c>1&&(c-=1),1/6>c?a+6*(b-a)*c:.5>c?b:2/3>c?a+(b-a)*(2/3-c)*6:a}var e,f,g;if(a=m(a,360),b=m(b,100),c=m(c,100),0===b)e=f=g=c;else{var h=.5>c?c*(1+b):c+b-c*b,i=2*c-h;e=d(i,h,a+1/3),f=d(i,h,a),g=d(i,h,a-1/3)}return{r:255*e,g:255*f,b:255*g}}function g(a,b,c){a=m(a,255),b=m(b,255),c=m(c,255);var d,e,f=C(a,b,c),g=B(a,b,c),h=f,i=f-g;if(e=0===f?0:i/f,f==g)d=0;else{switch(f){case a:d=(b-c)/i+(c>b?6:0);break;case b:d=(c-a)/i+2;break;case c:d=(a-b)/i+4}d/=6}return{h:d,s:e,v:h}}function h(a,b,c){a=6*m(a,360),b=m(b,100),c=m(c,100);var d=z.floor(a),e=a-d,f=c*(1-b),g=c*(1-e*b),h=c*(1-(1-e)*b),i=d%6,j=[c,g,f,f,h,c][i],k=[h,c,c,g,f,f][i],l=[f,f,h,c,c,g][i];return{r:255*j,g:255*k,b:255*l}}function i(a,b,c,d){var e=[r(A(a).toString(16)),r(A(b).toString(16)),r(A(c).toString(16))];return d&&e[0].charAt(0)==e[0].charAt(1)&&e[1].charAt(0)==e[1].charAt(1)&&e[2].charAt(0)==e[2].charAt(1)?e[0].charAt(0)+e[1].charAt(0)+e[2].charAt(0):e.join("")}function j(a,b,c,d){var e=[r(t(d)),r(A(a).toString(16)),r(A(b).toString(16)),r(A(c).toString(16))];return e.join("")}function k(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[a[c]]=c);return b}function l(a){return a=parseFloat(a),(isNaN(a)||0>a||a>1)&&(a=1),a}function m(a,b){p(a)&&(a="100%");var c=q(a);return a=B(b,C(0,parseFloat(a))),c&&(a=parseInt(a*b,10)/100),z.abs(a-b)<1e-6?1:a%b/parseFloat(b)}function n(a){return B(1,C(0,a))}function o(a){return parseInt(a,16)}function p(a){return"string"==typeof a&&-1!=a.indexOf(".")&&1===parseFloat(a)}function q(a){return"string"==typeof a&&-1!=a.indexOf("%")}function r(a){return 1==a.length?"0"+a:""+a}function s(a){return 1>=a&&(a=100*a+"%"),a}function t(a){return Math.round(255*parseFloat(a)).toString(16)}function u(a){return o(a)/255}function v(a){a=a.replace(w,"").replace(x,"").toLowerCase();var b=!1;if(E[a])a=E[a],b=!0;else if("transparent"==a)return{r:0,g:0,b:0,a:0,format:"name"};var c;return(c=G.rgb.exec(a))?{r:c[1],g:c[2],b:c[3]}:(c=G.rgba.exec(a))?{r:c[1],g:c[2],b:c[3],a:c[4]}:(c=G.hsl.exec(a))?{h:c[1],s:c[2],l:c[3]}:(c=G.hsla.exec(a))?{h:c[1],s:c[2],l:c[3],a:c[4]}:(c=G.hsv.exec(a))?{h:c[1],s:c[2],v:c[3]}:(c=G.hex8.exec(a))?{a:u(c[1]),r:o(c[2]),g:o(c[3]),b:o(c[4]),format:b?"name":"hex8"}:(c=G.hex6.exec(a))?{r:o(c[1]),g:o(c[2]),b:o(c[3]),format:b?"name":"hex"}:(c=G.hex3.exec(a))?{r:o(c[1]+""+c[1]),g:o(c[2]+""+c[2]),b:o(c[3]+""+c[3]),format:b?"name":"hex"}:!1}var w=/^[\s,#]+/,x=/\s+$/,y=0,z=Math,A=z.round,B=z.min,C=z.max,D=z.random;b.fromRatio=function(a,c){if("object"==typeof a){var d={};for(var e in a)a.hasOwnProperty(e)&&("a"===e?d[e]=a[e]:d[e]=s(a[e]));a=d}return b(a,c)},b.equals=function(a,c){return a&&c?b(a).toRgbString()==b(c).toRgbString():!1},b.random=function(){return b.fromRatio({r:D(),g:D(),b:D()})},b.desaturate=function(a,c){c=0===c?0:c||10;var d=b(a).toHsl();return d.s-=c/100,d.s=n(d.s),b(d)},b.saturate=function(a,c){c=0===c?0:c||10;var d=b(a).toHsl();return d.s+=c/100,d.s=n(d.s),b(d)},b.greyscale=function(a){return b.desaturate(a,100)},b.lighten=function(a,c){c=0===c?0:c||10;var d=b(a).toHsl();return d.l+=c/100,d.l=n(d.l),b(d)},b.darken=function(a,c){c=0===c?0:c||10;var d=b(a).toHsl();return d.l-=c/100,d.l=n(d.l),b(d)},b.complement=function(a){var c=b(a).toHsl();return c.h=(c.h+180)%360,b(c)},b.triad=function(a){var c=b(a).toHsl(),d=c.h;return[b(a),b({h:(d+120)%360,s:c.s,l:c.l}),b({h:(d+240)%360,s:c.s,l:c.l})]},b.tetrad=function(a){var c=b(a).toHsl(),d=c.h;return[b(a),b({h:(d+90)%360,s:c.s,l:c.l}),b({h:(d+180)%360,s:c.s,l:c.l}),b({h:(d+270)%360,s:c.s,l:c.l})]},b.splitcomplement=function(a){var c=b(a).toHsl(),d=c.h;return[b(a),b({h:(d+72)%360,s:c.s,l:c.l}),b({h:(d+216)%360,s:c.s,l:c.l})]},b.analogous=function(a,c,d){c=c||6,d=d||30;var e=b(a).toHsl(),f=360/d,g=[b(a)];for(e.h=(e.h-(f*c>>1)+720)%360;--c;)e.h=(e.h+f)%360,g.push(b(e));return g},b.monochromatic=function(a,c){c=c||6;for(var d=b(a).toHsv(),e=d.h,f=d.s,g=d.v,h=[],i=1/c;c--;)h.push(b({h:e,s:f,v:g})),g=(g+i)%1;return h},b.readability=function(a,c){var d=b(a).toRgb(),e=b(c).toRgb(),f=(299*d.r+587*d.g+114*d.b)/1e3,g=(299*e.r+587*e.g+114*e.b)/1e3,h=Math.max(d.r,e.r)-Math.min(d.r,e.r)+Math.max(d.g,e.g)-Math.min(d.g,e.g)+Math.max(d.b,e.b)-Math.min(d.b,e.b);return{brightness:Math.abs(f-g),color:h}},b.readable=function(a,c){var d=b.readability(a,c);return d.brightness>125&&d.color>500},b.mostReadable=function(a,c){for(var d=null,e=0,f=!1,g=0;g125&&h.color>500,j=3*(h.brightness/125)+h.color/500;(i&&!f||i&&f&&j>e||!i&&!f&&j>e)&&(f=i,e=j,d=b(c[g]))}return d};var E=b.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},F=b.hexNames=k(E),G=function(){var a="[-\\+]?\\d+%?",b="[-\\+]?\\d*\\.\\d+%?",c="(?:"+b+")|(?:"+a+")",d="[\\s|\\(]+("+c+")[,|\\s]+("+c+")[,|\\s]+("+c+")\\s*\\)?",e="[\\s|\\(]+("+c+")[,|\\s]+("+c+")[,|\\s]+("+c+")[,|\\s]+("+c+")\\s*\\)?";return{rgb:new RegExp("rgb"+d),rgba:new RegExp("rgba"+e),hsl:new RegExp("hsl"+d),hsla:new RegExp("hsla"+e),hsv:new RegExp("hsv"+d),hex3:/^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex8:/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();a.tinycolor=b}(),b(function(){b.fn.spectrum.load&&b.fn.spectrum.processNativeColorInputs()})}(window,jQuery);PKR\Je!!js/admin-scripts.jsnu[ jQuery( document ).ready(function( $ ) { // Meta boxes dependencies $('.shrk-input').on( 'change', function () { $('.op_depents_on').shrk_meta_dependencies(); }); $('.op_depents_on').shrk_meta_dependencies(); // Sortable page sections selector $( "#section-sortable1, #section-sortable2" ).sortable({ connectWith: ".connectedSortable", placeholder: "ui-state-highlight", forcePlaceholderSize: true, update: function () { sp_update_sortable(); } }).disableSelection(); // Bind the update event $( "#section-sortable1, #section-sortable2" ).on('sortupdate', function( event, ui ) { }); //Set disabled attr to fields $( 'input.of-input.disabled' ).attr( 'disabled', 'disabled' ); function sp_update_sortable() { var key_arr = []; $( '#section-sortable2' ).children().each( function () { var section_id = $(this).attr('id').split('-')[1]; key_arr.push( section_id ); }); $( '#' + $( '#section-sortable2' ).attr('rel') ).val( key_arr.join(',') ); } // Color picker if ( typeof( $.fn.wpColorPicker ) === 'function' ) { $('.of-color').wpColorPicker(); } // RGBA Color picker if ( typeof( $.fn.spectrum ) === 'function' ) { $('.of-color-alpha').spectrum({ showAlpha: true, showInput: true, allowEmpty: true, clickoutFiresChange: true, preferredFormat: 'rgb' }); } $('.sectionpicker .shrk-new-section-button').on('click', function (e) { e.preventDefault(); var posttitle = prompt("Enter a name to identify your new section"); if ( posttitle != null ) { var ajax_data = { action : 'shrk_new_section', _ajax_nonce: shrk.ajax.nonce, post_title : posttitle }; $('#sectionpicker .spinner').show(); $.post(ajaxurl, ajax_data, function(response) { if ( response.result == 'OK' ) { var li_html = '
  • ' + response.post_title + '
  • '; $( '#section-sortable2' ).append(li_html); sp_update_sortable(); } else { alert ( 'Error creating new section. Please try again' ); } $('#sectionpicker .spinner').hide(); }); } }); $('#sectionpicker').on('click', 'a.shrk-edit-new-section', function () { $(this).parent().parent().removeClass('newitem'); }); /** * Media Uploader * Dependencies : jquery, wp media uploader * Feature added by : Smartik - http://smartik.ws/ * Date : 05.28.2013 */ function optionsframework_add_file(event, selector) { var upload = jQuery(".uploaded-file"), frame; var $el = jQuery(this); event.preventDefault(); // If the media frame already exists, reopen it. if ( frame ) { frame.open(); return; } // Create the media frame. frame = wp.media({ // Set the title of the modal. title: $el.data('choose'), // Customize the submit button. button: { // Set the text of the button. text: $el.data('update'), // Tell the button not to close the modal, since we're // going to refresh the page when the image is selected. close: false } }); // When an image is selected, run a callback. frame.on( 'select', function() { // Grab the selected attachment. var attachment = frame.state().get('selection').first(); frame.close(); var input_el = selector.find('.upload'); if ( input_el.hasClass('allowed_only') ) { if ( !input_el.hasClass('allow_'+attachment.attributes.subtype) ) { var elem_classes = input_el.shrk_get_classes(); var allowed_types = []; for (var i=0; i < elem_classes.length; i++) { if ( elem_classes[i].split('_')[0] == 'allow' ) { allowed_types.push(elem_classes[i].split('_')[1]); } } alert ( 'Allowed filetypes for this field are: ' + allowed_types.join(', ') + '. You selected a file with filetype: '+ attachment.attributes.subtype + '. Please select another file.' ); return false; } } selector.find('.upload').val(attachment.attributes.id); if ( attachment.attributes.type == 'image' ) { selector.find('.screenshot').empty().hide().append('').slideDown('fast'); } else if ( attachment.attributes.type == 'video' ) { var video_attr = {}; video_attr['attachid'] = attachment.attributes.id; video_attr['width'] = attachment.attributes.width; video_attr['height'] = attachment.attributes.height; video_attr['subtype'] = attachment.attributes.subtype; jQuery('#section_video_attributes').val(JSON.stringify(video_attr)); var ajax_data = { action: 'get_video_shortcode', _ajax_nonce: shrk.ajax.nonce, attach_id: attachment.attributes.id }; jQuery.post(ajaxurl, ajax_data, function(response) { selector.find('.video_preview').empty().hide().append(response).slideDown('fast'); }); } selector.find('.media_upload_button').unbind(); selector.find('.remove-image').removeClass('hidden');//show "Remove" button selector.find('.of-background-properties').slideDown(); optionsframework_file_bindings(); }); // Finally, open the modal. frame.open(); } function optionsframework_remove_file(selector) { selector.find('.remove-image').addClass('hidden');//hide "Remove" button selector.find('.upload').val(''); selector.find('.of-background-properties').hide(); selector.find('.screenshot').slideUp(); selector.find('.video_preview').slideUp(); selector.find('.remove-file').unbind(); // We don't display the upload button if .upload-notice is present // This means the user doesn't have the WordPress 3.5 Media Library Support if ( jQuery('.op-upload-wrap .upload-notice').length > 0 ) { jQuery('.media_upload_button').remove(); } optionsframework_file_bindings(); } function optionsframework_file_bindings() { jQuery('.remove-image, .remove-file').on('click', function() { optionsframework_remove_file( jQuery(this).parents('.op-upload-wrap, .section-upload, .section-media, .slide_body') ); }); jQuery('.media_upload_button').unbind('click').click( function( event ) { optionsframework_add_file(event, jQuery(this).parents('.op-upload-wrap, .section-upload, .section-media, .slide_body')); }); } optionsframework_file_bindings(); $('.range-input-container .range_value').on('change', function () { $(this).next('.range_preview').val( $(this).val() ); }); // Temp fix. VC params classes are ignored. // TODO remove when VC is fixed jQuery('#wpwrap').on('vcPanel.shown', '.vc_ui-panel', function () { jQuery('.vc_shortcode-param').each( function() { jQuery(this).find('.edit_form_line').children().addClass( jQuery(this).data('param_settings').class ); }); }); }); (function($) { $.fn.shrk_get_classes = function() { classes = []; $($(this).attr('class').split(' ')).each(function() { if (this !== '') { classes.push(this); } }); return classes; }; })( jQuery ); (function($) { $.fn.shrk_meta_dependencies = function() { $(this).each( function() { deps = []; deps = ( $(this).attr('data-depend').split('|') ); thisVisible = false; for (var i = deps.length - 1; i >= 0; i--) { deps_elem = deps[i].split(':')[0]; deps_value = deps[i].split(':')[1]; if ( $('#'+deps_elem).val() == deps_value ) { thisVisible = true; break; } if ( $('input[name='+deps_elem+']').attr('type') == 'radio' ) { if ( $('input[name='+deps_elem+']:checked').val() == deps_value ) { thisVisible = true; break; } } } if ( thisVisible === true ) { $(this).fadeIn(); } else { $(this).fadeOut(); } }); return this; }; })( jQuery ); shrk_getKeyByValue = function( obj, value ) { for( var prop in obj ) { if( obj.hasOwnProperty( prop ) ) { if( obj[ prop ] === value ) return prop; } } } PKR\S admin.phpnu[id; // Styles wp_enqueue_style( 'font-awesome', SHRK_FONTS_DIR_URL . '/fontawesome/css/font-awesome.min.css' ); wp_enqueue_style( 'shrk_wp_admin_plugin_css', SHRK_ADMIN_CSS_URI . '/admin-style.css' ); // Scripts wp_enqueue_script( 'shrk-admin-scripts.js', SHRK_ADMIN_JS_URI . '/admin-scripts.js', array( 'jquery', 'jquery-ui-sortable' ) ); // Spectrum color-picker (redux handle to avoid double loading) wp_register_script( 'redux-spectrum-js', SHRK_ADMIN_JS_URI . '/spectrum/redux-spectrum.min.js', array( 'jquery' ), '1.3.3', true ); wp_register_style( 'redux-spectrum-css', SHRK_ADMIN_CSS_URI . '/spectrum/redux-spectrum.min.css', array(), '1.3.3', 'all' ); } add_action( 'admin_enqueue_scripts', 'shrk_load_admin_scripts' ); /** * Run at theme activation * setup extra options */ function shrk_setup_theme_extra() { global $shrk_theme_info; if ( get_option( 'shrk_theme_activated_once', 'noname' ) != $shrk_theme_info['Name'] ) { //Run only on 1st theme activation // If attachments and products are found if ( count( get_posts( array( 'post_type' => 'attachment' ) ) ) > 0 && count( get_posts( array( 'post_type' => 'product' ) ) ) > 0 ) { // Add notice about regenerating thumbnails add_action( 'admin_notices', 'shrk_admin_notices_regenerate_thumbnails' ); } do_action( 'shrk_theme_first_install' ); // set flag for run on 1st activation update_option( 'shrk_theme_activated_once', $shrk_theme_info['Name'] ); } else { // Run on every theme activation } } add_action( 'after_switch_theme', 'shrk_setup_theme_extra', 12 ); function shrk_admin_notices_regenerate_thumbnails() { ?>

    stylesheet ) ) { if ( isset( $_GET['activated'] ) ) { unset( $_GET['activated'] ); } // Switch back to previous theme. switch_theme( $oldtheme->stylesheet ); return false; } } } add_action( 'after_switch_theme', 'shrk_check_php_version', 10, 2 ); /** * Display custom admin notice * @return none */ function shrk_notice_wrong_php_version() { ?>

    PKR\ݯ6LLimages/product-style-a.pngnu[PNG  IHDR6IDATx݅n~e̼233A0֢u;G~6$izH&܅ppp~o}~o'P_r*v{nV>{;+˽f5~ )(Ç")7Vz;ܳ=*Ͻ ptS w w %%%%%%*%%%%% 3IRոRu_L*Nw..%%%$%%%%%% %%%%%% %%%%%%$%%%%%%$%%%%%C'%%%%%ur^Z~=rdt34E1{,<Z7۸~]W3 Lv7;וL{ncsU~xr;̬&۹G%_{<86q=Mqwqwqwܣ(>:eqeѥ{O%y{[yL.lqR>}Ù3;U;'E϶s"܇Kw+rszU fqǽݎs[n[f /bd1ZVo`q,}ra+-\o&Vp}כof}s{ƝSq:fk$-\]y~>bq Yphǹóyvvew{V՞_}?.ټZ_kj]Wg ܫݓ$y5#J;㾺uo;'k4ܓosr^˷p\A羼y5 y;v٥U'χp9$ "V;'[ƫ%qOtxz oK|꾙cy}>Bh^`eߗo36;Z{j98-H<nx㞿Q<^$(wܳt:칓-=,;+{zVo;+{O wܯVsp;_쁧rqje?+;{˝p湇_ })=I=^N~$7a6ʏ"wqwqwkF][}p wqwqwqwqwqwqwqwqwq}veJkt^O^Fg7\Jdq}*ri- jgo&4@KKKKKJKKKKKK w܅;½pN'2܅{a& w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w cG+R@EGQ7T96¼`Cy@ssvqn?s~\朙dw/QͶL EGq*.BZs>{Dܻ$>x9۾<'$@Rwm/]sS`-0MLe$qh&t*5! 0PUK]p6'U=i+ϓrc 锗x¶sW,4 \Zt FUc n{=vx@5bĨ<9Iu+4F ƨ*nhb8xxw/c0W1jD#퀺,9aTi9(|C^@c؜DuƯ$p|ƿ#fsiM'|lb.@`Q=(U몹c  I/O^fe sc};wv /2n?q\A7޽`kN;r|zϡM+=V6}z4}mMݜ^9ɚCo/xc?!w}?>:Ush iۻG>M[=:?vE]n滆>8`-;~w> ~^lv%Ǡ;r ̟Գ5/-~n<٢~XyW_Sƽ4⎿V,C|PiFM_϶lX+yN_̼EQD!T#N~xYAwj&ndŅ:[S>dGjmO5VE=n4&=~GW>u&H6Kd#W/35km?;%/ ޝ|C4b7[3t^0Q#A4 >e'PRwogR눛{=nB$~wYKŽBZՃ]>j6~<{}eڐ]brzT`.q)TZ}:Ƕn-$l׽-W:9uܓ_\lsϹ];ׅ[6ˮ{\߾{[yxSkG^rжiKztݾJnGg ]SLJ?ÈF6b(tRD2h5܁3P P|50Gc.U4@1G,wP fx(ah g >"`JhZHBt!fdjPDDb>3уC-%Tͣe8M>-M}bя?1ttmӛ?oI\c~A )[ sш@,|~믾P({3ʫpi Ji4J&;Ow7 d!9QUa(e<;zW =w饗/1Ws/ܯo!? tCE=+N}WfpB!{n㞽d\3O/qPrDx_}f/\/ $=^?m[>80H=#gXU!bۣy顂h\Z*yݤYsW-m\:gڎbC1u 5>/Ou[ Ǯ]9b٢͙[3^ 9vʕoo2kʿ5L9Sm߮G7q7f?&ʤWaɲ?¥ '7YMY4q+C6TYUA ( |y76?7+:P[~CϟĨWHb*F誹geSD^:_+׻͚*͞Iݦ ֬ڟ4uI7IͫsaZ6|eks^~ޏ=?֦7v'V߼8ޜ~OT}{ F4E8 ArXw&m?QH W͟S;oՁ }Gap]4w1:iH/4Mӛ _o<\ZGحnO͘kOz]"P"gV!'8og`> ?Z6ƶg~w݉AO:kߏ.Z|nv$\&_/'M=7of2`n/ 1iS?|Ǣ3ƴiK%˯1ן?|™W1bύ>US+\ĶuÁW:)h [{-p<2n>3|%}iͬ[a\}h3W4&va6l.e8cW>mjB+m~h+,|ѰiGv?~J |p3$q5#^uܩ <Kyq#_y!\ 'Csh r #w!!R ݀ "&<' 48+Qe"TB9BцBĒ~02@̪ &=b͊F0=uQ,!nw0.;!'R B@ `'TC"]J %4Cz@PJ A Q rt7I;pyΠ2UW k f4_=ϿsNSD3]誹;P"8$åR1 h`@0QRʂ@DSȡgfx@B @̪2co5͜:mNska// sjg/^y#EA݃5搢9⑀((q)`(  D(  5r#L0 tRά*UE!D}0"(5@AUUu u@(rMUT C%F1F"S_T0$Iࣂa FU=Sc`5Q1Jb҅7UC4@A G$30 &\$1YFE,5S1I x84ErNHqX$pJ@@ !QU!;5]! Abn@\ L :פM0hlڵs4 !Ёh Ѡ"`*ۚ}Nۃ;)P$\AvSowi&s7I?`E&Q(,bT*ɥb\1|78@Wmr6 9xMmn &|}X6Ynaoށ=Ir ׀НAiLALEV07?443uWy -:檳$p:+̓ B{c][G{Co_<2/VP !}cy(?Wj[AXLp5֪і\i(Pq-<)$%['CE>Q K'WQq|Qi,%(P*ţ[z:>3q7C:^Z@Y.O3cvkCea=<7q_7;'#/ESp!N@.H< LDm `:8Ptq<y{9oœj}aUin:*u6`1S+;̫J/- ϰ*imtOp?>wf]X?tZoW7q~ADo/T벂N\A܂0 v,*QfzQ2W(TeTar(ۇMxUyI}cXot#-K}ʍF)JjU(Pa_M/;8`nnA @ @+G;ĂV'.!T{qDm rO!-!\?r5wf~y;s}37'}#8ҽ-3ct{փܗq)PϹ'BP3_'BP{.ySr݆ r#w;rA w;׹.8IENDB`PKR\``images/woo-100x100.pngnu[PNG  IHDRddpTtEXtSoftwareAdobe ImageReadyqe<IDATx\Mh]EWB%4vQ&TM\h? b+,.Mq6q ]ĝgMa^J &r;a3wf}K^=ߜ#8P8B$$$$$ !$ !$ !$ !$8HKc>ޠ aKM}|yuq{q#y1KaA2B4C>MV9dd$:^hν8H~#f\{j]Ir/GrGk・GOdbSv~">ީiNg kR?ޱu| C)#O3ziEw|)mc;݁r3廰H~㚰'wI{̛ ɫ|2ф}̭:\bOěGI4 2~fE !2!rN.XMm7!iP[E zeу&.NFԭR,&|!GV"$%a0 FϠ=#322~BȰqF ƚC/~* $ 1!% [&a,>:g [L=}YDJZUUٱbBPu*&4T/n9=^ԡJ#޸eJFc$o(^ CIZ$[qO?<+ID,%p;WA$ȁLuQPmTZ_/@$o*(,ZlC:[o 0'IHC|"E"61!#X\dN*,IJ!eMD Y%\lr]zrf)r_zQζi/P1+4yOIIܝ!F!$ η@jՔyAJ['@ꅒ|C'*lRp,$s1!84$~$=ނWTV-m}w̐.0d$\oCjt(CP>?XcY=$$$ !$ !$ !$ !$ !$ ! !! 9Ox?fjVIENDB`PKR\*L}((images/ion-bag.pngnu[PNG  IHDR<<N%tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp UIDATx!l@hILrC e %UPHQVP4YAUR d,(P@" L5r[5e]O^:~wɹb!4K/~%v{Lnb77%U*9qK}ǚϼ ,z!ĢyRMyz@OI$f5!ϮgbE볥0yH5DѨ{D͉oUNJ0I.Hؤj }>z&I;zSr0䈰FS/Ggջ}g4z3R6_L">Q5րY"ˎV G^jv׏Z,hec@;}v;8z z*H;69 AQ"=BLWZI^Ӫr gCfmzQ03B:.鿶]?hV.+`NS'@9A理QVw?KP gō'==<@w{.ȯ6ܠў7f~dz7~Zu`.wK 2L@tCa{I3D0^ܞ(Cro:JI67hi'*Jh]/o;?Ft'z(ϮqNfEx5"AvkMo\hzܩhN`6xt{p\ O5Cb@SzN4@6%@q )\l;4ORK3 ( \3ׄE*) BYi?Y~} ۷<$Ō/ZAd"BlS)8Eٕ{t >sBQV`>Ɂ@y"S*"7/^q?t"!U%-ywnP/:y~C50LDv}!:r8|Ď N0I)34qgaWꞈ0 Fl4(y%-J4DRo %HjgI<.O:d:JzTp\ޟ #(8ZIkH|FJ0[㣣uK;{Eo2A*cL:fxAuy):s 3o%-"J Ưb {K"%P^E g~/B+fV1ʯPC yGɍ!try`!Ie b 1Rl1`zh9 Kks5z[r-/i-IZPA%uk$P8A“uӸlA  e fԅ*2D w{Ri. fZTӫʴ{,H_$֍2%jGRY cmf.v%fpiw~>5V Pm# A:3Z0DEc~#zgWR=w%q% ~| ,j4*8Ώih1;1)ji<rƆoGh  t:B@:B@~"t`x}6===Y˯ߺ֞6tDfZ{|Yѽ?u XU&rwwt nVhbbB&N-)^?tuU't ȡ:ڌsWuBB't{zzddd$ȡ^(FGGT*FyQmcۛc" VwŢ!ʮmoo3):288h[%3333f5]c3xܶB;ⅅg}٬83;;k['Iqh3299iSVEGOoY ^45;:z?K7Bc2[[[~``@rLOO:@ʊ @蛛{':@U*݅7C]o?;;s;~6$ F_5Ȧy{3lB}mmud2ڛg|:@zwvv KsHFBBlh嫩\|8I{?S{GW?<<t+>铓8{?w9)Dl  tt5#UY\\lFs9tЇ،:@*M, β,ad *wwiww7sLt⋴K_ x(V]Φ* sl<.@(jZ8m%mmm5?22?X9K9|k]=zٳg?6ϟOQ\.0#K71=jtjל/7GB}6}.3.wۆ c4==JH;;; eY %kt:K.sҙ3gN~/_t tIK]<]@@$%.u>%bh&}6.5Ы蠏Ϯyt@JCGÓW$Akȣ}W%A_l^@}e}-7^@Vo=@k\^JF()>9.q:oÉ.gkgV|G8c{_^b7%:1|lf9]ןӑ~a^}qg˄.={-nJΧ/ƛ?JOBѧWseA蠷}¯)]y0QQ\:٣,(@TW7vD}>AzѼ|v ,x|~,|H3͏ı}g>BtU:w>fvk"У8szz̋c챫TNtU"zwسћK[moݜS|,蠃~uynelN/tzz:1( ;{Ћ wc^޼yStz=lt-ltzn<>4AuyX` MtO./Bh@[+8tAܺ4Ajbh2wVttzŧрnpA tл>At: tA=θ_M&tA蠃@|@t:蠃.;蠃.At: *:蠃.Ar4pt@]K4猬4t5YtwsαCWHFf@I1qdځ+;lw|/]R]@*@TI@$Х$%. t@޼y~w%%.%. t. tI6H اCB[̽@@t@t': : : :DDDDEt@t@t@t=azѡ': : : :<~ A0qwiBNjcBq{ }3]׽KJ)'}&w}V9[kMJyB3zKA yڣofRm>Z*)B> 4 RrxVZZ*-EZ#=uB+Rv 777(~eeEUTTH``TWWaJrihh`N YYY(Uf ~~~TLNN2H__DFFJ\\}}}1a%$$Hww7-tZ>9{l Z988 xCCCP\؈v %$zˁ핲2b#a9!NMM}IJJI}}w`gge/jnO &=::Tմ49;;#@===RSSLLLgIIIoˤP\\u.m*zWXX(KKK999Y"""1_///9!?99a4 U<77'a p -_6a t@5.Niû$&&a$ۓXUB1'8sC򒦦&z8)x5OOON1·0'x{{#IíJn/E75J:pxX苋 (==@pegg*,`CMEguضR^a<`O777}]AFF@qzŀn@_6mz}0ɨ㟞T1@HHs.kkk ',sQ߯P@QEQsȃ$ƽ~˟^n(6ݙi7g~m+Әڶqk%`{v+L}~֝!{-:n-u^WtUu+^T鷤_[LK&j%<[O_ɃgzvSGOeQVf=ӯYsfgh2 d M=J1mjw=eؙxoB2}@=^EEgdޱ&7}?>t>#[*]̫2{W|6l_Ƥ/ +s_MGε[o5Z59dQgيYm+Q0rJb;Jҩ+׵ ϼmW\.լ+:zPc1z3I8%w,Fה9W0K&_~nU`MKw<vWJn[p8XQlǢ1*c_D_ooo̪T 'ˬ#Lx洅@jS;7Fc2c kW6ח{ȫ3'4FF&Z3+!Ji7טնcfϛ=Z&oYZcm?N-2h>j Eƽq%0G1[:T{-k_}t6?D?5FqwLh2"Uژ"l4qoli%`*S{'"-En+p=jcA8rС2b@B%oAv4@[B~6~랞l߿( Hj;24phCFL*hge;:cE'}5pE;ϑϣu{DLAn"߶֧'R}T%za䄀4@lYTbM(17=T)yVyA`~ ~"~ bJ"rtzD`hܜ_7MT*b!JNB m& l<"Yü]Gވn9&)&vuyQ!avJkm:!兀+Je.Dy}=wހ:B:: t@BB: t@ &w*\IENDB`PKR\Ť#)U)Uimages/redux_head_bg.jpgnu[JFIF,,       뗥NPx'P}E8a=~~;,ވ7BL@uNAztGtQ3_G\;'ƳsdD|jq=,F>| 3m؆elYrWP\dGFϫXrS:y640Lu?kIF>~ӛKZ| >W]]Z9gYs 1_R ubm_gyqrlW8دk7ⱘ-zBǗeCkW2ؿLzIS7b{9֩{F s^]A-x*^eZ^!juQyNw ⧳3-$S fri;srq |!1:z2'WGҺǓyDmmjrV9m R4!~B~O6URl/YsM~>%l&ۙ6ax_GU2al 7#JԽ~ v,qYԲJ^indΔl]zߝ/C\uC= fQIx[I ^jlӗW:&#l ț0;tcgfGl ?iQ tzu x('`(e3Y~P],!Gƫt Ki^3Hl99{gwx YfY "bsuqͽR\mI/O3C>svU27=*6@2NWgo^̄%6Nj?(aTƥIaw=¬NZewce:y=86zyͽ&c@y=9*7\{a@sө¬:2-+RšbG;SṄH6=Mz!JVni`e6Šj/:( ꌳ%Wr:c"6։|6 irTn~CPK.{y+肝 t9lHòg\t=[;[Q:WUԄYm fNq16,:<2\ VL=yT\[ ك/!:M܋8Cֿ֠^ܛx86uwwb"^gvpHח(ad$i4!T$6ke9p̭[rb^yE}FLjݼ}IqҾIxʻi NmV~sZדcxv$ J]sa8Z.Lj4:Ҷ3+(4NH1$KjK:;fLNL{xZϠ !۩46bXgI.m>4 aC 5ō3>DQSn1vW4>–7H1y= %J1݋:HkZ58RB^fmʻm!^c'm]윶FpQMٰ%mapqCn'nAa2IIa`" aŌ(p-w:o[N75|(WQ^IBn,sUj>MB!NhoR:/eͅsN'#S_Sk^a8fA)Ù^%>kcᒪTVKU(3KD3 ٞV1' $:SDЛL U6 8M1-Tǐ%?=hcA7d~sJ8 >+G!`>U(HwTQl|O趿GT:]֖&uCx[T$jZQ"*eVjQ)Ȅp%R[?Sa5;/^9m~|u' wnNcZ$7.٪8tVj;uDIAN2w G %K]XsLϲ墥z p&eWO#H MJ-Qh4\1 "oE1!9J6 z&L&u#ToM6Kc /"U*ʕ yO©Qh E+0xOTwE1!DqYB|>MN6.b!?H?=4ۓmUܓ$, TRy! c`E5lx ?*X#Υ e_USx=/~EӸnV=UoP*<qkI$] ٦p}ͅ?vKQ Rޣ0LeTY2c=oP}"d͡]ԡ|*])i̽ɹ GcLΚ't0N7P hͪq(Spr9T i nrM עLxh]**\SFhۢ GD)Jn!>/gDj0Z8Qō$e4tNSۅِniH*7sIـPkH;:'-֡z=0oK[/6^pDS9mmW@8#Z̮NHec3e_?L"rM"sBHkdÂyb ;5G 1NcSDQ=AJ^V<Ӛn&'y{D kM9* TJ5sSu9ex tR`C8'㉰8!ሲؼ:'D 'qNY=A䩷@;6l̢c6gwU8DZew1;m4vMU6{d{-(#HX*\>{[D~PN ٮcިgO)?jBB/i%JJ'N%6µLU@E{PVڞn鎫NPNA(xBR~NiZjA;h/a)iSУA HEO_e.Ut1ԧM8L^yU'DX. ZMkr^%xTPJCD s ڌ"tQg9pB_UP H%<$AoS#g5kIxNFsuŽ{A;2PZXPc4snqYdmgUg%7BЩ;nib,|'fXloU0QDBNS+gT=WtjW#E4<-C?T*!LSF!xZU+b4 1hL(pt]25q$0#U9颒BhqA j9))/&D"a6D.P$H*h;I󊩇! Ja39Jp RZY)لVZqr{B3~Q0yA;6CTZ@U8i;;!AXsNbR4,lLfvNUxtefEu[ilw LgC5OԦ7oRѪX#7<SiԖ}Q_v!<aF'{ zNÒ7ӽ0BjqܝT(S Bfl#98#3# 1֟`ҩyeڅD근+:NX\&F9sMk@LwBsÇuD=lMR\~#l9Ƈ:U,mޚswAnӓzk zoD=3B3EWz׈K<W-熸+hlU'O98;4LYOJDyS58 M{Z5B*:&xb8E]yS=&NpjH^5Tu:h@fG5Uļ= q32eW'uG2]0\3MܝOt9 1Lvc⛚cQk?KOo{)p҇zhHN&YZ7[gz[7[;52W=x g6 J RRSa*T B~hdTL)LU U{oRu2NJmg~U/M-7vhɝPcL'2l7. om?ToG%O"#jov#T<4:D,y='\mণ5c >:Fva`5(%:@3[iszjFj  bїtֿ@1z {9d{,nfpMs sN>Pw"G5nv{G1?*qF4Y&l9`k1ť*5 %T@g4ꜵG=bZrC+GЦԪ#Kݛ vkaef=`BS=OXw*=$> S2En{kF5F4c. -o `qFWHLT8r*b77)E7˄Is?U=\0rtb<PoDsAik+FUT`DׇsLrwK(DžWa$eASJEwA N!|5|ME3csn[;52]Uq7NJ/c~ꡚrzAkaN[1C=-,uU8ݼ\gPzf>ʋ˩W[7׿*@M hwZcL©96kG/Կ?ܿ?RK#+nc*1vȬ4T 9EW xkr-e@9 ^#):x\?}P ~CW_8p(.ti!(lÚW h4ZU&IԧJ-9H !yw1N8 c&D#LB+^ׯ:,5x`p #02^+W1@yTi/ F4QnL6Qܢ%+%ETq:" Å;?>*x2>waB8(&;&T)| !A8&ݛJyU3[ OS^ 뽑{7Y"fS clQ!U2FJ1XZ()*pFih*eU>PlVmI8sEW1uxy)7QkaT3ߧ;Bt*wKHEWjrur!W*|}kڣ)# pUyr.&͘IFAǢJ,g|nӋe6 A1SRRwsHU^̴{+< WgH(K!SWr*p N6qF n4c2Z#i8hT)QUl漪.95|6` W.4c a* ͛S9m3/wTT§9P"!#v  9A d]";s:-syhFc;)MAU fzݑm:Y'gLy¯zylR$+G^+׊k5}sRm#W4s)3e/sp(]w r=ʣ$#3-!da+m@(4TF׊_?y^RO0)/YP8~QSXÇu vACuOuN0 TZ"S2>Hxȩ'4 fҜ}<₀uPRwmmv U:"75pU8ʜe ݜ_uQ6S2rn.VTcMsB#Iq7"z亣mIn(UpdG~eћz'*&N87X1p*H# wN^mʙSNcQnpC$s~TuXŰ%QY0LnS ȝoՆhB%hҌ>Z&3gR~)ynm7̟[MIuEӸD腁6S(i?I)GstS&ߟ*'h|(܀ڒeUL׵|ي:4cp'J66(!1AQaq 0?~E+ȿT.ێSO9}f,(w=юf)㲢$D-NZԦrE "j9UM g|@|[EO0lCu6nCY C/>Q!Pc7Elf.SԭM`X#v  2a`,Ϭ]ZR䞤;Gx}˾wj&A,ʯY{Vw*w[2#G,שU+ڪAC;BD ޓ3=pג\Y];;{am&NѼXwTX>X 9>zmЗtszt/Vwg|AH<_Z:%pcO?Ly}f XI̷>ZZl/RܹZbPEa v|s iHG)ť  }+*L(ťuf牚1mym?7}jq? @^yfqfoQ^y]8@P{L8B5l{E5b*K3J E. 'Abv4& oyXi1Gá; Eh%>TjwC.`P@)ŮסDJCo&2k3 ?Q (C e3Ph OxToy qgm{,|jU j0kwn*+,99L5 :3} &j'͉c9]QlhS*m;T1T vͳc.;+!)*jl=a[oCxH2L|JXns %SkјשgYԠ~qF.> 4/0V>":Җ-Ǥ,b!0ŠՏ6`&e^j1w(+qeua-P5p#⹜";,jqe24*lQYZ߇'v@cF)Yk6z4qLQS2呇JTvJ[1Y.Լ~MP;G FW8^2T A3!uj5op\$`<j̸-\Y)+n"!uyT2;0ccԀ9׊˖\k]ZzӾmz\,e2ԋ>7_gW|M:ŋ律lbY8AUW+񾬻̠Q+_7(qp֞aLdaB;Uƶ'03Zن|zJ9ooiDM=-טo2}e~"|Q&'b:X' {7aߤ1/ĸF?R^EZ$_1$ɫQ@#&L06 1] 7i=`ѫԲTA+hp=Fn<@KOjQQk}#"F(ѺMc()uh-SC GSOD"^%u\7Kel*巈w:<twDՁ]|34t8- eއ_2 =e䩂6u=u/0Irz[hi툽kPY.`xD|L1,Xx5n8{)X6;aVveR9e)[LqT_guU&c}_/Um/JǥXBJ#[^Vظ"lN`/ " ݵ ^pu^*9H+ބ'Rꞓ`fBEq+j+KlA 1kZ J- HQX-鸢(~Sd D:,喢\H S  +  %]g58;3V/ym90b}z?tDaVn"n0Zm;eDcB4._r!eZ#`wf` =uy}Og_U8e%Hw Q1B]Mac]lrh% b3{Z]G3VǝT2Ioܸ{'L3?uL-eF:~??V=poB\dyhY@GTJ)d^%=nUDDz)O@fp˔)M| E\jԔh \>""6tiVxT z%y1>BMڕ\T-N!ϬZ2PDug1k\,1jx̵!~&8X~-I*- RA/WihE򃓗Y.n 5rd 1F\AOm:&U |(o>F}ְ zvx*Xk]2VVN3;MDzt: ?j0ߤ$FbAtW6}%}]{^-`CJbЙf`SXULA^Ti{^+DxP~s db#|Rq!\Vuz9RWm:mz:!39K9j 2^׆Jj* x ۛ3r.Ёq%Ya2p֘1do캟(jg0#)N⢐ЌH9!ua:E4Rw*[MTDV=e8j& \N^Ғכ|F˲׀cGQfZ\ fci~z`C jV<u bշjuwqg|KApD4+)W ՗LC>FIQvGAB 8P>bXٗ{olx0iqAbAH.s/ Eca8} 3ۻ`\U|WOz}CpB<ʕ4&feko3<7@rWfSϞLzE%]=f *_}jcb#=XkYGzCqE3jv(sєW4q6KWs|KSaEZ7bscY^y;JUp.о\S&F~wF ڝ?A?B=$lY}j]}.\z"/061H4 ˖!\܉ĂA*%^Z-gڝ/m#HxΓ Ԋ%.iX?\E9hӀ\G2JGX \ -Ҋʆ^ ffXbD"[/c8yOwnyx;< ޘHv(nI~dˊ@as=t&B[3ޅ{ Aƫ`/k.~,:|D܇@c301\SyW-V٫-T] }Sefy<q>.?/A;E-1/ZLV*GaBBSd{:s9:{R\忉ۿf9w ,NL=Aʇ+4=_u&NJw}CNa[}Y*q'Dj0WJxfBC2 SiX̚~p-P{q:LC fw]PT%rt2g pTme,Opܰ(gĠH<0-6iumEX: ǟHF1OxW~H4V+]dT&6 7: ۴v^o ݄!UU.EqBhia* ZA>&y_H;=<ˣ..vەxZĽ4hE9{)RBʔ߰T7vV#ľ:ꃆ_l੝]:)bi&m@F9j+e\ s:^r1 [Vlz*V! OacSwA #-f>nb= )EFqk6ю$q{gyY f:聁S/w0ϩq$vbZ^%10 c?a)^zUZxTB~a9tX +؈Q_.:ވ xVsԪ@da;1X`%L0bQs11Sk|@ 9vak,ʆxVbieQ vA`2rՕo~ )A8@Qz\@+Y-IOm/X[MxbDt=F|LDUE6rwiMmyqez@Wc `xM=!t;\yeVQG| VF4CD_ܩ\}u#í9UG6;ߙIste>3P?}3D?T6j+%{" ]*G`ZǫyTW_5U$9^W5 lXW2"]`}V3^_P޺;dOQ?өTHإrL{!݊pည8fAr~ O39Q?P"5AVs~5z|Nͻi5D`i \J%e dtLTN1j)Jĥ|)=ƣ.-|%r,qD p0 [T%׬1U/z\A?E|1/*QwUW!kS>`QfUAys8YEQڌU)w A8eEڞHTHoK.Ǵwgrop;&# =ӣ)yPϼkPS߳7b.H;G eΈ;s\}[ jp14ҽc$f:8!۫16HGT/ q0Wy^7+^x'l zs,)4=Kh8DUl2r;xf`8gӖ:WOŢkE1iԶLN,p[:lMVX˸3l P(zEi`AZ7R[rϷS>f[,}:/cG#㥻!þuz:tV3у:}'K۴DטC+eqP[3qsLiDƳUX6,n ]04c"oQP-ypxWH9A_s -Ӧ`Zynp31,7ب.V٨Da\oRL|ƲwTbu)eQ+M*իޤ_bJOL@oRf&K*rf`<9^}r_4]s|vjt"[Q21l7kׇN.S UѴ{iV.=-KAn)VA5OZ8'q-wю0*]F;p}ǴGuY]W0 gkaԌLPn:~-I VsP q$\ƦpZ9 s;Ġ3 ٷA, }.7%]r@ )VPh cS.;|W7/1`SFOr2AcX!̽^JľfDC]6PWѣ2{U5ړ!fdCK7?]^W *JJ9o̹[r4csɂ]oa7Yfljm037n:]eq= >|l=1*Zq7Nu.+;~[)9MyA%=T8V%4'IY};6Nft  0@P1`A!?%G϶>yGe[a55j~,5Xr[Ұ|8cyz1Z;Z_T㼾DwtpFs2ŗaO4ԴȫS3F'1S 0]F6443)6_(鶗KO_ɄYx9>4u(v? %Vm-0hC(i8U贵-VEt^$0h`G-aa0#4~eܝzܞ&,(NK/C'i se~G'VڜSFasa =(aČ#Ʉ6s$ 0@A1P!`2Q?5:}r5?UNS槁G͡Se?\h2pu^_{Ul FY#0i{D0780QĎXK_Q_.KdyO/_?=ƧfGtKv8Z?=S~h85{^sx=}ii~Sy' kilo/7q< g4VlBRx\ L,(G{ ͆m-19Ro/ -##Ƀ-l͇O& FXvaPKR\&qimages/ion-ios-cart-outline.pngnu[PNG  IHDR<<N%tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp rt(2IDATx١0j\U 93 00;5!6jv!X 5t1!fi4[_>~ɗ~P Ѐ4 h@ЀqG~ܐz_2~n.V}ѩpG>=ʈia6IWS5z0]_&4QK3QJ/P(WBH3N#3O z^!UA#u=o]#K!J:T2A{gвl}wm&ڽ|. woRяnsK i"fwoLЊlwokiDzt Mft⨴pp;wpeٓ"jvlr5#d+pe۩bgӅ;RǶp;ܳ3s^bG;ixmF;~Pmpޯfiy.6Θ|)y~ZvBUw=Ul{.u\q\>U{4pWu>ݺx{?<wIv3s vnSѲq;EzgxLh^"at]LѧLXB#f+-nǹ}"S5'fzgihp;sxN i;|z?w.wpG /K[V@rYt;>+@X7w]l۹z){~Vq'wôD?y3;^!twu_ L/#^Q X>B0wyRy?D p<~#qnd4-˖^k/_ʶü}dGj9 ;.OvztSTOp<}=wyhw]Uwi|wNpdrseLqOOv7wwqVjwp;k/p;wp;wp;wp;wp{֏wE3N~\r}#|+.Kfw8Q7ٻDu:W\D7LE3"W˶{vH@!Pwfލ*A w;A w;ȝr?InLrA;@ w;NA w;rN w;rS'w;rܩ;rArA wrA w; r$7&e.b a0%ULUhOz~9.˲ǝv9335Mwdq *8 M@x#{Dl tn)1Ʒܧq|ǿ{573dnrHnvQs c*"F] &0 \u {-5-Ǡy[ `#1@a miV6ݬtp5aH+g` S,ci0I25e8(pƀhs$ $JUèDt#6+ٍ 9)V)Te{AC[` i tE7/po0hhsWэiQT!q uO*~>s gQ{ v4:R $\DϺRصڶ5Ol8mǶm۶m۶mTXk{7y*2ܽ|ˈADډ#$Z@D`ϔ^ȜwԌ sSP&Mk)"yٹ ,X4plj3iikVoi֝wھxR2W%u0ޛ<鉽v0\ْ= MзG!ro5;7nB{Ga˶u׬I/?]^Ѱ0c9im2sC.mUHdK=:M曌j4fOY "!=ͽP DWW*R|J%SX/Jo>˧.]}뚔qGX9Kʖt#ڊiJ'ԭ]"4,]S^A7=kj7fʞ#;֬>v.ԋ굟15W2a(78|~`u.q Aybv wļ$9MZW_x-Fmף~qffOR\W)"6[Z IsOs7ϽunA |?|>&b9ݡM.]s& iQfE*2o^DjJ [P˯'[j1/Jj+Z(xMaƘev171nC7_Ĩ'.[mR\9ѦS] ցBL{{ K "q eB8E K^e::'BEJ}#B)0>vpߎ:zX!~>4 \,+A";a,08YFUi xʚ#+"0pC"'iiHp`,0&‚ q?=^6c7ykq%z yHk"P. \| -Q\pZk0N"X\2!}BZ(x.밠L,xD MR[ G,ڂ$<';S/ kfNTJؤJ; u,pA M O:F&*@0ZH|ʝE5. `C>%鴸o(ᅣتK_+'f))n6Х)ܔgzTy&Eg3>7+5uhoFa^1$^`}TpQHcd7,fCuٷ&ѝʣWħ*k(_op_l{5Gy&d;Ġh0M@Ҵ!÷DN՚.OHo18\`ЃiB",7]&i yu).UXόU]3K8z2޴{9)$6D(F􄄨SE%|<08Ch >_@@/I4hRQV`ⴿ˗B Hd [0?\)M _$$m6 L4FYU\;}))RQ xx<8;C0w4">տy!czY!=PB&]ĸ3^LmlXs]>AHpX`݀~'u(|7nʕN3ЯW\pVK?u^;fz-y%X7)>ӭ[m))׎]GYZڢLBzS᭗s+p~&mim-otM# F kY3ngʺ}q+˩v_Yʢ~ @_iJ(}W5ors7)> T+رdڊyFM6A[AE%NQծ[րcӚߝ?ڱ}OàXYWz^ ~^n@U}ڮ@-خ2lo`?M7c͓>lJ+pϣ/'~]s>o<oz%W;-reeh]4sk Z vL[zz寯гs[8|M@*6uV 7n@E"uemh]k@up^߬Y۟zYx K#Zy;oSuG37$݀~S`cN хQ[pݟx]Y{Xsj;^ /*(bǖgwaWu~Oo`*݀~6L8k:yU^Yf{++\qV׭7=)~eU7{.@n%1q_q:Up8 % %Q`@ eVre_i>A{u0Y-IAkoz 7 e=w?+ w @eQb5r=t2+?UkKRas>RV^g_?Zor;>pmaڃ@綫e_LVV8h ~3 LU_;ZkWe(5̣F=vwK7"MS+Au|-#)Y:%^bH*vEN_Ń|s' g=:xn@I#8n3\WnSuIsxrcѵ淋Пѵ i>J)[{p]5,\}6pѠߏz< x;b^Oz_/]Pz6u.Lܾ5i6ZW\~δgf:f _3݀SMٻ?@de * kwQe ^a矪JHO*ޕOƴJcAWf6Wu=9,MN7doZAпV?؊fF0"tD:nks nv 3P'ej+y]_}̶츘_nkx10 \Zx?"@O27{ﺁkпF?+=AwvncSV:[#Yӄܞ'9zVٱo3 kt }ƻ6@׺d{ εm$rcpmn@lim]5+NR,ڶ}WQ֞[k7LU dfvc~6>[zvJZG+6eaqw' <;ccmn@Z%Z~\n \r,rek?jh5`3Vvw91u d{^^"yhgW\VkiugsR۶^S|a+"[ wߠ _5=97W3u֤e'r ln `;S53[ǘSlv&H*ƺF~+ދk̬3pC#l/}pFA пd?wjEa+__Ɔ5|:ڡ縚Tyu<֫Hc92 ݳڪh5= 1 쑮~j jҁ''GޭjФ+4#oX[s+4ޞ;_{4t̀%>t{!~}2rѧl>p6]/߿# _ `}ԢU|W c yb1{3HgW%>)[4۸G,uQw#_WW\+Q|MY cg% ooP/zur;Չm s͎ (oA#ırL{?MxC>\7vsR}D11pm+r59rנGu-iJ0H{fm]fJkMG8#ҹ&W|' {5p zkL;wp7ܱ:n`ṭ|p#((zz|;n5[֎O#:n;am`H>JM3t nb|u-'N'TWkuP{kgu~'?5/}P?`690۱wqb+iIƯ=H j?[ܧҪg=k;Wcz<` UXw6 gYF4bґm7ENۺOnڤ?lY`.f0$4F[v,wzs+\Y/F`:-gIv3V6sv k ]={H+ZEϒ( [j[um>]N5MHS~(KǺ n@D.z\Ez]7f^<:;KoYiQSoZ: wMS{YQxCu$*/yӫ^v\BS};rԱd$}mͭr+\Y[yѯ݀Bx Wv 3XAǕ-nTJoYH7)EuXy>ek: ~3ֶz& _kҭ@Jt \q06'jO8/"[/괶`?.݀1B@U+K[[Υ0:;zr@WM >7=}>osVR2&SsW3hƶK3@1cuOa+`Ipնd1ba;xvRD}D7,z=LXy$Z~5=vh/i=@٨kf|. {ЇpC O7&?3x1Cz Fzf,zM>wueVX?*6ltǒ_S5Z2Up-X#앃*x-ψ-l5'c_AWַh'NZݫ:|ﲵW_.M8?{D*tkQmiLUϣwx*~rWSsva7CpYıiىiyI yϼ|Rutꬼ˷T7E:juiPWWqmWgm dT{Mq4qt+ɀO?S_ߛn@ :Pj]^N%gi`%tik~7ϻoc*+?^Z\堶z 0DqV.5]uxS]ZU ܃vZlF?Hw~'۟Z"nt81VۢVxW)_wꚩUSGU0xL^GYn5Wl|/^ _;^jW,k{?][)szI]ZuO O PsdV>Y-n:jUqinxGƦ#ڵUo#c_u1DgV~SWցnQ6̲q~A__,0Ĵ:?xXgs란:%)bmkZ_y?hGהNu#YutUr봴V}18 NL=}B&Kvşթk*yU^6~;OF<̅"p*I38JO~y+8Բl'?%f[֔"誁ol<6|5?WЯ 圁z\_S uiWrmlj7Z7Ҁm3zd|kV5N*Mu[&Ӏ*,v}oWwJ"u *my@<:%t>}, 1] `;/ß4[QO tּSb^WS3m k@@t\͎LE=}Vq~S|eh$I@}w~]=Y^X#QF/&)Xnnn\3+tuGW@-fl_2K -w`=jh,Ľ6 IDAT6+~;| ;TyijM?g.J7br+F\[w^덹3>}^;Ɂu'q{0s]ԡ|I&Yb+=X;q}mc?z=|ҮXmձ F*kdr}f6YKmjhx,rq0 >'2O<",ƳGp&8Ig딗 }?b2-Vem3 ke::iV1g) mop؏RݬR5,O傯e0_vX`7_|:qds뵔/_eZ߆2R>cK}wt(݉ػ|Wv ˼WpB wS Ήiv8t#-4z O9|t ת[:{ l:5j=6٧N<M->uec_y]4 (_5dz, +x쬱0 7j+ VeEWA_#|3(wȁSn,j4͝W9M%ImfCz!An ,:@`8)0v2r\u@:?+7?kSKףN:FYfƀe~T[;ˬwqq=A5k[[V:ڻWWֵ.:o?[ ˁp%-P>e;TXIJ|]Co_? ~=wwff#:l[>[r'`[ɭd!Uzk[Au^q{\]GgW~/GʇIy`\ /7nfsW9fuD^{ԩtF85Uy3|&U~6=f}o25a]1Lۜt?kϛEs_d$R75<+czsFv7;s;^c>z\?|ޏmMBP({ߛ|,_=@ A {@_Сj>y9WEȩe8 8*=>VgGU=pr)UJ,h$ᑬ˫^vFjle}W•U0Vp%P.ХWL5%E:VZ}}Oz[m[k_7c5yo7߾P~ߎ-j yO:ٺl!|V3N^4hW_kT3V1mf [ZIEGhX󸸽g 6 <1aN /68˔xt[W]f+A6AL|RܛWV63߳W_UW5CFGW_w|7z}(w-ev@?N"\ќhFxXL[/go<HnKw@^D4Q]F'6+w}xy6:/z3[T mȻneu¢Nޗ.X q<1@]F|X̬J/u iU{]u WIPԧ %qtޚnuuKC uO_m`G/v|>ąBy2蛛Yˏ{y|iזz(y=\[qNl#VzJ2N#σk |@,G=wǽ>1FeAcY*g9P3ZU*mmW2u~5Z*;wn㠿cWA;,7s9D' 7u3f`nvN];W` kgɓ:_U{yYz Hv)`3L,pͺ2Nm^?7~Dy}v|־y6e@;]n[OTD#d"9#嬅x"3*d&<ՈNDz5iNN yPǐOd kpb7%v5g{#h2U5 UwSHumЧ'gnE{XBn:p ;wmu4f{q<_J<z=ߛfc<__~_};n;j\=o?hk#ڣo(PZ W tY9+}`mP,;=.tz5+Vҡ*,neV818 p7Q-*=}Xu!맯~FbffW{mԍ67{eoڅe#/c`ܵjgܪsԝ+W{vR~Eg[s7|/f{u:sb*-U [fSz;XPj]L`P_.u죣GN,jIkҿ f f H c9FבO8q@V@_}$\ ʍ5lq=ɻEy"]z_ SU [hL\'?7FADőC/zW ߀G3sp`#>s-c}Jknso㵤EwFcȓ7?FǖO\Hcp=ooc,F4n}NiW5U+wuV Mת}FpdPrhS㹶zt7U}:>5qt 矟 WS?_& Rx/\$W7`33y=;<(NW׆P;kqbuhiuǴD *-gAs> *?x4x:nW{WAr;ָyoonv>[cVׁpٚF g0@jy ڮxU @sCYle3X$@s YGo2'G]V W:Of??诀5{c?d:F߾vSny#y#}}3[ٚ{0ǿ5K{/m}W[|t֧*Cj9SX(>zSM\Bmc`9d;]Wz7I•}cV=~{O}7\M[Pg3ng.vԃ[p<܌=xwћȓXj{hfi;V?eU>̬ڹnn/x?"!rǾ,%zJ>^g"j;wrnəiܯV2:KYQFkޣѣ<\ϣn ۳;'8fy;e͎3mt-rf:bǠե5-O+fyzUn/tŮA}fffA᫠ȑGY*z Wjq]z^_a we@ϲx vW^w&g~U;]`Tnҽ~O.m&W{j;PHO<]p-o-%mfJU.z3{L9#2L Ks˧baffSzff*A:ב(3苯 tV b+U>K3zUεƱ<σ_5-]κfjukK~f]̯h}|:m1jK {.j Zř,ZQrj[Ǡֶcy$|RE?l9~_h6 g;NTЛyGjb:B{oW`0VWW<1m}S=kwҵ 7tܣQojMmkfLhjO{Ozk@kjz_Ζ)O糶 +Y ֵQ7%# PM=;Ez[M  s[i'}ո?~jK䦶ćDpfagUSƑZ8?c* Pz;mkO\ v{jG]7{(.]TVuXw-[MX?@.SAre7Ɲ: ʗֺsU2*m'(Gbhk}Lgͮ$ɓDޜTG\Dv1N58+@`}>WrzW柁Few-3!Aބ\_Zґ8k[S:Qm /;"1R IDATdUzWe>~_W1O}Lr_*.wd3?&79<7ӑ뇌O6_G jF Tj8jaN%ɓ+.|gG+qa4'r326]Q7~9͇aK,S5#On=i6I.׏?ty ]<<~P}g{GUv9/Ycu7C,=l,(Nջ5;KBr_qdf3Kuž쥕T4:3:+ޒk=n@7 R?߱g#(3 \Y#},ʢnp;d^َutU >n/s ^t++eVeRY+=uf9LXf.v[^}Ox_}zɩZsg[9lԛVc}?y6r[N`C 1kAp31D0根FzǞ99GO ,ZQ ]6О5UǖsSN<Ͼ$*x=Ao>/>cQi|UVl<ͲNu1)]][EσAy_CqH_ߤcQu-\Wkpc3ѯJ2,O5jbLpׂoy\JO+Vz3r~%ʝ'xWu9<NB3׀^AHE R;U $TyƳߋ1>wb>`d!E@ tn:5Orc0^CNñz5rj39?v[yz9莃xLsB*΂X亡u =GY-5*]qO>n0OSH3&kٙk؞]QAo8M[pgU]jܗ:(S8ݝt!zξڬL&$86uN}v뢾lc@M0ޯ>?;}13 33%6"σPZmoc"0֡&êπRmig= be?$QggĆii-jln> ~Sn1S[4.,.i|5s=~],`#|VqKK#-l('ݭi2s&/Xi.jOWYEOh#X2l/ٙ._5j\[nZ 8E;׏u0˸Kı8<ޚUs-| /%ܷC|]߰8pN Nޞzs@nqM=jTj ג,хL#Uvz.Mf?bP7ou;xߞO[0njs>OX5ml{Ȫkߋ vmM{W\oԇߠި?p%zAa=h1$Xʨ_/bVaf9|#!eTpöCGiAwvrUVK,tƟeuѪLqQ^+g<󏾸N[pKሧ϶7˫-mle|z 軲UMn_+KZ-fb'lW:CP6>}Y[Lo sV[[iM >G+Fu,[sL 9f8(nAe6S }ȧUog]NN[!Wku0[ ̽X usBWǽz]z"8>w"+nD{}"Q 6ǧV=Gh<Y ]d gB7q0<Vɛ ?gwC7vEpYρqoA{s 풿 .Ejz0XguaƸNYrfX?c6:?zCmj0:^-oBMϪnFW;ǟ~'tV>ИgYUkDKXf1ۜ W3 ktߠ ~XS˙R))~!ZQn3UzЕ͂ܡ>tCg c7zn W{mW9gK_ΥU,q]Rϧ9* ηmilioJϥr+^Y z}N+ 3@l(}Aʯ[ Cf-̀8i-lfh7[88:r,hkǵ-N,ٞ؞'f̷ʡL͏.xP2^DzbJ%' PVu*P.fyR1p g&, G{}Q5G/,<_3lz9汽zqdoAr|;[bVQ|P|kZv|H} Z87 3ۏh;G<ΜS)>{ڍ$xJ튿٥89_1W|˽UWPOq"aMCGU&9k띀Ժk 2̑U9^ggU68 ӱ*^ޟ>*^c=>9-FbzOiZ@}?:]#oS*ߺ>WV(2ЕA\>2 +0 5@-k_|ؙyrJߺsWom,kUKMeklD ^윢V>ׁpX~ml$W Т{ cx0v9WIYxpBQ%zQu%5n6!O6o?>x3G]9v{Ж۹Yv*@垯,CZ3̥t:X"cRشE|NzeU7(;O=m~;2gU躲ֱ-l:60f{gnѢ2f=cގH'}eSpu ,$?ÅYbrY>I-75:\'&bV2&٢EUۢ^3;c}ѲUPx.ֳC%N,詷oGˑ Rnlo.ߔP%jO^Vtx d<5|DƉ۪ͭEO[܋75m$2._N4W9'>և8_hsނ#Խ_,? :t` +hz O2/9(;pgrmV>Yv{1hmcֿa5PU?-8;1}k :F{p=p"0{G:OlAOt%i;;|+ݑJ^^ަo$'(x͢[C۠/]{3`?+=~Tf욏ь#߱Yv#Ovr7቟T SQMͣݻ)W'yS/(ꯞy_ Bv XY68c ~NHqW6sI]ᡱT˼o'Q3Cogl ؎|ux &<''vޞmoeU>kC:d9Y~ 6xk۟A LGC >sc_I(? ke)Ck#EyKjL-}*zYe5yON[r/ֹSLgesƸf-\t xrANe`YO7a}3 o鎷rVm?u>ϓ!1Y:y~F+h|#d;EIF><H=r ǥTTzz:X?\湞-xnt|eT{X7-kq֩^>koB7uWjvoh]}*Z&+~ܕGObjBi[[NB{z b{3ZM{:+Yoh|PmRHb @yŽnCב ӱ%oAG? ,EYV73\??zq]-خf k1Wg)ֱkVc,OJy6w֮l)П9Zњm㻅cF nW+~lYJGFyvGtu:g e \moGb6˽ޠը<|1V̦Ar!;{K 帾ߨfus<-h't_?ZG)Y;D&TGjyzu8(AX;W]sxy8F:sD>Me"Xr߫m=GG٣Hf|o]qEUk8ﬡ3 Imje]V[s"McTwE>7얒Ƅ q$7M(CY՝k㬻$1|?jk[X1Pgg>>!ݴ/ޫGy? Bo^;7띟yCS(fnj=Yv{N.3G.xD @7,Z;[mvzwls-k4knq܀3oKw35{8 mlw$i˲-eH~gsAys9@Å-fHvS1㖲u =Uc[V0np~9͎{ 4rt4Iv{9qEg;H'I#yYʵtbwz;vՁ)3h3 GUjJ'q7{2EDVρԶ8ylq5+GWJNz〶fgY2f¯۔ܮu@@~uzu:r ^o?GTe~ qB:"Q_ݺg6 .yM#ש.AQ_ްYԏV=;@3Tl*xxR ށ)ytvL&+f)&#w!]Bm8if<׹Omec 3Mut{;1˜'vV~W|k~ܶVe۷;`-Ƨ FS}U ΕkZhO(.:w~+ :"uj_x%~T>@S[ԗ2xQڛ_)P IDAT`O=rYoiކrj3? Ϡo?pwyٗ:}5c+Ggȼ;[]VX_砻86&lL4=?8Ol}'6Ӷ9 ~kuN&-TonkarHʚ~L~MgC,v3Ez}@#NKj6n(:;[P'c_vAlA7OlAu|_?q| fF=ogY .-* Zq\GWhS.[MY8 {34YBx E ,WFgnЯE+xV}ҍSpZj" j6\'z,Ny*x >ڝvs;mq܏zJ2&f,'/jWYYYӇ|PmY0(ܽ~q|=&6YfUV}j]VF5~c-~԰kOu VkovE#*;s'./O!m3wym'*ǟmޏAI}?Grf2>UFh3Զ.\WV=˨8fK;Z=k|!=>~|p`xm_u:Yv :>E)K+r5G{=GjW9G{>1?occF 6F=aY|oe 9_YˍXo,*p"őM U(VkcY,?yu ne2$=x=13ux?NU-[eW~u?Y橁R3GA;j@˪M+|}{KHwaiWVםnma'˺(gl G0މtWA &fѢHf~:Oݝ^0xDB=ٺFg@A31vAyAݟ9@GpO]U0Xϼ sЬ& snăw<{Qw1sӨ{L"hz5s+I cp5N5&|:]Ou]pVu ܣc掖i}! <)}ܶ/iFubetwShZ!h+DZڹYL)LFgVmcPOg=B&ܧjpo*;kaS?Y1ס==8.H[Q ,Tmo;'ܕ~o6/u8 U$k κk1hծ9oW'>|lS`c7=@_AAۑ#Z8!xr`xgkc:<zwSoEI#Itn1\V<p;/ߠ @mV&:+1$yqVgp aFU+>?mccUq噟ƞ-Խ,th k9-difVQ??e/ll8#p1-u;t#P(Y;w6vRʠww>20GlTYj=wMtOsߒ&y hiS#J >ءܿjymgob-`5qNH@y/f2ν >԰boµmxk ̔8,8exB@۾U uvqkfsʭ/bv-zζ~|6Q_}6gdufsfV4kWճ+}=s$\:|*w,5;=^vQnE=ꌟMQf]VQ]@^iB¿fΤ'L fVnk |ўuCIQǧS얭yru(PVjYrg4WYSU|ͲxY(ՂƋmVrw+,GOUuE4V!s(tkXo5qD%N t8pkޫr{q{T 0v b9;Xqor,Z,b]m>JwuFuJ{b:VX_Yq]%Q:uthuGhηhRc]euo5~kb\7d7,hS=VZSvPf^yJWt^&y!uYX#Ȱ;NۜJz䰟{|PȾ_>,W9f,m +Ʀx4̏ϓB& %?OnGRu_Q;>dK? TVSU%2sBk@gD7K<î|@(}?d4ʊut353(kǶXqFaG=e4(,WmF37>JxW93"1PkqjWV|kYԟkOß7< oHcP(73 3p=x6@T#r{%CgzϺ_`` hV%Ԟ+`9*y| %`e]$Ma3=cq8umxfXݕƖv^Ϭ7|ZtU;(_<T@v] 2Wp5sn fQ鮏F0)حfqx3y.4dERQ6SdžrOB;c;( YEvBGnE܂5C7?G!`_kz"A`Go= e(W$3ؿ!cl9?~F7>QJ(Vx[WῆQuUjWUx$ ?d2 5uh#l01N㖵 *zѲ਀yx-}~NŤsaޝ|~OyRvG[?( Z[[?qmuK<1muUB].d# `7iabr6>,x޺q[䉟՞;J10#hc}mv*V⟁{|^QHs9=Z{7;pY:IO@Tݕ}YD8 lHw"x^~yey{Ց=̔G/O|~zo(zKW|>FQ?fX\WVV4[;@TMbagy?E`]hޫ[n3x5Wp8OQA';1sK^[jFuɤZy d[:eE/,q-rmTJWcb?_ڑ2g7 bs h=NY1C.^f [Ȁu\rE=b$?Zl`;tY9?ioIO_ 0-xRg;ŵ\_vch$7d"+=Z͜msosw>Ǡ v!z+r1({v6\;6:#yxX%DrwA>ArJv}C&ma+N~3X'9}ob1ֺv/қFb߮`S"N/w(?~?|sXt#nw8,Wvc_ =fq׵Ͳ+"{oNaCжps+ܒ̈3G0nNx`V<}ޚ?]2w?^y2Ё='Bx;U}z!'; Wx7UAviZ:GZ:LY K:ɻS46@6imh]e0g"C '۰kOHz}"0a~lGrehIr(IlT1Vcŏr8* dcWŗfxϚ_mczXbWvrq8u($rAJ{oc .v^oGz_Ȅ9^;& D.i֋ FA2XTJ'I@M~*q=3n= h^tͺTNwӳ|n6;-m+keWJHBB!l6c1`LC!7{򰺤QFIsj3ꖪJPJHuvki-xSqQY|yeo6'UVGrmHƺ'hfuٴUJMv%{q6rXyZOk =t.'Y's+~{֬O}zuW>{?쩫I㏸ lGP꯲!@μ|f/vUhrRPbRX:Fw[v#:Ժ ق-5뢜(볅=?,kOl|o;N0~1@Z :kA~pƏN@-ҽ1`| F.w|SY'=T}ߨ=kз8(`:Iԙei+4:t ft돹DWӏO59PLju\ m&FqIo7ç Alm̶*=[- ъW{U;Bswg6yy~}&0ͻV wy'Q-`ee\Z[zuE+23^OK\ &*Ae3Gfqn˱-FeZNO:){?kF5[otW {V?t IDATlv.3XnoW&VS7ވwg͟XN}  ZMȮ&v[8wSnĵnʲt gpHȃOZ[9W峬ԥúrq'f6֤c|rhtaG{ pg 6JY@7d)ݱ*òly*xZ29B>y( +zC}Z.d @^w>emU'`ONqN"gTSFe5ūH?Y9XYְkӵ=p 9yeG067&[ΗwjZ@ )m]֨Ӝ?Q72qRʸrIUMin!S9No*Mm0^6^cju) n@GO"b7Ya( c|BZ;\9@x^_kc+A/ZT薓-޺4 f*7b;'aAPDz2e|?T<{xMx,@ͯs-y}dk;13KeehgӪ@b3ˮʳ =tiհ1])0@ :u  #Untkۥ=չ|'c1|O#];ϫ2Lb׺{ ,c䭬fra| qu`?rZ3PN> ъ治 '$7GxlvA.~Glƞ0r髯g:xtIOoe`'P.vc? [~a*8ŃTJfoq0ʠ.UĻUy$&%_ [Ჰ;\+i{gklfo).kAw9gJlgǡu?{\*5*\'U5$_Rc:l޳}u^n /M>׹Hq|`3XOUƙgnASs^ތ)zcpE_0k?: a)3YWOwQ6p/8 zxLUp3޺YEl"m…nVZݮsvBwz3@JjRIcY\ 9j1p-t)US ,VlԷ ^C^nmj}- Uy[--@r:9 'Tss^<*- 3@ly`JwL˨85oދ8,23`2G}3@yXt j]:u#\fa ӱ;PcHnRW۲`B`6e|?3M,CkM.;{&vK`]@ sx̠r`*;]\=u:p!+9ZO >pIN|rG~W#@ۖQoښiG ܉f,zyC.ՙx>xq𛗡Տ2s6>,cw^Ǒ+ASbYh[]jr{Wu}z^gӹ.WcZhs۳,K[Sj}'Z雠ڠu>i'Gߨן.z{X4m֎.ugK]m-ϕ%\&xyNK:{"I~XiC .xut:4R%v!0emކ4\s i:ьSw(PЂj6\&fg˭{qDk:Ky ۩pi]}8zzu/T nڵz+w\5ccœil30,Xm:33H3" <LE)Ќ*ր=tzr`\o>G/C=enqۤj 9gk&C +3T廇[N1wR^πnss7wAdm5LVR3K{|7Qi˴ pA^*{j{;_ܖx]%YvX'szO#qeߥCpV x]M˛`Vu?eF ~ykW'EH泮yM4yw6d]s̒Xy]fV{ܜN"M m.OֹYqr_@oA]aٰEtY뮷_7iiPؠSVnc ]tOOxEލ,osWAr:y~u 8&W̳͝gs26'(|,G h /GǁA̼ k5D ttxP#gw'}@ ;:ur6(w>j=;5j*žPQnv˛,EЧsrE P藍y|e~@WMtc; -=:wb<`xuy01ȭA;_u+feBVy߈Fr :2^3`@m9M]g{|^WrFyW} }Wn2NLHlq׻(ws~7uΖy3 KSmn`'Bgr ܃P3ڤ `׀ƺ3 t展˝m)(h ttm׬CW)uܗ^yWzCPz_uɨ;{k?'W_]u@n0&@"XѣE;:.|2M ϑg-9t5*A=ȈPX:_ |֫NOy)ʽt\6*k,z8C7@42kv6?Nma`a ށ :.yȬU}:UrG⺞ΡW*s%ܹk$j$O{= vt(R^g+mΪ9kY?䒷U_vKlE L}Șor#H;=U4v/ŵʧ,αp<oa[QiA@:qrrꘁ;nr4c@tfvhwxm1C  G46s JQ^<p$Run'kdרics <Ү;P\-CÞ"ϺjT5C{me:̋8PڽL b0XVȇ9>9>߽4>CZ:v 3~^u^L=:;AcMyn64f;> \)w[-?S s 4!Xđ,l^7Fy 15׺2,htoJ@%g7p " i@Zĩ$@w갞ʽ2'*L~*?ϬjжPjtǹo/v=۔םЅ [].o(zO "75C>UaMOSQNe@o%u nqC6:Af(7xd{ eaM>ylW3 )X(v?h:IF poG9GͅW=ӨA\谚CxVrxqJd^%,GujWmt|~w:ޫzqngho̩:$C^f 9p0s'de٨#ۨ~ {=sP|4A.'N{USoAu:>q;#b:Z⣎' }Zj~|[m!yj hpe _- Avj[/Iɮk[s>,څӫs۹++ @W\J P^^* _pZ QnwyY^ͱf>B2p˕|?@wlmecs{l&xsr3(lO]r?ZNH VK:/W >A=Aez3|#/t8`% PboMf-U\{]ϭedt~ yӁ-wșX| ?~|18hu/ ipsxU}U0W}[ c; S2U@sv3^'?u=u_YXx٬+0="/΋7♮boCf7<ׅ^鑖F=Ut{/gG= F^x,X89s ~,wL 䪓G ĝBTfנ[.VbG"- @ 'Zp~ Rsi@P\'Od ,=Clt͛3}7nRh;Y~ʠ_ySYΝϽ~"kzW 'kے\'euv;}ekzw$cy+78AxJ,.i !xx\E>]wC3wt&%j;wCY֥GLJʫ[;`lסW@ۨD]u#ϗݱ`wg~g^tuc?+8۾xRfv ʂ1̠dB: J τpˀkP|*AkaGh[ALӹWԝZve/ce]~@)guz0A/]%lS^fPwAF{Buy}AV+y3Xݤݐ6DGy΂a>@:hum`K,]f+ ۻڃur֯ohN>PX?.r\񅺬njλSwy%̖k匀}Ѭ%Hu}Ǽ,{ӃT,:O8;!#2s=mq~  w ^?,ș,1Qm #LmbZnsѯ/Q'X1xcF;4y I7T/F~/|EC=`u?q1!9]NUɀਬeo{7U9^{j]UN^YΖz@?t f x~ σ$gsyM:7`zY'1rt9o%& 2H߬XfҼA _&~lp.h׃A[8q_Zm]齦TЉz kU]~W*S{A7]sgF8g>R,{vgo}>ґ GZ7?.ä#Qt%n [⬣rs(M2x<';wmR v&`w9#䏨PǕBpa&eY~˫+oH,`I IDATY2YnБViWϩD+Z`_J.nŻ( 'OV n~}5+ z }s3Vy+ɣK&[8۹"@G@Dk[} 3*/C8SD]\1c`TGs藀dS>0f =7d<ԳVǠQ6ynqG^1*OO萶jPv{ۜv\O'zԷ('@WgicڻgǢ݇:_֘" soDy곫f5'e8\ _YyymMpm4k+p4?Q7Cuql:#KQ^>o-h8yCV(\{>!Zp٪UΗ#e]}+9;ݗr,S?6\3دAkhpOY׸[wvv@rOd|OYj][6-Yk۴Nj+`Zļx,&Y*j $xmQ] ^ZB-|E :< e$Ogz^jW _WѨ}wརxVZ񕜕;\<ɒ=c gEN.w| 'vnzC;:<[2-w+_-[3~Vּ5pV087 "߬x5+* =vN緽,]\7;\-@OvmLͅ§sIFAW &<|ŷ,w@v%zQ>h`p<ЄIeyGrJګ _@t^UUy.VeZuik[3<(S ɝo6A7hGjrz|0"2pZK ]8.z 8xv58dд*0ف(NHE˺3{$ wUYƿ+gU^c"YG|{{W̛c >@wǹ;v@DLgWFxWtjSI>ns uCZ`09t37ͩUm@HDe;HGlQ.yU*Nwy5d_u]O9)%$-\XS_u'Uj?;ns*by͏uK}J{oEf| y\޿y"7<h9)z6B'jG;ꍲb;hH[.*/L֥,kc\fz^񜂾{zR^"FܟM1wd^:,{'Ou:g_V'xW*:^fq6ϗL>?jĮ}Smu CY<葏?x`ޙ(0y

    w̅_@N4Ӻ8wFA:X/鲡3yhry-W U+rcOǼOS|l-0Е3ڪ,͡9w&K7[+uUrб mi:$}^x {?gdowj95_ V,u8ٳMKr/*CGnSȣYyۂ+gڲ=T:ÁҬy4XO?Hۻ|2N%'rWJ'qݚnCH;z!+@:Uܲ5R@xUzނ'V9_gR6gyqp]=sWy7]AV{~'ΝggHl;#b~i i^Tu(40c9+*t|l:WNWߝ6ZήUɠ#CϵLPeQmTe|u.˦ vg2|mi@g*y]2@"p;.GE5 ȓVs=mGLUMUznCTef9`խR'^M'Wr3ݚ.˾ks;"1_Hz^3[3OѪ@~n4@ߩTT-RɎ ٽ `eA>Uj<1DysW:ʸQtK05 ;w>;rN'A.\vw^e#tzyD$HPzArehJ %`5^ѩ^ ~߲sӀNMGE/5syFlvީH+u8CgZ3uV Um|+9;n;r{'n N[Ѯ,q*>۝eY J?9PBֿԉa{zm?̠e^nV[_tn7Ocv7 xNeuUoVn\fe4?7w㺟PMYN?x@kT]w@׬xx VqyxyN xۨ[~F#;!t3`Y}3un"!eܑ:-@+ԿW:j~ˏ @&%g4)b]t JHb~'j(~]'ِb]Ϻ XV`"g⽌<~NzLs`wɁq ڜ Y 5Ƀ U`tJr&PrggDkw)puSUOHJG6ꚯtkf)Z}ga3e}vXPσj ׹Ꜫ Stz-@d)Q $fL{fBw;WU/j,+T?lV~tfcU' txIbۨ !?^9n aLUͷ3wrvEj-NpX@ p["m|S>KY|$*=掻tN^ֹjKU 䖖{ϼOu9]&RNSfLwճF+k$MovoAX VSk=ΕtspН/3ݝ{i}t o#V|J!}2GT\'}S ,gOȟ ȴ[~mT-O֑{^X-tj?X=0++DկwY ,;wgYW1MUArx?y]' _ z26,۪ƪΙyaYɍYzqw"b=w'W+|] PJusd_wZ,f[WFa ߕN&Jsie+^T ܳ5"2b;Z7IY+oy8pw+-3yŠ`+:g7c7}w7!k^ݱyMY<yP#9 UI>Iק@xO;ZO9HX^kqzj?,oTKnKyeDzB=C O|^W4^p‹ iu}@诔ŋS'q(b zU9Kklpf:f*,yغnY]5eQs\=փ:ipyte[x9?"o:.@B҂b'rW:p{0UtVIoO7yJIJ.|{YZW( wtg `lm)Z[ќkK(˰댺h]fꖬ@d7UGAǪ{q=կ2Ryn}վ;δ]Jc# 5=jO~*A{ۢ$}=x&O_骟 ӨJZT@_S"[Zn!y9n1;ç;:k驅ϥ|Wx%sPo@6QtzSRiS@Wyǿ PpƁIp7;{A)Ώt W߽^&i=Y< QU?aK>ś mVyKN,;SD2nY w:_M7fwۢݼ_Js?<^Ik[~ rܞWAm-?yf>y,~p/Fڶ_r!%(ՠyԙt=ePU5=cY;`^ {jbJ܇D]7/JB|ǯs7S Rnp¯lS +zOzR@;? 8jRSv=*_'=_=nfu_-x;fRXg߭“Ao[ f},K +K#dNoW<_oRb+0I='}8م._u~CUsi@gT\!@nNt,̓kh|Y:_5fg =@HtQrwZoxHǯ;}@<TwwBfWFOՁx0U Vjr0@dR~ow@݁jۉ\ݷJջ#=(S]ֲgRJE^ტ}U~:$`سG/n vN'3Hnck1xLeȫn SOz' 8/$W'{f6xcёTɓvd+OB:}V]7UsK;cw7DN;P?{C: p#<Ѭ׹Ep}<ՒS{xQ@bW7w ⫇*:H.:PZ+~BܭJWVP T^W^П3+xNw6+MB~Y]NFP+Юh*k]S7% ܭ՗)}Q^.x].,i*j2,G +̳l0V{;WrW+zǣ'W6ۜR,\`: %ȣ.ӭzwpPJ>h NsXua:5|9GAπ+g: |ݺf/w\H`I ]8Z3kT!~j9Ym}7⪳PWR=0;nny8u7ۃNV+`(6'$yiPQ`P%a%oM`J䵘xΤ ^)b,P3D&EwW C|9mo:pˍҴHM c.[ɪݑEC0rKX7ӽt迊{Tyo/wTrw]kyv|nSewTyչ0Tw?~E5{P%( vPE]Ύ36P?) +݋w0Aw?ݒ+<>>%g|7 ^++nSR>-z%hfo.c,@+-l)hS"I_b?O,y_퀽5;9'0NTa#Py˗s%zԲM/A ?Y:_e  nt`*WfA@'fW+ _ʩ@Eۭ8[E{~b b7*0\WS&D}UEuI~;(`혍z|eﲴA1bW_\}B3h;&cqg@q|ltHyqaI6bu6-s - >&*mӖx;0WW󰑧s2l$1yyV|$@[wl}Un;V )r`5eF@Ѫ^6zWn.M_/{* 4[w׫y>B& d/I [@ gX_KA=3_G|f{7cd f̷fmk .](  C"9& ,戴y9q%c7t+^-q=m9{._E[^4H)kePo\&^w}EZ[ώYE߱O]/ȯdas*^җ,0@\Nd[]r,_JQ kωyg\.]Xn֫{'pG73K寧WrD;*{l~GY |w: N^ -c|/VEE[ww+ &'__.aT?O &AwȑG Po&x $B% (8q5c8Ӂ@Ly%hQi{˘,4ZNP  @IfU:ǎ xDˮ+YW˹NyURQd\.nϓh]4;$O4Z qT,e*kX(Zϫ,x(Oa`7+ e;Rm>,b5܏e}r^ c<+i̳ҡt- xa+k~'>`9dѪ 3^)37wh_--x Uo#@tԀN.m_5Pwr!$@ NUI{[Ѭnr)y=&O}͒<78^zUzۦճ?fi9 qf[j2z R-^G>WT vyx*krY$|[8AZ/t.N+1VWz]֝϶~zo2_w+]m}PW;pG=k"O?kzG"^$VawA9e;ϏKtic \UӸNm`^8'F|!4MQ=cj2]xz\{>H M nTrw? DYTYy %+񺌃 ;VuϜ}fW*p"._Eޫ+fF+|yX;Cj= 9Nh*b[#,.,p%P= ?Y[R_n4x:Z+]F1(<^ P,8o0@pЯ`yA^f9ODF)X;Wf{Wij=(yUNb5Im9+!MJ"<q3+(6~7ZX!o-|2+e{]qP+q}-f9t+? ;"jy@%,g7\8OIov-Te6f{KhP z/;kv[.OW`VY%of/z~ /v t܎.pu`W{@Eům$?Igfz߻sܷy(f3̋\ay9&a95'8;aD \zW.~)_M߱<5 ֹ z@to o ?JQ>inox1\|9tU/\0| 4ά.xC w+6kF^LֿZ{_o,`Wv) ~w/7iN7[& 嘝-Gs|yMAòӋNucr8%U_'Q,=vnvkSީ5a 7MJ"-5ӻٙɹu~R6jn{\欧`堸j -GaGo~sr*YKb|>+)+v|'<΃ݞFzQ /\] :Pd;9oťiׁG+NI0)pf\JGY҅ytpP~s;YXO:Rh%w(*y~҃:6-1/Y^TG̕JxߪzOT\SOW:ez;$sy%r?+Mu4 :@r>[0!OZȰ2L-:ձghJrx;.33lj#?_ecqZ3 XH;X^F(m7׶4O*˒~ {%BL 0+@^̭6&Pg\6q;=hXcmU߁%8(+2-顿f?,hp:guQϦytm^{}%"P7ŧ=@#@aop?,Yڣ}s5& Z<6e<v @ :^_3_.%o=u*nVqjuP8=9AsWEJEG@[o¢dʞ즌;ַf<+}&N"PKNKfu\7v>85>pA8xD)+Tq6ţIwӢ%W"H U7̱,=@^?<[ }: @qJC;M趚;_YΣ_W8/@~qG~ǿHtmwkS&w$] 9~{qٖw]F/\U0p: ſt~ puXC'X<!g . uyx-Н7<̡˹u 3rTל| ʊnQAW=+}'9fyR> -W3l4 t)2TӠ9Ys~ D4s}j]rm} tY4/ 9K}ѫ+݁[l٫5׻ V8;5udum%YFh'@k-[A}r{z$ 2ae]w V^JnKOpw @`iY.9^>\Xu9ղ5( 7N`֏t&h)\} ۦu%ꅜJ_EWwϣ{zp{'Oo=v[+AqTvV~xQ,D05@k̽FH9@zi*K}! ܻm)Etɤzz(Ҡ{w+A|t| qZ>AW;yGHmhgwe4 u ,AVͻ+P@dN9Yu2tOvmw\r׀U1߽n~Ɯw3cy!r[X$a\u:7Gn$O`cXG }5>yo2AaI;ɰَ-q骍f?6u@<- yNvk9>|iheE ݠ-rp_!DNvۻ޻-c =MPnP^,kH#헁5|Knswvy ,O|ZnwK^d.7wW4іE\ܓwiݘA8+(<.OUG#Њqc#C% W?fvM%rC]?]>oG\27ㆣL/YZfyWyUsp"=Zޕ,ͫnħV0vFsYk,/U Gˆ,fܘv`Uv2 ֍}G2ɮ`iq~y` ~2BYFt>hI/{ O(o';4 Aw303G2z0薩gz+h;= h8x V[=|_o[otվZ`橫tҒ5S -Fzf֞#u3"MYSE>yptXi\{j סSYtƄHsă2;=B AG,/a` ]Ye,qWx ]Z?N}NN ;tޯώ\v3+zѕWb^-T5OWK6eaKٮ}=oj>=({҉OgN$H4oZU)~;Wjt]Be6FB.]r {nYඵ ާ"ʱiGOYпf4t Y0>@~y `s2Utí3/%'v!/nFi6`3HqO&] kr[۽\vYfq~rݬ\QDqͩh-r2O>iZ˫Ovc=:??۰\fD*_$n̾lu9X T*pN͍#83 /y>Aٍd^!v^NqLם-s4N@G{/1OMr;= ZnÁpF| w*#p7* Q,[y8#"p 6nf-]f 1>~t q9"ad]?o>>>ځ(/u:MةگsxCWsnYrk: qrWЋf.{@,57x@Jgz Nfqs g5ۋ>7`I!0;10K`ӤǮ+ ?~ X>w%`<ʸ Fj \ twS$Z`j6"=]U,˝8=A@llPj.(@ IDATi7j@o[3~.<^-:N̡+NX|JwehN.Q8TԳ\YKF ǁ :XYgmחLy(hϠ^֖Qvwne:} NyW Fp\>(C Y<V\f-tt pCyvRjPm旣Y=PμnsT:Wu@ݣS2sċ%頻@Kr.<:sv/xu.r|;"&р']ްr?2Ȋy`tdN~np-Ӆyo'vaz;A2Eޞ59{ޘFpH6P5@c-YFj^ڼ [HKGK< GO>X6ߦ) ؁t `?+pNҁ@:rP]=\-џ̣AAEdjv:ր~7;C#N?/ꝵv@E26zJOC>{-˱~p'{#-W2;}BYfi@Qz?|odD îi+ ywrXf&8}!x-  ;2ebf}HLs{g90\;>rGP㕻 YAZM?t=VF5f]nՙ~` n&lYvU]cQ^ՂI͏wA5δد@^ü{ fOvk nw!WsKj}5KFdf @+1683hf̵{*hz̢ZmI[#:zYOu]n{>$~}TOyܹ%kD3eٵIYZ>,'K P8e7]ϞĀ`^?[\M(.Zv#hR4oOX6"cyܻ|"GRWt2χx|+73~2l "ۯKn?ւ}.*>Oh=m>+@-u9@e49wǶe7 hwX6F5E8 ?qjx Sek,X 灙^"ǵߎ,4)~E5+7ItӛeOEzu8@AN]9NbW,㐔m9%Fw00 d9@ nvq8auYta3^r܂ᆎYynpPS¢xh_ Vr:{qRAJ0xr-k gY Dʸ!pAmf="<-A9w,c0vmA`Ukٍ6|_t.xKq@01й W8|: ]/vL #Z̍YO'Myxe_sD;F£`/!tK5opz:sa姁c^~~A'u9wyq VٽU{7 \&2/y lԩ5MdGm]ѽBޝY AZٙg@% sއ~쫀ѿو ,Z-$(chiu {s,DEXnܑ.S@ejV<u}]l8g۪eja-Yq"Y,yX?>^G h KW5!"jɚ:fkJ,^<W\L{@[w * V*M_t[ޕlees/Lщ)5([~p}ZU:5M>en`&*2\#vt֜_r9Kz/ʀdcߎclq}^VDikiLj(i$.^ыxH?gx/rq-=YaܬsXh p`-xA9NnwHyqi:whwn*>Í*ޙIt# !ݎUz_hMnP֠+JWtS@k/WVF/B~W.OMS!#/7/h,GKk\{$Q? p06hu#9kS]^AY$K=b6řcU  k&t\N1p t -%<"Xc`>p_E,awyrK"-K5bGLry~ݰ$K,nʼur{6Lj%u%''X-s衚S^cTUxn*p9[ cWM?Ț=5L!#QNA@`8"_4)yᚭ-\Yx][¼yCХ n# 8ne "HW?l\e~1?be}5U-aKL<ni.|8p-`붴%]|5uW6![;B~\ͣ+Z<{]hNg?U6y[1'߹Ub{YηB?UY^⣲>f, f (_.v叭Z2 >ߺMd2K#$QrawNx!)# T;G߂8+ d"P\+',nwHǛH|a2Cs 6䒸eN;{V9i'1=k?wԫvZ[Nm Us~ Oitn(8b;2 ݏq~[Ѹe`sAhN5 +tT}*+m#=iou° [ჵM[.zWOu@Xf)R=j,>TaFp)R5?תQ9ȟͣ{u~vGOV7Z.{7reH4Zrrwl3Ml9f 8e>4wa*g>n :/wcM%!W-֝X ߨN֞cz*;=' $w֔rQJqȫsXx}nZc dEC@@.֐{ex'N=d;?ZzX} PU xEna~@8?CUw@V2@"<.B`p`\ק 6eU5cVtq*W?YniZpћ叺f_]Їt*Jjޒ."jiӿfmd?1 xtB?yn9ql]4hL7 !2`.5y:?<̴ţIAp}mOrDϣwƮ/]n'b\h1y5 PfObzi8oe?},y ΙLg,us7x. w0We2y/af XKlfs`:Bi_j`5]̲ h5<6[b@nսg|i\$ ci*-ٰ{jinY:5 ;nx佳Ǻ_ wiWƽ/7HlXly =(z`:8!: ZH,_<nlfre{hu.\ slxY F1՜:tIaQyHFz3chwky_a>Vw> j\D\x.,uz̢n]8O~`ّ?Ӳ%sm򤤬rsp۹i[fYf٪T:9wgin%>KWPF/Nou3ڠUvn8\|Ney'> Xe-p\]{3-sG2OMPo4 :e> JpiõTLX xاjݯyy-?]f0j;uwKi&cP gPO7{<=Цog@x5$ Q7$(ڻ5鶟o'?{=}B Q$ DD7!((D1B ((DP!B(B0"ApMYdYd.ȟ>疋3O{pLWWUk<]=z^ sago,Z';+Z+n!/$|y{اD@|Aq7Xӧ)/Co׏v[/1l(}^9X)*τ׵>Aw`=9! yrAu~u6 )@#H8$rɼ̫y\%)HxƆiW< 3#9<:9 iA}ⰱd9& `şڄԀඓcF^nsǮ;ԙ>woT+}ʵsx=U?roǗUp; xޓ4y_y'NeoBvhڞ\w@@|)~ $ͩ'zZ<$8 NfsܺkoN|>̓}pP˶i\Pk^ !?/.3P77ywptOx`d]x<[ou _bc~axlwSl&.WsC|{8u};OX -K0bo~TԐ#&I[WGlkkU~spWl0_2ͩrG: 9*˥УҔ29u˟lGҢ;e{(A/4Zym2(uw!Kg-ރH1[Kೞ%$}P|)&]@Mzy`γx im/zv-zw~]\Õ @飀輛c.wy~E nm/-5Թ ˴C` #1\qu\=yz6][9gUCꛐ{*&e5/g:Ӂr/tvu0=*Z&C'ǚYZPzɗ76yBu)̯+?t{%! fO6y k\gi#o̳,مһy/p/l={瀠.92p5?~4Xwo*~y|$.A㾂A5'&zZ|rH = q^2܃yN,A6 o/2_axuP=sXe |+΃pg[5So}/z> tQW/\A$O2^<̯N~s?(Ux0r7|º+\ GmT%rT<ΉM%m^pfߧ7vxI֢6&`xCL[_M" ^^:Nw{ܛ' 2t@"<:+$gOR'MSG}DzpNNt5jx<(C5ئ|_K +X߅=GQ]][6-65AԻ,\9]t?O}v03HM}ٿy2w>C)sU2f]h3S҄ؗ,x9u܌|,o@ҁeHKe5wTS?^z 6M]_L綬0OP;{@MV6gq/X61. MA5 55^;iק]֠P\o; _f\2]zmv-͠w^=/cO}kpE'0Wo"g-_&) 2|y޻s ol۽ IDATK[ Hg13s޻@zcocT X_%˅8 S?AK|䀟q:*' Xt}u;\C;.|> 064S^Z΋_tzW57!x;X:z8D>Їɣ7ڮ3\͍mG>|QiW/܉/_vc (7%WѫInYz!]HuFzNe 9LL 8߁e^ڂ4ayĹA6bӀΙ9gGcvb',k?9(!7AXO.6˝6a΀/bkWAPP@3 qLvvä́+tt/9 _6P-pN#y7^=Cds_е俏d}]<@1|K:OoѶ3FzIngs̨jׇe{z"PZS>.8l Ё6zQuUw)qtRvp;0G‚x3^72M9ͶS_>h{>~Ⱥҡk4~;?s3g&AruZ!hb`tӅBu_y]S q7.-~/mX[^:ϕQL0ͭJ/p)=>/,Pו\1WK|M~ɪ.W 7y.fQaU8/[;"j5SUn8yy}6L#\E..F Q~]6!Ꮫ9֥/K\i\|pedN{yg;2>|B{ݮo0d.u~"9n/e_t%{3eoms'vZc^K [e%ABB닇oy3*7zNo>xh?q5~F{OCH_px-S?[K~pv ;Gc6 _kgzu _E&)oLH1v9};.Lp!</O}ȹ<|_*S:@)!Orrbg/n,-*VW%mtpZzڈ QSJϊgt E*s=j@yvW|9C4͏.enAYByadOpYY@GppRYVzf}s@/7 O$:m&tω|>unxS6TY˞C{§^#^!4,#;yY:ty+]H>wuMoz0'X`lG< M6VVZq>ִeOzL&^Jɖ_M9 سGZf^'vy|&&de֍y̧ :{:_ 8mʢ;%W ~RGR ଄:`wOicSt&_#S> xr3 ! ~;sJ[ޞT:۠}iL@r/Y:Nofٚ.,^vT37g h l3eUd Z;wB<{˘}TNq'@ p 듗vɿ Xw_ p"} eIW yCAl?*{4S9W}|ɬEw]Jg}:78ou $soZE1_7ͭ;:÷W_xf7e`BKhڤwB د!l.}|1Gu7e'<Dfo/_WׅmJ̏cT zL"!0 gW+-]ΖKjswM:ۣs iz7!2T_>}JZuJpރh`OBΏ#s { l;]͹y'W?;NF8Sgኾ}J`I`+v:>8e]Z=ugzlƀ]џ%>03g?v.ase8X^&cK;K<}lo+_}/w(o~( q7i!$Y]ku%In sۧkv"X?u]3/@Ix[xP{52y<D 1%$?i|<^yDƵO[pձ1o;~lm &d>zX4<;~zYnŧ7zϒ,m)g{ B ,!DM&V,@ڸ4QȾ5R7/Cfk,_Ћ4?n$yc-*'>~^ ېG>3 o Skxd_1l7Hޅؗ8.m`t!w`Adӵ(@']yNР[Jѣwٿ Ӂvt+ :ŋm噇q8\|r;ZgwʟIj=x 7q3>A蚝ʒ5 0˾/c6S>ϗN7-Pp(W*W9c=G?rNl|ϵ 7xĊFzޗSV?5v>ae7FCSObvIvrk 4ydrG2W>pAGC6*{wh9q/Dp[LhZ苮mM[@r징ViOsDD1_ܕ?6Is@sI U`GI灃-E/6G?a>㴭iW= W/n.^t^!yڞv/1s9!.EC'eًfK:e5l+.uzԩ`6vnf{9O`9S;w̝N77aP9w|~tϜyvrIwOPbᜃwy}w<<"|z'l=Vy/g=h5NzZvˆnٚ>:xd0yyXI76O?/i+6;oz}񸏾 %pCs]{}cXyN}9UW8s:g={띳.z>G7<&>6^}=./ZmRΏ˟d{8̞ȶrH7w$5yu3;{eg_1Uyslkt<݊T.Xqd;~^;G(DvV䢏kwDZ1vޝ Q9 y^{c+<%7 f2.6jܲ;R;}ftsܦsL7|\լ5^G^+N;>IC˘g{&V0XR*Rrx>=r <|W޿ٵ;O8Ӷ>b٦hh*`hodyTΕѵ]Ε< 0ǵ^G<г} J̫U.G+m^:w{wW|-:'\hA9nlp]>=,+]{Φy/#'|-Vz-nU&ak"aON{̅AuMq y.n+cg4Ӕ9~Hy!z^z!r|wWͧ]pzݡ̪0Ρt*g:[IwhɿxZnxJK|3(pWmOE;׏kpPzW!_|B))9OiEJΥiOa_͏=Ufͻ`٫-|`OaӾvyo|QslUo7͞]:Wޤ?Im?ڹr0GxK{xs#zw2?$YzR./ _ytmq2J^Ge⧌u:o8e@nWt1G&_*o,2K7k0uY  Z;~ڵm4i+t. x|>M_y]Ώ/7kSoɣrz@(K`Y̡ x֑ Ӂ5@q=r9nۭ[_j}Joױ&sN /߀vsouʷЁ:=!|rn9'i2Jw>G m{)-YL g8yK>¡7Þožg>mx˾:{7%HNi^8]Wޔ_^k_*?GWtnweʹK{TRҶyz뜱>Xmh^z2֋wz,A ^\O?<|8EOue;a6r}''}6Sۢ5\|^Kj$-j|2?2 z hMMp7n+iҍK]ɖjvJ_b_C6q||X_|@)uD 8| aQ[eskH`Pѷw kn*oarǣasۧU?6 7awRbS3OnǓ$,8Z&0<8`^w!}s7x&1>q!WE_ԣi,A..t'[B+Et"o; (%N0ņTnxyx)jr^ô.uMFU7pWWZ%>LOug1np{ '%R0u^3Ї9oˆ6Ir[O'7?y7ΏA;em8lu[y=ƅmރd:»x M[/^k^ G^:7q60C;g IDAToVt8;s7avZK6xKf-~wsh[C \qc#_|JzOòpw!ԡpe9wu:oo^ٮA<m[gp`wwxk&X1'v&ײ K nw7W< @ϣe8˗m@ A@\p; S_\tp<`3P/co s߮a0: |%InӯVOܷsgx}C/Ow1͡p1ۗ{^KPń$%rOn&t)ʐls(ל&̩._wajHg~0< Xg(nsQXZ~\({x)V.Qn ;qFZwr ݳ}bք#~&PS;Xvv uMZI[IۮM'KL?>LCtן'O` MGk=_%,-݄ǐvym[uva]پY(‡`wuYCJ:44ѣsޓw;{:uq;o;ד6d됣o7N`Bۢq G<-v ?6}/\Eǁ<,߬|ɓ z&y)̨@j۴+۞}(x_ʕ}ۏ2:t t>yڑ&Oqv9Ӌ'ԋ.塟;jZ[PI/ŋn t<^}ε/NP[f/݅z\ԁIpb#Pbۢ~Bg=ftK$f;ͮz% \7AtKq;/FK#mnmԹ [Om=tuKq;o}8ƼGts^Oz]αO6? *Oמ̳˝u{ڥm9_CxL[zx7sn|Qlhr;>n>,sZeϹp=?ko=@w9n:C=9)A?z\3w ?ږfԏmC߱el#vgE5_bN/'Gusԣiߵ)t_h*yz]nTDžlܓ82NآmJ>K6@t`Ɠ~/}q,r8Aatz-XohFyŸz?y 2o^~~=2m7Ѓ({s"l,u*MJ;|Ҿ8=yS5fx9ߙ['>̧/z8Xu.Y]O腦KgK[6=NNs{Ё{(,iwQ?ܖrҷlzqEsٸA ym]?US5qT跜E|5MzߩÞ>7=e_I#/?N:9%P;KX'f?5tԇ l} '?;"^Si|܀n ~{ 6@|ɥjr֯:M۰^p?W!xd ~s /m8C@Mh0ش-z8 2XD7z8϶.y+p/_`>m@ĸ+V wC_ %hܮ ~!wS"Іx kRۨͯ#^|I{ik`NZdK;-N/_Lt3 w ˖yOnVa}ü?OG{.&%潥2峮2 -wؖ~wm+n s~ve+D8K Mc!el|U2sR.ls#^u Q_>.PCdӒȖH~JK\0>@tfq^ow1(/D7ΧG>zMOi}v'>}UnuDcoj9['WSf&nIӱ$)wWemg.ade4%~JMi lwכ#YllfdQʟ[&NOUۀ~X\ҜhC q7KP;.Ϋ[]JF朷k'-_7r&1=eݜ:'䝴?Yx" g]ֳD5B>vb+.xomWgt'S/nGo'`:Ȁ5(xꥏDYw.|n>%~ A6O΁ʘR<% ֻ66abN"X3kAZ G}#U|S.m[诸l ikBt~yG*s}3uN9CR_֣'OOc#iS[VxDɻr&QyWT?f  zbsyu3owtiGmuK=tzzP8NesRyϊz%,$sn7jH?y7%-/ўlTcmCι.|/}']B^4Ei..KʾXT/6 l\vvq%j=vq#{11_ק I.Oٙ2 (}E/5YhWBʷKXvBM,Bj5u.G㕗S(wt>ߚh\a~IHMB햫-2w+nT~m];?'st[P ߵXm蝷7ˠnK ߮5u={7~1gk+z4w+@yv[M9w@Ǵ٤0::=n{z~@?'w k[TY~70hߜ]6C]Ou 5}65ݶG w<m 0Lv+<_f0Aކc=wՂ? .36m ğy_B퓮Kvzm>6w.Y.u;6!i$s=l7  {5f~!wx=^'N]Y'h˗yI~˿폓Ȇ:hv8&~,rK<8IXׁK&S3%h[Ob?<,GzTOGioi[/pN:Ix?)_|NwA3OzM[>ߔq:}/u:N4z(_$G|u;O%h|S$uk5y+zn\`9Nݪwf_zqAW;).B``.:܆ERw7d-ۂw>-[38Q͵Z[5L^)Yϒ%OzY9t ƎXe?Z;{pi#Ӏmwz#oށ@k[tM(^xvRw,{2iѝ\[krϲYh@)kIx^i>jn;d3Yϋ,9R0UO /%,?65חrݝ/y[˻?4tr<-enm#*aj_\ϰ'.nJ8r<5BW8m/CW6>К/K\Hj״ yMS28B[z'Ck?R] o֕@zDRVOzW|M$[s~v&Kۮ-`ozzoצzAw>\#z !MPc>C /0^;˻$b?y7 {z北m0w)pkT,% Xm^yEw|?58RLu ؂c`&vyt܅\7Sw][ɺrK(*e[fWP^Gʷ6<Vy0!^ QwmY +WC*^yoAluWUg(?oP0PG;1!klLKcYC>rjyzKXf7w-c8mZ̢mEA9?=,j_zGAwf}|?B[|q/@!]A!b,gn+X݅3dm0ldSz̈́ Fv \o hH^PǙN6҅0:an,kqf?v5(ϾMw^ i=l{(FĶ3Oț벞̈́K]v;-nxD ͅ󼣳BC6NF񤸁R,`a@npNUƄvkۅ7:\&ζvdi@- `o׍.ܻ9wHv}rUծdl&{A+؂g:֐/^\ꋗ~gXs dMm]"/2`]\糝͏S[;8?"?:';|Ё `'@]0tz. 3Ͼ6[)2ϝ6vx+_|`As׮XmU'z&2<8Pvޛ[hƆ_#w@t+Η_ynz܌yKt@TM?I=iHsC%Ou6 |/sɿǹ 4Gri5m@Dy6]2/?pOr4/|ͱ5pWJyK OE#.Ŗ^L};)ߤw3>3o):5I9f3;o~yޜ뭧> nkoCs>PCx-3?t oxv=u21k:H )nY[䗵ptm%LϡwK(kcnҞǖ_ۃCq' 6Iۇ>GlzʦdnȑDž޻+'l.|oE72Wu=f ;s[k37DžUu.K՜\ہrö;K؞O}];̹ oM𻼉]~KH7s)D?_dIIqÏHJ3 ry IDAToi|7 ~^0wq% Ir[!v>Wr.tKXU˽Gn0}wl ëuļܟ#LdɇE^|M .0g۰歄7v 'J4 mvN ɇ'Vݷ\/dB MoC*8R{ >iNl*]{nx"{FTbͽۃٛzhϡ+XWWc_?EIr陫ל0ζ-wggjί'/q{n7ׂ?Cobm/~W +j7A{w)"P\bܝ78L ^B,-N;oܭAm=u:W׾s'K}Y;^[vah[6cl ׉p~um˅\; Xet@w ?[=yV8^$͑6aŸlߚ~Wu,w^7ap[6뛹-.owi5 TN<Ĺ;u#F1\O"gڲ]v㿻2rd7Bt,KGB K{S027lM,AYFEO`Ay㣡k_m _2g,cDp ,k%_s~ņԛyT>q,҇G ,ѩZO(֏r˵M(9N6u,a~%nٮ+st֫/;cw&8ˮcuw =sx*.|~;avsj /!vn[B56rψd?Co=m>sT w<٦}-nk퐼 U󜯒zm[|Bm.A/^O#Wo .EA݁e?^YGQ0-C=b 6R?h9p ͷ0/=z?r9`0 fn-m+r;>irg /}d.nstٟy^k`C\1G 9 P]H )OwΪ5doʤD)ݴwu :16>* L{2mδ^o٦qz9oZV&N.5<♖2GZOX" _lZxV}N]fu9kt%aa\]V 4(}ؕWM` 3| x3|.!c}ArxZ6G^73GֽUgi{ྛÿ U*W_Ypn~hj},cc0< eiz!p$986ηzɔG#PKc# od4l~OEX>>PKm9=e^|!#7ϚC7x!|Ys{+>TsE]^m}{&_.ms46͜< 9 xWi:1G#f6=bKV|:?@>]Hxu`5?v?InB@(TȠYd)R7p:~Mz@'$mןp;$v.iKf\륛ޅͯu乷|z;veg=#d́/?~1-K(VOEuγDNo-qM"\ܪ ^ZWO*! rYovǻ|G# 5d(:6~5I.+ι8鶉'K֔/sgLUmusCvԿdk%9'?cO'}% ޣ7z]c:eee ʥ,XCL4+u!P4kjT4À.,iw6? NFڧ -JɁo'\gBwAM ̥]hvmwaxNcV@Ѹَݵ.tP=澼ߔc..IB䱗6>7Iw[ n!ޅ풴MKt64-_ǖڻm_K;s:pč!/Ccxz9ó9H&y*P$_t/Ey1F:9t{'-W6y+']OM}L[uR5'<{ǧi0]W)kAs::[,eI=̝oF3eW-[S/]y7=}S w0#A==|>bCO#RT_ZR..\#a]"p л5}ڲkWQ:a.9Ne:}2 w F m ad-g=h@W^%}^\Kyp8Gq anm~yG#uȸl)[b_|;Mr%Խ9.vwJ&xOYs΂sZѼ$Xfz'%ϣ6 9L[LP|t2ln^W`-kh}56Ӷ,jd& -5 [ Mׁn;= 6  Gӗ[m?1/`s{C[xyRMS wlW\z[Wwxx{\r\s_N9PfJwm ~L_o97meGǮ ܟ&6M~z\=vao>oz ͹mwo `7w@Pg}6|.&|M w׳wbp^}>Bш\/`!۝5`ὛIcT.;~\#2#J6v]˷Ϧ<= MەG'hhrtq{w0_0^ XBΌvϳzHИ%id 㔳\Jpx]z.؁5CuC.կdbc gu0!mmdBNշiC4U?uqw<+?hiBR6籹Z׾ o;ϗyv\X' ?_,u_G\`MӉ`wItB8-|ڏm<K۴StF;6}f;sYw!Am\ݑaj4ۃsE'|&wk+unm;ΝhKl#/ݲsMZ@%;Lj?~~uY!^xk]uf^dwr~W.`w;`@ױ;s&-=P@[A1]KWe @jڸn3̳=^wifǎоמ/K1߭ǻr9֢w0пVc?+[6^]Wynӗe~=ew^6nxn.]\:o޻sCε[tmL]m Rvr2c|T~ jYF yO0tgq~g^>Xf_yx/AK(w0:пf;>?Q;/|7׋'>n<T?  +Hol?xV%9O{\yߪ#Ν./ nw9nj֪+MbxXUdYW~c3RkV\PXoצ,WkY<滁f6|IZ3r@/+0>5D@9}Ss|SMiQm(>O7*#~_ȁ!MahYڐ jh-<}pEiW;wG㴮vwmwtln(b kF_藃 @lZ:YkF_&`;/9ޘ ֆ_;?G{^ZΕ? H/ Dz"<hӻ(Q߂4?PE/)@Ɍw۝wNy7HH"ݛ(`nuj!'-a6) ڵj]d}.ZΛ[hG߾U}rG/0Y}vy[) Ū+xtҵM};|͠t3BMNK &AbעٶSԋ͍eJG73/=04`;^hǼw0y;꿗vK6A>G·ښ}Qd[Dl5}NySOTBE[#kSNlr+fԅܯhO*8d6A@:v]aFH)IDATCcAt/ H^*4`˞b$e-ddWfI]&ҝ mueC#xE0.rjn~"jL]y w>Ҷ[vU`هh@y-V;пr|!'*9@n>. ۬v~%3]h| զ/6->\[#_R[p'+~@_(PzmGj|CC8ez6醴47p0;߈ek m;п9֫S݅ !oof ५Yv`~g;C.ZWLށ=\}e hy˼9-b#߭9 -p/[J۽t  t4ws1wR{+1\osF jϹx7Iβtw% Hhί>'}uz~$`lxN,hH[{xצ9G^0 (fH}-_yc9QChZ.vs|xa_m kH xum;; m'o56}EK0~h3f.'z gy﹤ eɪstA73?,F̅yYZ}mw9zw9;oxtlgֵ,-<- fw:xeGK2k踳m? tls;ƈ}zKr\zqWW^ w~Q(H ]vi{׋Xx:0[W:W`PouR2%z;p6%W[n mYku[y >iwuɼ_G)` X{.9 Nr߯@{K.+zd}F#K$w'x W:?') ])CM':oahV6տQ];wWӋ52~Sp7G(#xm/Ʃd})7hDK7"}''cL 5Ѕ(#^?-[h ="[j{CaeNoR `7++8wX<@cw@?wfޛ;{UUW,Kxjw(]߉lyy:v| +5nNUϐgN <^ى~<6יڱy2|v;՛^/{CS{s[k oQ6Lk}9%+>mˠDZyX$}%m}ӶyڠQ%e$TdI ̚x'D^J[ݩWDDQ^ΒZkuzxͦh89N ۡ-pضe:wx6хPDL/!}E6uOeF֨_҇Ffrh(iIFtb;:քau>D<_xJ|o}m?$oNW)@tEm:ʬIξ͵w VD z:g QsW⤎ ur_ WD~(B&tjaGuS1LHNkѻo3Ƅ;Rn)~G+Ѱk!LnWvFꢭwbH7nPDЋ׸>ɒ?m殓綬ErQ[VFv3T;ߡ!2{nG8 G: ^'ȝNjȯ E׊w~&>3> kԖ(SHo`ɞV'o!WgeI'j։7VFg;9> aH>ȯE׎SwT}CߖFCdMcz[klw4Fyyj`Fw%dI0)mBI5 EpR^yFΒGƢOt %kR_7Пvo@lrIذ":hMñ0>4us:<~5]%y'GFFX_YL; kEsG؃Zfk٪A*`Vme#IM# %1|[ʶc{C#:Yz*,"^(BݱD8@%yq&&Vq:Eu}T{ij_aRVM՞tXR3<]yz"yIL|f}/2~(Bؼ}/(k^bSx`:jfK[rL2ZP+G{R='Kw,5?Mz?fηz׋$-k{/"(B#vE+v&'ʳz2^?٘l?0ҌxeP9!?nyp!K{B2vkGI׹G^D^(B/Zh{<ӫLZi;0>Α.YWw\zcX%t67OGM _ U_zq#)"/l(B/ ؉-x:g˛]ukNgss+ؽ CWFԊGBlu@PX1L9 &kA쳈(B/PoޙG}&+غ6dS6:Ge ^ǹmYY)g:֟i z@t>21{$][_"kums| P^pN7n$CcbAG䡟@IuQ&nropy5ks0k~ː<"BE4>4b={^{6 Nw'1Oyoɕo!*]biw8Hxx=3 ?ş (B/Ŷƞy:Ϛ9BQF :>/ycwᴼ {"§%HmW ={ǃ׻"Q.N2;2;&K{e칫x;f_ V=t??`{x,aH1&܁1-"/\"½?@2w~5XsGr>^btq[DoǏe ״~ro"p_xC>FV E{N km_S{UvL~2ݙ> _3l?ꙫ@LԔ$if?Eg}gPD^g6;vWVv/a>vn3P{AG=L wUٳ,1ݣئH"d8زaKl=-/<$ nm[em9uH̐P}l FDЩ(#>UA Ӂa hD}`Lo~/EGÿcgGvn(fÀ/yұˬ׹ ON{)!D؁FЕr$ΓYĠ(B/<:ar;*ֹ厜ɀ|6pw@Ow3k\ 95}Y ̗3OR$^xM(B/Vesl&L ɣWYZ;o.%U>,N24}J^tL[dow' 6ȹ}cQ^x#w0W tS(t!xۆ*N)UA郒iP Bom&VO߂er?%duxMBz߀_g{-f|(P+s鄄N9f?f8mzhH(o[׻7 o( o4,Z *II[ݳڙ5[6A3Qi/g$;E\Dzۗ|HP^x2y~wL2>3Չq̳oG!w/ܾG"c$ݕaTH 8 rWPmA;E'"“_GCQx]fcO׏m+ȄD%Re]P($76zv0 OE'-oW< l{{ċN3Y8K& hE腫p縗h@1n6Gfe,t avaE+EzgxxK勲WqB;R'UIxᙢ 9{ۯO_uL.ܞZkf9j2qO7ϊ Zy€?rCn g TIDATx!S0:F=Ԭ**3ffxfv3(PS @f3VUf5S̬ ̔N]׻{/ZKӔT-HшF4hD#шFt跉SN{z6m£uG\?`%k e<^gy{2 ϱ(hW\J$=4qZ +{pjFi)-yR[2.kkJOuh&$fS)|q>. fgM\7k E%Mcv9|)gGMn.p.gA蚩Erru3}:rU'q̼I.ab*3wtveNWRShD#шF4hDW+5uIENDB`PKR\N?MMimages/wheel-dark.500.jpgnu[JFIF``C    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; """"""""""";}~._?R+ɾ]uoڼ"""""""""""""""""""""7>w<2-2*3JJTW^gr""""""""""""""""""#t:KY****45J2M2uzӜ[DDDDDDDDDDDDDDDDGgy_Zҭ-iiUiUUiVjUefi=_ӟ9chyOҫZUiUiUZefiVZiooTDDDDDDDDDDDDG72-iVҺZUZeZZefiVie|Ϙs/2Ҫ*֕UeZefVYZiͦW+ūDDDDDDDDDDG.8-i4ʴ4ʴ*RL+5JBrй\z?9u""""""""#wrҲ-it44+45J2T--5rW+W=ˌ2+-+*֚ZZJ-23JJT*+2LY\ZʋWq|*""""""#<Q6qM*+-+,KJ饦kM-***22L+5ferh\f\;5"""""#s?MҴҲKҺZZUUeefiVjF.W-erk2FSz}H^4ʭ+4+,饭4fVVYZieK˕嬮Tk2嬮W ןDDDDDz|^w5iVeefee]M--iV*,+45J2(W+嬮eY\˖)y\{DDDG,ίLR2JJ+,ikM-3J-22JT-4MerY\Z̹\W+DDD}UeZUUZVY4ZZfZefiYVjʍer\rW*Mer%Y+~ϗ"";Y}_2R*4+4+,iikM***3TVk4.ZrT-es.Zk+.ZĽ^n?hC=6iViViZUUiUiYeeKKZiiViVieiW+rk+W3Y\ereY|oڝo̳LLJR2ҭ2J*֚ZWSKKLT+5JeEY\˖\ereY+.Z̸kω9iR**J*ʵJʵJ-*iiikR-RL+5.W-f\Z\W-f\rW3X\e|[s6O***+M**M*ʵJ+-*֚UiiUUeIrW*5&\areY-f\pe]OQUUUUUVUiZVYu444M2Y\W+Z̹k2Kk+f罟,zn*5+4444+44*,饦iiVi嬮W3Y\ereY f\reYk+z^/Wӏ.IUUUUUUViVjVUZUiV*+5J \er˖.̹k3Y\as5̽ߟ}o'***-2R2JJJJRʵVY\k+.Z̹k2ˆk f\eq5/_>wߙ|*,4444*+M**4+5ZerT\ereY-f\pfk+rf[jJKLLLҬ*5+444*-*ZVek+W3X\f.ZkY\eq5.ZW3^OGOK}&UUjViiiZeZeZeZeZeeZeZUV3Y\reY-f\fY-b\K5ם~~UUZeZffVYYYUUUVUY\W-f\5rf.WY\eK5W3Xk?k>fVYYViiiiUUZeZeZeZ\es5.Z̹kY\eK&eYk f\˖xYYUUiiUZeZeffVYr%YYk2Mes5.Z̸k3Y fk+peYk辇{ƴ-23JJKLL*454ʴʴ23RY\Meˆ53Yk-f\5r&3Yk˖/?vo444*-23JKLL*4444.fk+s5.̹kY\eK.eXk+{5ƫ454ʴ223JKLLLҴҬҬԬҴй\f̹kY\eK.W3Xk2k+}ow'YViiiiUfffVVYYUԬԴT\reZ̸k2as5̹k2f\57zstUfVVYUUiVjViViZiYu+4ʵ4J.f-f\eq5W3Yk˖5WYk2k+S~oeZffYYYUUUiYUfef*,e3Y\˙fk f%Y-f\5˖/^cCeZfffVVYYYVeekRiijh2eW3Y\˖5WY\es5.f>g?rkoefffVfVVfZj]KUYR\fr\r%Y-f\K.Z̸k9K?'4ʴʴʵJ*J*4,R]M2iVjjjYK.W3Y\˖.Z̹k2˖.Z̸Y"=viViVijiiZiViZiYVV]gZiZV2I˕W2˖.Z̹k2k+fm;֎7[|5UYUUUYYfeVYK]J*M-K4M KEek*K.ZĹ\f\rfS̿-C6M-2*J*J5**R4˩K]44454K%̢k2IeY-f\˖.ZĹk2xw|SVVffZVijUf֥֥ZefZ%2Q˙EW2˙reY-f\/ˎ"5߅&YVfejYVԺԬ֥ffZ̤R\Ir\s.Z̹k2宮|<(};JJJJ,ҳTʵu5YJ**M+5554KIrʒs5̹2˖gqμDDkYZҬԫLRK*,R]MjVkRZVijVjijYR\.eй+.f-f^<Oݖ+{X ).ISZɄcwaqq-bZwcI$ZcDƓZɆ{m܏p!0mK}][OfdhJҰ02w޿Mv/+r[tٟ9Ծ-kG:z.SJwO9wn0[*==')3/JxzϨKd,ȑm)):Cy{5BZH,LΐAaȠ`'ֵ1E%9(cs"(G׋&#Rk[_n-uIu43un_-P!10@Q "A3q2BaR?d~fW!_5a^^b/|^|\$6 i^Ƹ' ;0{͸{i[qm*KN:w7jKQEN.(SZV m۸7=0o.b _|Y88W);7F8NŌqN Ҹ7v"@K&WY֜-I]6NrrdiEq552R\w :Sv&ɖn:/rR˼N뷽O4),"gv9RXURZjt*=EZl**-׈[982Լ8P& s#s$H+"cG=46I@=_16W>Kդ?1~>/}_ϿKģ:+M# #U}c\sO Y镀мsk :g|NsU \ÜNlg[3Zjᩯ (B\z7_|ZޙzU]!BJ,->b}f[\S4RXupפvR~bMCJ,**-%71W*]q p+_1H qD`Vcvbnkݓ۪bbjkCj$.(W~#lmAC&wJa&&xqp.RL TUѾE(ÎR\ NhvtGA|YtupR\UbT"o 0AMH7\ŀ*Es_/!1P2@"0 ABRaQC`q?%ݩl)׳kv:_ם/k͓5KY8xP/io;I*?IYO{֚S{6jĘu'H/iDq=sAHm \btz{m;v⦠,=UKt͢ߣTտi&:[.Xx(.ma$154]Ub2խF&~"^ ƙOkuz[jGdS1c-n|Km@3bXxK#m;f<ޑӑڭW] 98ݣlH0Ž/9ǖ:~ǰNyoūL?~ǚ?j>8hF?[)ڝH ؎> '=&J4磗 —n}zG>}zG>#sсA&mڭϯ+΍18>6^~6ΡG/>T)X0s紗\{he5Ix`Rw^QPE7I׽ڤUu1xkPE7I׹ڥUu&y7b-ZR{G44߀V奺jQ3*kM~~Oq#yN"e٩oV 69i/dW+y1;њCw4!P"1A 0@Qaq3r2R#bB`?%>iI{HOIDWSяYDŽlxHDŽlxHDŽl?w9ΗJ'Қ̘ꋩ/hDŽ>e<}ΑtKaa"ЭE%ţ{<1ei)c\tɿ_M5{?r;{|]Y5o4i9gul_H8ISLlmYߥb/j=g_}/^JϏT{B*(X\Rtε#/|9/v#ݞބ,lrGne{U^6^XOz ~}$4,t'A$xU^,%!e {o^ g6QxUUUUUUUUUew߃W?5F]+xK跅UUUUUUUUUUFvorZZ_K9ՙ9-UUUUUUUUUUUV[{oY,[UUUUUUUUUUUUU2K-%mcUUUUUUUUUUUUUd~zW= s~\UUUUUUUUUUUUU',jZ? jZy&/@fkxk|ZֵkZַUUUUUUUUUUUUUUW k[ֵkZֵkZֵkxUUUUUUUUUUUUUUko kZֵkZֵkZֵkxUUUUUUUUUUUUTT5kZֵkZֵkZֵJֵjk5f&kZֵkZֵkZֵkZjm͗3>ZֵkZֵkZֵkZԭkZjOdfkZֵkZֵkZֵkZֵϻukZֵkZֵkZֵZֵk|uUUUUUUUUUvlֵkZֵkZֵkZԩZֵk[UUUUUUUUVn?&ֵkZֵkZֵkRkZֵ:s[9kZֵkZֵkZ+ZֵkZxUUUUUU~ΗkZֵkZֵkZֵ*VkZֵMUUUUUU[Uw]iPJkZֵkZֵjTZֵkZַɪ>7+}ֵkZֵkZֵ*VkZֵk|ƪܛ_"v=hzUkZֵkZֵJ+ZֵkZֵUUUU\y<ӣֵkZֵkZԩRkZֵkZURt2睝ZֵkZֵkRkZֵkZֵoxUU{:lkZֵkZ֥J+ZֵkZֵk|ʪO7~߆kZֵkRJֵkZֵkZַ͕h~w&}kZֵJ+ZֵkZֵkZ2G0'I ZֵkZԩRkZֵkZֵk|rmj?^kZֵJ*VkZֵkZֵonM?M^kZֵ*TRkZֵkZֵk[㝩-Oֵ݊jTZֵkZֵkZֵk[_o):Oֵ*TRkZֵkZֵkZ9#hjTRJֵkZֵkZֵkZ)J*VkZֵkZֵkZչ6?7𯶾*VkZֵkZֵkZܛ\u/i躄kZֵkZֵk]1[i>DvkZֵ^Wpߢ뼞d L>^_ I$I$I$[WI$I$I$I$I$?tyvI$I$I$I$I$Ly#e$I$I$I$IИ2A$I$I$I$gZL<$I$I$I$oJA*{ә-$I$I$I|$QsʘO$I$I$#lt,2ɟ$I$I$d#y菚2QI$I Jmf{#.yd%9I$HC"SzDbrX ^C$I$Sݢ+@7$I$8C:!a>{8_C@$I$hQ:[/aψȀ$I *Qs4,23u$HR:s\?lTG$$Ƹúz-bz Y-I$B{V6 eÜI$9*P`QKÎI"ꊺ18Iw_񂮶HF=X¿]AL<=2G((|\ºPa۠Q !EVº?T|TN5`S 9⊒i0ǟx\ tлCx yX.rGG ;QG\RsXƺ(<": O8a8]a0jr=G0aPsQ9qX\^-uՆmucuC㸨x,0ew]j1Uσ!T*pqRxÌk1A:9jE<{ 2yPT(9]Xaq\«1aNnQAuӆTs(08gTt:Dk1Ey*}uE]Ps0ʺ 늡ܡ:]tuJ5u(;9c^0 1ĒIPP= W& 1$Iq'6qcXC Y$F>*_oeTCԮI$KSpӫ$SI$EA 4}pAQ.qs`H7tI$I$J?۫(4u種Fm$I$I$Ai P:Nɶ۱I$I$I$I)m<< I,I$I$I$H"(Ȇ$I$I$I$I$:8\$$I$I$I$I#=\I$I$I$I$I$8(jI$I$I$I$I$I$w I$I$I$* !1AQaq 0@P?k8/Ϝ%>8;Gs]w5|sXE4#ҲxJ9-z"""""""?#lre.y;ga˪"""""""""""""gDv۟5DDDDDDDDDDDDDDEaI#~gLZ?>b_MLm}@Ab""""""""""""""""$ 2jO>pb ,DDDDDDDDDDDDDDDDDE=,5" '. qgIAAb""""""""""""""""",^'A=M| DDDDDDDDDDDDDDDDDXXS0lr"""" &_u]<y` """"""""""""""""""mcs?#:iAb""""""""""""""""""^w~.;~ADDDDDDDDDDDDDDDDDE7?fy|{;xDDDDDDDDDDDDDDDDDDDDDDDDDDZo_7t:m1DDDDDDDDDDDDDDDDDDY!_?0tzN""""""" """"""""""""""""""-i`~DDDDDDDDDADDDDDDDDDDDDDDDDDE;uvN%6툈N;@s{b""""""""""""""""""""""""""""q/O<}o+1:4 \""""""""""" }=3{Lx,DDDDDDDDDXVuvODDDDDDDTlu|g" 3yolv|.#(&F6v숈 -K˳φrԈ Dk~޸)`xDDDDDDDDDDDDDDDDDX px:穯A/oDDDD004^  `.D|^~u/;xow>=3osQ숈Fq[{xw&m\ϾtRs|~5v(~DDDDDDDDDDDDFqn/owўkf|s1\ߌ7lDDDDDDDDDDDFqn7Fj7|NIݧ""""""""""""#qn7]&7ys5z:"""""""""""""#qn7ۇf|%""""""""""""""7q\~:;is~ }"""""""""""""#qn7DDDDkfsc76n7O.~xqb{v""""""""""""""7n7xorDDDDDDDDDDDDDDDFqDDDDDDFn7uȣ"""""""""""""""7"""""""1qܝPVWQn7Wɿ_Nꈈq[[$q\DDDDDDDDDDDDDDDn7DDDDDDDDDF[""""""""""'k-n78q%wf""""""""""""""""7DDDDDDDDDDDm;8ێ""""""""""""67DDDDDDDDDDDDDDDDFq33pn"""""""""""""-=Q˛q3suDDDDDDDDDDDDDDDDDDDDDDDDDDDDDF5,""""""""""""""#qXDDDDDDDDDDDDDDDDDDDDDDOٟ숈؈툈S=1{o>Ȉ\Xof"""""""""""""#q興DDDDDDDDDDDDDDDDfcȈn"""""""""""""""#+g DDDDDDDDDDDDDn70DDDDDDDDDDDDF""""""""""""""""3n""""""""""""""""3&{|uDDDDDDDDDDDDn7n7a߲""""""""""#qDDDDDDDDDDDDDDDDoj"""""""""#qn"""""""""""""""#s'sg""""""""""7DDDDDDDDDDDDDDDn)n""""""""""""""""!؜?hn7]Q}n6NDDDDDDDDn7"""""""""""""""Sj""""""#qF"""""""""""""""yTDDDDDDFqDDDDDDDDDDDDDDDcc}۱޽ޟOqn""""""""""""""5ƻ>r3<n7DDDDDDDDDDDDDDl̺ρYq9ϞwDDDDFqn72|&㓮tn7""""""""""""#eׇgլisQn7DDDDDDDDDDDDE:|Dn'Onx}7~n䈍qn"""""""""""#q\^pzWߟgqFqn7f,n}>;o4w2tx^qn"""""""""""#w1wҴf{o7wCxo{ۍqJ\Wt_s7Ysˏ DDDDDDDDG7=ge=3?;82xyLE8p"""""<2g6_O:g -qnz,zG${PGvfwVǿgӗ)!1A0Qa @qP?iptx3uIeb{tc7rzrϴ5pU?))Pn}К vƈ(}]-zZ|>\G5ɪPz uh}45p=_u|-gMϬAAAAi=5p^P&!]. 8 ~0?6߄9G霽t     dCxs1Wz1hpד85/^s>      /[,q4z/'$q܎S/C 54z&'ϲVuNRtzʁ_^      " GrMN5Øn1suj>4f[       ,S3LD#b__9;|(Vx 㦹eAAAAAAAY0t ep    ,,  ,xJR)JR)JsxO~>TtO@       %R)JR)H!g\Lpz'N ~AAAAAYeAAA2YJR)JR)JRY ǣoO ϴADAAAAYAḀ)JR)JR)JRbxκoۍö    ,  fR)JR)JR)J+?C53AAAAAYdA])JR)JR)JR+S[GDDDDDDAAAAAOJR)JR)JR)JP5kY|>""""""""""" ,,)JR)JR)JR)^興 &R)JR)JR)JR/7 )JR)JR)J^ )J/ryuȡ1 $$$$0 0 0 0=gȄ=AA B!BY|=eba!B!B!x )| 0>!!B!B!CĐRa` B!B!B!!YJRpk͎"!B!B!d!,ҡxu5x!B!B!C8B,)JR nz6\sHD!B!B!B@,)J_ gBuF!B!BC >,,)x4*+|zr}P=!B!BBYeYe)KcZavȄ!B!B/!YeR)J^/Fqu{i!B<Px!YeYJR Cw9:~B!C0 ,,YJR(9Wck1tGOo4.!CYeYeYK)JR3'eyuqB<B,,,)JS"z%__|!BYeYeYe,)\>YS0=1|!BYeYeYJW.z`/wsB!y`eYeYeY887A~CB!@ ,,,/#~C!o!B! ,, )DG_9B!BYeYcD5^3ߧɊ:8B!BYenQY_!B!y,w}#WR4h<!B!e.Tr=~0!B!he]wOP<| !B!y(Zm+N!B!@Q W~gdD!B<0uU>w:A{`{>F!BMf1BG=V {{tq K30 19^=kGPKR\images/crosshair.pngnu[PNG  IHDRrP6bKGD pHYs B(xtIME _^.IDAT8SjAES$h ]L*tUZC EJ6W p *4w.yiNK@y*bOx3,3TCk=nuݹj.6 jڣ8S"")W.#*;!R|cc""˲N[k=!"2 mHD9g_d2y nw@@f)!1H)_T*Y/ W\.EB&8Ӱ6""4am~B*\""ضb! ;!)+Q x{Rza9[VjMT*eY}9[k93Ms; mM>C4 g rIENDB`PKR\u4NNimages/badge-style-b.pngnu[PNG  IHDR6HFIDATxֵ@@?J&oX3^}]%j{B: t@ t@Bzei~XBx}ڿn?ن~\t߈~^'$I8EQTp8Lv;Wx( WJJ$J%%J"QJJD*HR"%*zoug'fg;w c zE!$||9*IIIN̔XNB|#:*:%'$EUSrBUgݹٔP5TVs.n/ycc9U:::(97ݾ&ʒS|'9!^&758jINE񽗗)))'?B%Gߥ;uќ{#~nqqL$'^r̟Hrrr d||\>??n;999!9jrH~~~.d_[[WBѭLJh=ɑWxJN@#Kn/{D1\9; QHn/Ã˫ɑ; HNEBr{dbbB%׎ Qw/..vVrB($'K챔M1{.;o+++!JN@-$=>??GShPI^__/EEE6CrGuB(mmmͮ0_ؔ!=|ow++++_766;HNE׽ݭjtO^}yyۛ9Niii%'cwn-E05600`Ԩ[[[R^^~uuEɉK(zaaUg=##V5R@JEE:!sss?nh0yq Pt4t;f ßJh7kJN E5E ^4*y~:4'''i(CpNjPeLNNLuvvJOO‚h@HNE \#EA꒼Eqs_:\@K@aZ@P kͮ2- tK6L>O6.r0.ݓtw0,b(Y}N?^KpsݡZn<{Ё.'5qrE~xWۓNB%t:OɡSNR^DU(+Gϖ :%Yh)Q:>Vxm/oЁ=}t|TЁt%g'p6 -/>Ը>NHCzo*_}ֱ:SR?3j36OZХht ^K宺GstiZn/n{_<Ԯ6ڸ7> t}ykeَd+݃tǼܑ|]Z$Sp ttyּ7:K.]>}R_~:|}+;@ @_|^}{W:ЁyEekt?/>ht/>/>hta^Ls5辛Ftorh|Λek[h ~Ft`.]:ЁttЁtW##]=eW:ЁN@:ЁN@tЁtЁt>ttt?tt:tT[ae3.*e@^e.X'>ôC }%:O9W!{`]{t (w_!HXCS[ y'vD!B: tH%t@!h :d: t@!?B2: t@AB B:d: t@!B: t t@CB2: t@AB B:|yZ:ܧz e{ TO9%/uuq .yoE7+7z^m\dy{rB_e ]@``9 %44pOci:ֳv7S__5ultSuJ@i.^YH~(aW3bش˸,/ߗOA:,m!ǵ^J Z@H h KCgěQ'ƱXs c\.{9\׀^DLP鷍O >fٷ;?!و}^% h(ܽ)/yzoDQ/TJ"%DA@@  @ R@%Ep}_; sOiv̽6}¹qJ...~K =X%ƶ}|mmmg6R2(+i({?;;+ÚT fffsO???KQQ n Л &Ύ$$$`S ϑ6:44T`ާJP+r,Y7!~aټC_u h+--///ĠwtCOv]ߟ{Yt{)݄Z绻;IJJuB"rssC***$88X0UUUIee%q|\$00P<Ƥ?==Ivv6;JY"""9==|^_]]I&듨(Gp/&DFr @­Ǡ 9??'װ׼6::ʶ0744%h+8т@l!`^)++C_q*v?^ⴴ4ߗdT7~Y>|>T ּ݄GGGRPPϒ.gggGjjj?pW: B"q1EMſW[ eii0Hdd$ 2^ OOO#PssspX+Awun݀?@DZRdpp6Kbccq 2 1aq?9<<ijjoeeeI{{;ι65<>>}---L*yyyAG1??/Hp󈰕M %D <,%jraFrrrΦ=N#{7^tguK5UfW/[LK$rZ-'zg{C" f= 5gwk".͓,7?O1klhgG(#񑜑1.u͗EolYT:LH>cD:*O3NH}~&-1! Fxe7_Cg[~0D$Nu-k*RdP[XodtruWv97$.wC!z3A8)+,D#)r*,ZK{\@5?<<(ͱaHS _XꛛKd*SGFS9]!%o68 9sBQ'ܱF VZn#/G߹}Fޜ:FVģMJzS/8TtȬ ⍵߻̂rf׶H ?M hXʸ6y5xS![pVTMzD0Hl\|i3TpZZ?b>(⮸Lh""t1ŷh'lp]]aןE77)DAn ADHIH No>F+"s^^NX驮!uOwـ ϷD/xRet*ȤB;}wc%#qS||~yyqNN9M?On"z(ы"DYc97\2=[9y"x%zq1IƎ )I.Fm'L܁D.J"UeIRc{ʝ$svLv; )?fQITKYN$G ٭F/D/͟GCwYB N'|r]x]__+™W* QANs়`0ޒ.bOxx@rf E˞mto^~#үWWWiGRşϻ(K}y&D7m-Q ,rOS @E2lg 3d`F#sx}}N@^qC'\'u DNY6ʬ񑫱g+򦻿(v:Vወsm xB: t@wB: t@ t@B:BgZ IENDB`PKR\s>eOeOimages/wheel.500.jpgnu[JFIF``C    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DDDDDDDDDDD|_.σ98+*Ի޹umoj"""""""""""""""""""""3}^?Sp2-2*3JJT]mt:^Rҭ-2-223JT*.uDDDDDDDDDDDDDDDD|8:we*֚fZfZeZffYYZViuwv83t+ZiikM-*VVYUVieeYWW^7ygfKZiiii]M-*-2R2L+4J2Dзn}} s"""""""""""3~tiUZZKKZiiikJ*M22LT-4LW+5~∈c~-+*KZiikM-2-*-22JT-4Rй\.W+xy>^""""""""">\|7)YeeeZZKJ饥iUiUViVjefYZZk*5嬮W6""""""">X0++,KZiikM*ʴ**RLTtM2erk*.W3Y_{x_?泜SJJ+*ҺiiKJ3JJLL-4YY\Z+W-e~҈/q*M+J-+,ikM--+YYYViefYTk2rW+.Tku9R"""""#\^>iZViZVYYiUKZiiikJ-2R2L+4MY+Y\eY\WGo""""#uo ZUYYYYYeeSKKZiUJ4*RLuJ5rk+rW2嬫{VN.$5+*,ԬҲ˦4*+45J2LW*5˕Y\er~b""":eVUjVZiVZUiYfҺiiiUiZefYZk*5reY\5X-f\q|^""#㞷QLTJ2+J+-.ZZJ3JJL*՚ \%Y\˖˖/כh~LJJҭ2M2J+-.ZZKJJLԬ-4Mer\KY\erk+.̽ǫ}Hu8iiViVjVUZUYYiUZKJiiijefYk+rW+Z̹k2reY }xDDuΥUUUUjjVZUit֥ZZfYVj\Z̹\̹k+Z̹k2嬮f[s2M>RYYYiYYiYVUeZJ-3JJL).ZFW+.Z̹k2˖.̹kysUUUUUVUiZVYu444M2Y\W+Z̹k2Kk+f^juwEiUUUVUViVZUt44RBrW+fk2ˆ.Z̹k2es5t"eiiiiijiUiZU4ʴRB嬮W3Y\fk2ˆ.ZW3X\es5/infffVVYYYiYVYeeZKLT.Zs5Y-f\reY\es5.fYOrxLLLҬҬҬ+4444,+,֚UieYQs5Y f\reYk+f%Y_g|oUUZeZeZffVYYYiViUZҴ,W3Y\fes5rW3Xk+r&;)IiiZeZefVVVVfViVfW-f\peY-bk+&eX-fkeq5 ?**-23JLLҬҬ,***+*Ҭ.Zk+.̹k3Y fk+f%Yk+Mes5t{Ok<&iijUUZefVVYYUUVUk+W3Yk˖5ZĹk-f\5feX̹kYKLҬҬ**4ʴ*-223JLLҬйkˉr&Y-f\5ˆ5Z̸k2as5 5ViiiUUZeZfVYUUiik-f\5f3Yk2˖5fX-f\}WEĵM**3JKLLҬ*+4ʵM*** fk-b\eˆ.ZW3Ykˆ5r&W/<6UjViViiiiUUiYYV.fs(\es5̹k3Y\eq5W3Xk2k+3K??|,444ʴ4ʴʴ45*ԴR]M22MMs4KW2˖.Z̹k2b\re]O?ǓZeZeZeZZfffVViYu.u4555,e%h+eY-f\peY-f\MeuGQzߞ**-R2+M*+M+**ԲR2KJSSB\5r\reY-f\eq5W_^qy֙VfVVVffeiYf.u+454,4).e3Y+.Z̹ks5reY-cM-2*J*J5**R4˩K]44454K%̢k2IeY-f\˖.ZĹk2FiVjUYVVjYu.+5Y+4ʵ+54,).e2h\˕T3Y\˖/i?xQ~զfZViYie]Mk7SZM2Zjijjijhj\KE̤W2s4.eW2Oa㈈ef..+5u4ʮViYffrSy'ለ:Qu5Y+4ʴ*JJ55kvWWݽ_rq94˦YYV~s|c88b""""""""""""""""""""""1\N{Mr]eYiKuy|r8'P@ 01!"23%NNNƷjl j^syF !S}r@4O27i)ﶢwf`a @ L d,Hc!pE&Xgm?4D0K>g7Tqc$%!"PCqSC8YT3{\,̽Sk f=-3]zs{7fO(|2I7@}2v^rqi;TVwgh;;^/<_xy\OR?;B"*Z x׳8͚1!ףcs}0?_Kf꯵_Ni 3WcTR0bC Yz u~rs]={`@ͿԸRrtk釬@5+W9.\ŬT-곾8FL#9D>nxr}Z"bV$FLU:ww­FEpDx9F`'ikLj"rP>u}'~TL ) 龷M=*ӅOoJxh>};KP*1"pΙXC#ENjw ^z]T B'NerB]9F /-P!10@Q "A3q2BaR?d~fW!_5a^^b/|^|\$6 i^Ƹ' ;0{͸{i[qm*KN:w7jKQEN.(SZV m۸7=0o.b _|Y88W);7F8NŌqN Ҹ7v"@K&WY֜-I]6NrrdiEq552R\w :Sv&ɖn:/rR˼N뷽O4),"gv9RXURZjt*=EZl**-׈[982Լ8P& s#s$H+"cG=46I@=_16W>Kդ?1~>/}_ϿKģ:+M# #U}c\sO Y镀мsk :g|NsU \ÜNlg[3Zjᩯ (B\z7_|ZޙzU]!BJ,->b}f[\S4RXupפvR~bMCJ,**-%71W*]q p+_1H qD`Vcvbnkݓ۪bbjkCj$.(W~#lmAC&wJa&&xqp.RL TUѾE(ÎR\ NhvtGA|YtupR\UbT"o 0AMH7\ŀ*Es_/!1P2@"0 ABRaQC`q?%ݩl)׳kv:_ם/k͓5KY8xP/io;I*?IYO{֚S{6jĘu'H/iDq=sAHm \btz{m;v⦠,=UKt͢ߣTտi&:[.Xx(.ma$154]Ub2խF&~"^ ƙOkuz[jGdS1c-n|Km@3bXxK#m;f<ޑӑڭW] 98ݣlH0Ž/9ǖ:~ǰNyoūL?~ǚ?j>8hF?[)ڝH ؎> '=&J4磗 —n}zG>}zG>#sсA&mڭϯ+΍18>6^~6ΡG/>T)X0s紗\{he5Ix`Rw^QPE7I׽ڤUu1xkPE7I׹ڥUu&y7b-ZR{G44߀V奺jQ3*kM~~Oq#yN"e٩oV 69i/dW+y1;њCw5!1PQ"0@Aq 2Ra#B3br?NZaͩ870Ɯ sncM~\O(ue77tL9ewYG+xo/y ˥u<=/´Eki|.oN ջ0ѯ-S4ްz[W[!*# 70ͳ/GaGϵBv|HS}'{B5=ҝ/JW]ғC& y)5ohMn rܱ&Oznh)Pb.ND ;@"[㌊~o HraMOƑplf aMsLfTL>hPDY%2y&B왌SdNa $9س:i8kK)ư^!-a%})it8"z+VF 2R}G }caPha(=CDU8c#IWALm~$OSpeF'iD'd*9(nCe'Ԙ zq*!1A 0PQ@aq?!4[3myY>z9?????p: vs>QϪBSr=/.~mm[}J*{OC{[_6''hYcFW/ d#$YΏBUV؇'W_͝ǟvZkWܧi?C/ ¶6|//ꪪ9/cj*yֵy}%x^U[e񟿙]Sj*SAt+Z%UxUUUUUsWWѯ ª'^WUUUU[W/؛˒z-WUUUUUUVݵs[ફ¯ 7kWUWUUUUUU}4ն-^UUUUUUUUZ}Ѫ:Ī8[ª9{k6UUUUUUUUUUVYjˆSꪪ e,\=ZoUUUUUUUUUUUUW">/[SgUUUUUUUUUUUUUU[fscz UUUUUUUUUUUUUZ_AjנUUUUUUUUUUUUUUjֽwUUUUUUUUUUUUUUUFkxk|ZֵkZַUUUUUUUUUUUUUUNַíkZֵkZֵkZ𪪪Ó9ZֵkZֵkZֵkZ񪪪767LxkZֵkZֵkZֵkZkxUUUUUUUUUUUU]#չ#5kZֵkZֵkZֵkZֵ6fsmRkZֵkZֵkZֵJֵoB9kZֵkZֵkZֵkZֵkZ UUUUUUUUUUlrY^XֵkZֵkZֵkZԭkZֵ:99>q)їkZֵkZֵkZֵJkZֵEUUUUUUUUn*t2??ֵkZֵkZֵkRkZֵ:39yɭkZֵkZֵkZԩZֵkZª_})ϙZֵkZֵkZֵJkZֵoUUUUUURXByI; O_LfkZֵkZֵkZԩRkZֵoUUUUUUowֵkZֵkZֵ*VkZֵk|ƪK[o)'w9e)&cZֵkZֵkZ*VkZֵk|ª#דyOxֵkZֵkZԩRkZֵkZUP*z6JBYyYU{kZֵkZֵ*VkZֵkZwUW(;UuRkZֵkZ*TkZֵkZֵ*}﷛ ޝkZֵkRJֵkZֵkZַ͌7[OfO ֵkZֵRkZֵkZֵkZ2:)g5ֵkZֵ*TkZֵkZֵkZ*K[o)#٧/0%^_ѭkZֵRJֵkZֵkZֵd'-,6<ֵkRJ+ZֵkZֵkZֵ8J: 5Oᣮ~?dU FY{5kRJֵkZֵkZֵkZ{}UUFy>=5J*TkZֵkZֵkZֵ ~׽&'}+Ysۿ֥J*TkZֵkZֵkZֵ/6RpO{J+ZֵkZֵkZֵjKm GVkZֵkZֵkZ[o)#'IkStro/~ۤ?鹓ZֵkZֵkZm'ߡ?aS[ 6{;n"X\kZֵkZy6n9 Xlb˓y:ކl|Xt:;Ϣ;rU7;_ K;W_~TyvDLy#eИ2APgZL<oJA*{ә,|$QsʘO#lt,2ɞ d#y菚2QJmf{#.yd%1C"SzDbrX ^JOSݢ+@78C:!a>{8_C@hQ:[/aψȀ *Qs4,23uR:s\?lTGdƸúz-bz Y-B{V6 eÞ9*P`QKÌꊺ18Iw_񂮤f=X¿]AL<=((|\ºPa۠Q !ERº?T|TN5`S 9i0ǟx\ tлCx yX.rGF ;QG\RsXƺ(<": O8a8]a0jr=G0aPsQ9qX\^-uՆmucuC㸨x,0ew]j1Uσ!T*pqRx k1A:9jE<{ 2yPT(9]Xaq\«1aNnQAuӆTs(08gTt:Dk1Ey*}uE]Ps0ʺ 늡ܡ:]tuJ5u(;9c^0 0%PP= W& 8q'6qcXC P>*_oeTCԮSpӫ$SA 4}pAQ8la|/dۯќWٮDXc^춽>d65^7i5Π6>.qs`H7p ?۫(4u種Fm i P:Nɶ۱)m<< I "(Ȇ:8\63=\8(j@ * !1AQaq 0@P?k8/Ϝ%>8;Gs]w5|sXE4#ҲxJ9-z"""""""?#lre.y;ga˪"""""""""""""gDv۟5DDDDDDDDDDDDDDEaI#~gLZ?>b_MLm}@Ab""""""""""""""""$ 2jO>pb ,DDDDDDDDDDDDDDDDDE=,5" '. qgIAAb""""""""""""""""",^'A=M| DDDDDDDDDDDDDDDDDXXS0lr"""" &_u]<y` """"""""""""""""""mcs?#:iAb""""""""""""""""""^w~.;~ADDDDDDDDDDDDDDDDDE7?fy|{;xDDDDDDDDDDDDDDDDDDDDDDDDDDZo_7t:m1DDDDDDDDDDDDDDDDDDY!_?0tzN""""""" """"""""""""""""""-i`~DDDDDDDDDADDDDDDDDDDDDDDDDDE;uvN%6툈N;@s{b""""""""""""""""""""""""""""q/O<}o+1:4 \""""""""""" }=3{Lx,DDDDDDDDDXVuvODDDDDDDTlu|g" 3yolv|.#(&F6v숈 -K˳φrԈ Dk~޸)`xDDDDDDDDDDDDDDDDDX px:穯A/oDDDD004^  `.D|^~u/;xow>=3osQ숈Fq[{xw&m\ϾtRs|~5v(~DDDDDDDDDDDDFqn/owўkf|s1\ߌ7lDDDDDDDDDDDFqn7Fj7|NIݧ""""""""""""#qn7]&7ys5z:"""""""""""""#qn7ۇf|%""""""""""""""7q\~:;is~ }"""""""""""""#qn7DDDDkfsc76n7O.~xqb{v""""""""""""""7n7xorDDDDDDDDDDDDDDDFqDDDDDDFn7uȣ"""""""""""""""7"""""""1qܝPVWQn7Wɿ_Nꈈq[[$q\DDDDDDDDDDDDDDDn7DDDDDDDDDF[""""""""""'k-n78q%wf""""""""""""""""7DDDDDDDDDDDm;8ێ""""""""""""67DDDDDDDDDDDDDDDDFq33pn"""""""""""""-=Q˛q3suDDDDDDDDDDDDDDDDDDDDDDDDDDDDDF5,""""""""""""""#qXDDDDDDDDDDDDDDDDDDDDDDOٟ숈؈툈S=1{o>Ȉ\Xof"""""""""""""#q興DDDDDDDDDDDDDDDDfcȈn"""""""""""""""#+g DDDDDDDDDDDDDn70DDDDDDDDDDDDF""""""""""""""""3n""""""""""""""""3&{|uDDDDDDDDDDDDn7n7a߲""""""""""#qDDDDDDDDDDDDDDDDoj"""""""""#qn"""""""""""""""#s'sg""""""""""7DDDDDDDDDDDDDDDn)n""""""""""""""""!؜?hn7]Q}n6NDDDDDDDDn7"""""""""""""""Sj""""""#qF"""""""""""""""yTDDDDDDFqDDDDDDDDDDDDDDDcc}۱޽ޟOqn""""""""""""""5ƻ>r3<n7DDDDDDDDDDDDDDl̺ρYq9ϞwDDDDFqn72|&㓮tn7""""""""""""#eׇgլisQn7DDDDDDDDDDDDE:|Dn'Onx}7~n䈍qn"""""""""""#q\^pzWߟgqFqn7f,n}>;o4w2tx^qn"""""""""""#w1wҴf{o7wCxo{ۍqJ\Wt_s7Ysˏ DDDDDDDDG7=ge=3?;82xyLE8p"""""<2g6_O:g -qnz,zG${PGvfwVǿgӗ)!1A0Qa @qP?={8Џsߴ uv<G˘ L oT?u?P.nE 1\GG    }/K>k}N ̽jAAAAdA'=?Cu"6u:AAAAAAdIZ8;x=7:atyv`     ,^Ck=O~.=Ocв      ,%3rz6t=dUfZsK,      " 'C$ 't;CteYAAAAAAYd/)Оz\=.=k,,     Y6 N%"WYeYdAAAAADt>/y`@t;ht;dYeYeAAAAAExJR[x768^AYAAAAAAdB_R`˓"r , ,,     <e,RRCu-DCj}`  ,     )L)J^(.잌˹>W2a{  ,,    <R R>_c=AAdAeYAAAA/)K)x Rd 7G{~wΞo   ,     _^S)JR+Tg?o!@^AAAAeYdAAAAe)JR)JRuӟyWh    ,    Ye)JYJYJR+tgv|LAOAAAAeYAAYe2,)JR)[<9 eg^'QW`   ,,  ,xJR)JR)JuWYzw"3zIr     ,  ,| RJR)JR2z(6034M۾2" "     )JR)JR)JR $4MlM}_   , )JR)JR)JR)^wߔfo   , )JR)JR)JR gs_uqFgq""""""""""" ,,)JR)JR)JR)^a35AdL)JR)JR)JR ^o=b""""""""""""<)JR)JR)x+ܽNdd$$$$$$$0 0 0 0 $|YB B A!B!B,tWv!aB!B!x_6=`GT!B B!B!B!e @t5=1/q!B!B!B ,)|Jם5<`>oB!B!B> ,Rʀ0tzW{؄!B!B!C8B,)JR w7;DǺ!B!B!FBYe)JR;=~<C!B!ByYeR/);?CL:k!B!B,,)J^`xbzr>9ʙm!B!x9x!|@,,)JR)|@" aH#Nyxno$B!ByAB> YeR)e)J_/G_Pc!B!xx!|@,,)JR/x jN}NU.{ϹB!y8!C,,)JR/,tc>@>÷oX!B!|`YeYe,)JRp SMw=7Mόe. =u!q7BB<YeYe)J嗻8NLp|!xW^W!y<!(YeYeYeRWؙWIt $n=S !BHeYeYe!BYeYeYe|fw炽^|h}u;^x/B!C<,,,;JGwx[y<!B<eYeYe Uw _ǫ ]Ahw.b:<!B,,.^A@=_~I-N剻GPyi!B!(YeYgYZ@߷ x|QN!B!y,E//uۣt]8(c39 ӓ{]tN{$?'!B0Ym_J]9e;uN9΁4`B!Cnkrr pNw}z6('^zs[^!B!`xǼ8ztysru^^_yJ^Kz9zf{k7!B!B&^\N"tXFz`~p}kEWW7Fe7' in!B!EF7~ϔ>g2ΣU'"+G aޙLgSu!Co+FrG Gk3_^;oG%W 1G^;ӼDŎ`V^3ab k NPKR\LV66images/transparent.gifnu[GIF89a!,  ʺIk);PKR\΁images/ion-android-cart.pngnu[PNG  IHDR<<N%tEXtSoftwareAdobe ImageReadyqe<"iTXtXML:com.adobe.xmp ƑIDATx/ppuadbEH1A +ԄA,Zf[4H$d2iPL&,Lvc0+}{~w{-.K&FF^`ڳ4MpoCMgCt:=uv'BM/0~&y9'l LӃR1N4kEI\(DZQŦ;UXiElB( 'a~|F=ZvLdy hoZP틮>ElQz֪wA zW"Eؿ/&O*QEl)hZQV\8vf(9ײxcu׃JPA>٪g A2 W;q=QXI4Ga]M=(6tr أC,Vf,p"[/mѯep4UlN7Xz8@4@4@4@4@4r 0c36 IENDB`PKR\xkimages/vc-icon-50x50.pngnu[PNG  IHDR22?iCCPsRGB IEC61966-2.1(uKA?%>Q#m,4 jD$q V (6 AQm4s&3|۝awl6]߫,,.)ghb%lp2DMΊ7VhPQx\ZNx[KM§N].(|k2X(z([ő_&t*Vc5J / L#] ndE|OYUe(J$9zLb\jG^hx2ͷ~plAhY:#\d}X}.Zd7A .n=s|u+݃9߾ Yg1Ӂ pHYs  #IDATh]UUHY6= ZfzyP,_EAj1`ӋVh~D/R2Fq< jZTKeg9s1޵ZukTPAT*Ix3o)u4G̬~uc- xxXlf)_&4؍ MAL LvK8$U{i|3[D3C|E뤍] X 8ݙD߮2sU<$@&r* I|^Sb =* 8af#x}&\nfF7 :}%}#Gh\:0#6I NqNG@\ lFv`יl^w . T[ ;{#3{>W m`9M`\,-ۮ qaU\ /mb@kZXmܟ_ )z~ϢQ@%wǁfv&E W6!*イ5ͷ [')+rpͣW+׈H,~6p#p ~(mrUj{eY!:1fU鮲f6)b`uE#?gYxɷC>F߮ˢqxwO韬XJ[D?$M EtYi:`Lojeeu7, Ԉ`<&p0 OaQzFak!a~ndYAȓXgf/d b$ef0<efmZ` Ȋf\Lm<gp 6}պ+[$MMӕԀ+ s̊($m`A0C`qIudf'qAR Q9ݿH'Qj| xGH] Q3{X9z\I%R*a.Iu1Ww\$%GKq;s-̖R#Mz}(9K?{,ĥ)U@ϭnہ 3bRt3nf qy: d,qP q=$LZ};L$ʁ$aZ ιDR]) acW_4 .n 0L\d} g#0 XnfVf!KIfR\_V4 ]D]0Ll >Ox fvd..$UK*ޫ *ާ IENDB`PKR\[vG-G-#css/spectrum/redux-spectrum.min.cssnu[.sp-container{position:absolute;top:0;left:0;display:inline-block;*display:inline;*zoom:1;z-index:9999994;overflow:hidden}.sp-container.sp-flat{position:relative}.sp-container,.sp-container *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.sp-top{position:relative;width:100%;display:inline-block}.sp-top-inner{position:absolute;top:0;left:0;bottom:0;right:0}.sp-color{position:absolute;top:0;left:0;bottom:0;right:20%}.sp-hue{position:absolute;top:0;right:0;bottom:0;left:84%;height:100%}.sp-clear-enabled .sp-hue{top:33px;height:77.5%}.sp-fill{padding-top:80%}.sp-sat,.sp-val{position:absolute;top:0;left:0;right:0;bottom:0}.sp-alpha-enabled .sp-top{margin-bottom:18px}.sp-alpha-enabled .sp-alpha{display:block}.sp-alpha-handle{position:absolute;top:-4px;bottom:-4px;width:6px;left:50%;cursor:pointer;border:1px solid black;background:white;opacity:.8}.sp-alpha{display:none;position:absolute;bottom:-14px;right:0;left:0;height:8px}.sp-alpha-inner{border:solid 1px #333}.sp-clear{display:none}.sp-clear.sp-clear-display{background-position:center}.sp-clear-enabled .sp-clear{display:block;position:absolute;top:0;right:0;bottom:0;left:84%;height:28px}.sp-container,.sp-replacer,.sp-preview,.sp-dragger,.sp-slider,.sp-alpha,.sp-clear,.sp-alpha-handle,.sp-container.sp-dragging .sp-input,.sp-container button{-webkit-user-select:none;-moz-user-select:-moz-none;-o-user-select:none;user-select:none}.sp-container.sp-input-disabled .sp-input-container{display:none}.sp-container.sp-buttons-disabled .sp-button-container{display:none}.sp-container.sp-palette-buttons-disabled .sp-palette-button-container{display:none}.sp-palette-only .sp-picker-container{display:none}.sp-palette-disabled .sp-palette-container{display:none}.sp-initial-disabled .sp-initial{display:none}.sp-sat{background-image:-webkit-gradient(linear,0 0,100% 0,from(#FFF),to(rgba(204,154,129,0)));background-image:-webkit-linear-gradient(left,#FFF,rgba(204,154,129,0));background-image:-moz-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:-o-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:-ms-linear-gradient(left,#fff,rgba(204,154,129,0));background-image:linear-gradient(to right,#fff,rgba(204,154,129,0));-ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";filter:progid:DXImageTransform.Microsoft.gradient(GradientType = 1,startColorstr='#FFFFFFFF',endColorstr='#00CC9A81')}.sp-val{background-image:-webkit-gradient(linear,0 100%,0 0,from(#000),to(rgba(204,154,129,0)));background-image:-webkit-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-moz-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-o-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:-ms-linear-gradient(bottom,#000,rgba(204,154,129,0));background-image:linear-gradient(to top,#000,rgba(204,154,129,0));-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81',endColorstr='#FF000000')}.sp-hue{background:-moz-linear-gradient(top,#f00 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,#f00 100%);background:-ms-linear-gradient(top,#f00 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,#f00 100%);background:-o-linear-gradient(top,#f00 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,#f00 100%);background:-webkit-gradient(linear,left top,left bottom,from(#f00),color-stop(0.17,#ff0),color-stop(0.33,#0f0),color-stop(0.5,#0ff),color-stop(0.67,#00f),color-stop(0.83,#f0f),to(#f00));background:-webkit-linear-gradient(top,#f00 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,#f00 100%);background:linear-gradient(to bottom,#f00 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,#f00 100%)}.sp-1{height:17%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000',endColorstr='#ffff00')}.sp-2{height:16%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00',endColorstr='#00ff00')}.sp-3{height:17%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00',endColorstr='#00ffff')}.sp-4{height:17%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff',endColorstr='#0000ff')}.sp-5{height:16%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff',endColorstr='#ff00ff')}.sp-6{height:17%;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff',endColorstr='#ff0000')}.sp-hidden{display:none!important}.sp-cf:before,.sp-cf:after{content:"";display:table}.sp-cf:after{clear:both}.sp-cf{*zoom:1}@media(max-device-width:480px){.sp-color{right:40%}.sp-hue{left:63%}.sp-fill{padding-top:60%}}.sp-dragger{border-radius:5px;height:5px;width:5px;border:1px solid #fff;background:#000;cursor:pointer;position:absolute;top:0;left:0}.sp-slider{position:absolute;top:0;cursor:pointer;height:3px;left:-1px;right:-1px;border:1px solid #000;background:white;opacity:.8}.sp-container{border-radius:0;background-color:#ececec;border:solid 1px #f0c49b;padding:0}.sp-container,.sp-container button,.sp-container input,.sp-color,.sp-hue,.sp-clear{font:normal 12px "Lucida Grande","Lucida Sans Unicode","Lucida Sans",Geneva,Verdana,sans-serif;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.sp-top{margin-bottom:3px}.sp-color,.sp-hue,.sp-clear{border:solid 1px #666}.sp-input-container{float:right;width:100px;margin-bottom:4px}.sp-initial-disabled .sp-input-container{width:100%}.sp-input{font-size:12px!important;border:1px inset;padding:4px 5px;margin:0;width:100%;background:transparent;border-radius:3px;color:#222}.sp-input:focus{border:1px solid orange}.sp-input.sp-validation-error{border:1px solid red;background:#fdd}.sp-picker-container,.sp-palette-container{float:left;position:relative;padding:10px;padding-bottom:300px;margin-bottom:-290px}.sp-picker-container{width:172px;border-left:solid 1px #fff}.sp-palette-container{border-right:solid 1px #ccc}.sp-palette-only .sp-palette-container{border:0}.sp-palette .sp-thumb-el{display:block;position:relative;float:left;width:24px;height:15px;margin:3px;cursor:pointer;border:solid 2px transparent}.sp-palette .sp-thumb-el:hover,.sp-palette .sp-thumb-el.sp-thumb-active{border-color:orange}.sp-thumb-el{position:relative}.sp-initial{float:left;border:solid 1px #333}.sp-initial span{width:30px;height:25px;border:0;display:block;float:left;margin:0}.sp-initial .sp-clear-display{background-position:center}.sp-palette-button-container,.sp-button-container{float:right}.sp-replacer{margin:0;overflow:hidden;cursor:pointer;padding:4px;display:inline-block;*zoom:1;*display:inline;border:solid 1px #91765d;background:#eee;color:#333;vertical-align:middle}.sp-replacer:hover,.sp-replacer.sp-active{border-color:#f0c49b;color:#111}.sp-replacer.sp-disabled{cursor:default;border-color:silver;color:silver}.sp-dd{padding:2px 0;height:16px;line-height:16px;float:left;font-size:10px}.sp-preview{position:relative;width:25px;height:20px;border:solid 1px #222;margin-right:5px;float:left;z-index:0}.sp-palette{*width:220px;max-width:220px}.sp-palette .sp-thumb-el{width:16px;height:16px;margin:2px 1px;border:solid 1px #d0d0d0}.sp-container{padding-bottom:0}.sp-container button{background-color:#eee;background-image:-webkit-linear-gradient(top,#eee,#ccc);background-image:-moz-linear-gradient(top,#eee,#ccc);background-image:-ms-linear-gradient(top,#eee,#ccc);background-image:-o-linear-gradient(top,#eee,#ccc);background-image:linear-gradient(to bottom,#eee,#ccc);border:1px solid #ccc;border-bottom:1px solid #bbb;border-radius:3px;color:#333;font-size:14px;line-height:1;padding:5px 4px;text-align:center;text-shadow:0 1px 0 #eee;vertical-align:middle}.sp-container button:hover{background-color:#ddd;background-image:-webkit-linear-gradient(top,#ddd,#bbb);background-image:-moz-linear-gradient(top,#ddd,#bbb);background-image:-ms-linear-gradient(top,#ddd,#bbb);background-image:-o-linear-gradient(top,#ddd,#bbb);background-image:linear-gradient(to bottom,#ddd,#bbb);border:1px solid #bbb;border-bottom:1px solid #999;cursor:pointer;text-shadow:0 1px 0 #ddd}.sp-container button:active{border:1px solid #aaa;border-bottom:1px solid #888;-webkit-box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee;-moz-box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee;-ms-box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee;-o-box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee;box-shadow:inset 0 0 5px 2px #aaa,0 1px 0 0 #eee}.sp-cancel{font-size:11px;color:#d93f3f!important;margin:0;padding:2px;margin-right:5px;vertical-align:middle;text-decoration:none}.sp-cancel:hover{color:#d93f3f!important;text-decoration:underline}.sp-palette span:hover,.sp-palette span.sp-thumb-active{border-color:#000}.sp-preview,.sp-alpha,.sp-thumb-el{position:relative;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.sp-preview-inner,.sp-alpha-inner,.sp-thumb-inner{display:block;position:absolute;top:0;left:0;bottom:0;right:0}.sp-palette .sp-thumb-inner{background-position:50% 50%;background-repeat:no-repeat}.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=)}.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=)}.sp-clear-display{background-repeat:no-repeat;background-position:center;background-image:url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==)}PKR\<[D<D<css/spectrum/redux-spectrum.cssnu[/*** Spectrum Colorpicker v1.5.1 https://github.com/bgrins/spectrum Author: Brian Grinstead License: MIT ***/ .sp-container { position:absolute; top:0; left:0; display:inline-block; *display: inline; *zoom: 1; /* https://github.com/bgrins/spectrum/issues/40 */ z-index: 9999994; overflow: hidden; } .sp-container.sp-flat { position: relative; } /* Fix for * { box-sizing: border-box; } */ .sp-container, .sp-container * { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; } /* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */ .sp-top { position:relative; width: 100%; display:inline-block; } .sp-top-inner { position:absolute; top:0; left:0; bottom:0; right:0; } .sp-color { position: absolute; top:0; left:0; bottom:0; right:20%; } .sp-hue { position: absolute; top:0; right:0; bottom:0; left:84%; height: 100%; } .sp-clear-enabled .sp-hue { top:33px; height: 77.5%; } .sp-fill { padding-top: 80%; } .sp-sat, .sp-val { position: absolute; top:0; left:0; right:0; bottom:0; } .sp-alpha-enabled .sp-top { margin-bottom: 18px; } .sp-alpha-enabled .sp-alpha { display: block; } .sp-alpha-handle { position:absolute; top:-4px; bottom: -4px; width: 6px; left: 50%; cursor: pointer; border: 1px solid black; background: white; opacity: .8; } .sp-alpha { display: none; position: absolute; bottom: -14px; right: 0; left: 0; height: 8px; } .sp-alpha-inner { border: solid 1px #333; } .sp-clear { display: none; } .sp-clear.sp-clear-display { background-position: center; } .sp-clear-enabled .sp-clear { display: block; position:absolute; top:0px; right:0; bottom:0; left:84%; height: 28px; } /* Don't allow text selection */ .sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button { -webkit-user-select:none; -moz-user-select: -moz-none; -o-user-select:none; user-select: none; } .sp-container.sp-input-disabled .sp-input-container { display: none; } .sp-container.sp-buttons-disabled .sp-button-container { display: none; } .sp-container.sp-palette-buttons-disabled .sp-palette-button-container { display: none; } .sp-palette-only .sp-picker-container { display: none; } .sp-palette-disabled .sp-palette-container { display: none; } .sp-initial-disabled .sp-initial { display: none; } /* Gradients for hue, saturation and value instead of images. Not pretty... but it works */ .sp-sat { background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0))); background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0)); background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)"; filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81'); } .sp-val { background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0))); background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0)); background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)"; filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000'); } .sp-hue { background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000)); background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); } /* IE filters do not support multiple color stops. Generate 6 divs, line them up, and do two color gradients for each. Yes, really. */ .sp-1 { height:17%; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00'); } .sp-2 { height:16%; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00'); } .sp-3 { height:17%; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff'); } .sp-4 { height:17%; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff'); } .sp-5 { height:16%; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff'); } .sp-6 { height:17%; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000'); } .sp-hidden { display: none !important; } /* Clearfix hack */ .sp-cf:before, .sp-cf:after { content: ""; display: table; } .sp-cf:after { clear: both; } .sp-cf { *zoom: 1; } /* Mobile devices, make hue slider bigger so it is easier to slide */ @media (max-device-width: 480px) { .sp-color { right: 40%; } .sp-hue { left: 63%; } .sp-fill { padding-top: 60%; } } .sp-dragger { border-radius: 5px; height: 5px; width: 5px; border: 1px solid #fff; background: #000; cursor: pointer; position:absolute; top:0; left: 0; } .sp-slider { position: absolute; top:0; cursor:pointer; height: 3px; left: -1px; right: -1px; border: 1px solid #000; background: white; opacity: .8; } /* Theme authors: Here are the basic themeable display options (colors, fonts, global widths). See http://bgrins.github.io/spectrum/themes/ for instructions. */ .sp-container { border-radius: 0; background-color: #ECECEC; border: solid 1px #f0c49B; padding: 0; } .sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear { font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box; } .sp-top { margin-bottom: 3px; } .sp-color, .sp-hue, .sp-clear { border: solid 1px #666; } /* Input */ .sp-input-container { float:right; width: 100px; margin-bottom: 4px; } .sp-initial-disabled .sp-input-container { width: 100%; } .sp-input { font-size: 12px !important; border: 1px inset; padding: 4px 5px; margin: 0; width: 100%; background:transparent; border-radius: 3px; color: #222; } .sp-input:focus { border: 1px solid orange; } .sp-input.sp-validation-error { border: 1px solid red; background: #fdd; } .sp-picker-container , .sp-palette-container { float:left; position: relative; padding: 10px; padding-bottom: 300px; margin-bottom: -290px; } .sp-picker-container { width: 172px; border-left: solid 1px #fff; } /* Palettes */ .sp-palette-container { border-right: solid 1px #ccc; } .sp-palette-only .sp-palette-container { border: 0; } .sp-palette .sp-thumb-el { display: block; position:relative; float:left; width: 24px; height: 15px; margin: 3px; cursor: pointer; border:solid 2px transparent; } .sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active { border-color: orange; } .sp-thumb-el { position:relative; } /* Initial */ .sp-initial { float: left; border: solid 1px #333; } .sp-initial span { width: 30px; height: 25px; border:none; display:block; float:left; margin:0; } .sp-initial .sp-clear-display { background-position: center; } /* Buttons */ .sp-palette-button-container, .sp-button-container { float: right; } /* Replacer (the little preview div that shows up instead of the ) */ .sp-replacer { margin:0; overflow:hidden; cursor:pointer; padding: 4px; display:inline-block; *zoom: 1; *display: inline; border: solid 1px #91765d; background: #eee; color: #333; vertical-align: middle; } .sp-replacer:hover, .sp-replacer.sp-active { border-color: #F0C49B; color: #111; } .sp-replacer.sp-disabled { cursor:default; border-color: silver; color: silver; } .sp-dd { padding: 2px 0; height: 16px; line-height: 16px; float:left; font-size:10px; } .sp-preview { position:relative; width:25px; height: 20px; border: solid 1px #222; margin-right: 5px; float:left; z-index: 0; } .sp-palette { *width: 220px; max-width: 220px; } .sp-palette .sp-thumb-el { width:16px; height: 16px; margin:2px 1px; border: solid 1px #d0d0d0; } .sp-container { padding-bottom:0; } /* Buttons: http://hellohappy.org/css3-buttons/ */ .sp-container button { background-color: #eeeeee; background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc); background-image: -moz-linear-gradient(top, #eeeeee, #cccccc); background-image: -ms-linear-gradient(top, #eeeeee, #cccccc); background-image: -o-linear-gradient(top, #eeeeee, #cccccc); background-image: linear-gradient(to bottom, #eeeeee, #cccccc); border: 1px solid #ccc; border-bottom: 1px solid #bbb; border-radius: 3px; color: #333; font-size: 14px; line-height: 1; padding: 5px 4px; text-align: center; text-shadow: 0 1px 0 #eee; vertical-align: middle; } .sp-container button:hover { background-color: #dddddd; background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb); background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb); background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb); background-image: -o-linear-gradient(top, #dddddd, #bbbbbb); background-image: linear-gradient(to bottom, #dddddd, #bbbbbb); border: 1px solid #bbb; border-bottom: 1px solid #999; cursor: pointer; text-shadow: 0 1px 0 #ddd; } .sp-container button:active { border: 1px solid #aaa; border-bottom: 1px solid #888; -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; } .sp-cancel { font-size: 11px; color: #d93f3f !important; margin:0; padding:2px; margin-right: 5px; vertical-align: middle; text-decoration:none; } .sp-cancel:hover { color: #d93f3f !important; text-decoration: underline; } .sp-palette span:hover, .sp-palette span.sp-thumb-active { border-color: #000; } .sp-preview, .sp-alpha, .sp-thumb-el { position:relative; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); } .sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner { display:block; position:absolute; top:0;left:0;bottom:0;right:0; } .sp-palette .sp-thumb-inner { background-position: 50% 50%; background-repeat: no-repeat; } .sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=); } .sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=); } .sp-clear-display { background-repeat:no-repeat; background-position: center; background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==); } PKR\cjU//css/admin-style.cssnu[ #of_container { width: auto; } #of_container #header { height: 70px; background:#f1f1f1; border: 1px solid #E7E7E7; -webkit-border-radius: 6px 6px 0 0; -moz-border-radius: 6px 6px 0 0; border-radius: 6px 6px 0 0; background-image: -ms-linear-gradient(top,#f9f9f9,#ececec); background-image: -moz-linear-gradient(top,#f9f9f9,#ececec); background-image: -o-linear-gradient(top,#f9f9f9,#ececec); background-image: -webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#ececec)); background-image: -webkit-linear-gradient(top,#F9F9F9,rgba(134, 132, 118, 0.38)); background-image: linear-gradient(top,#f9f9f9,#ececec); -moz-box-shadow: inset 0 1px 0 #fff; -webkit-box-shadow: inset 0 1px 0 #fff; box-shadow: inset 0 1px 0 #fff; } #of_container #of-nav { display: none; } #of_container #content { width: 100%; padding: 0; } #of_container .group { padding: 0 25px; } #of_container .group h2 { display:block; } #of_container #expand_options { display: none; } .wrap h2, .subtitle { text-shadow: none; } #of_container .controls .of-color-alpha { width: 340px; text-align: center; } div.colorpicker { float: left; clear: both; } #of_container p.shrk_font_preview { display: block; border: 1px dotted lightgray; float: left; padding: 10px; font-size: 10pt; width: 318px; height: auto; margin: 0 0 10px 0; line-height: 1.2; } #cpt_info_box { display: none; } #sectionpicker { overflow: hidden; box-sizing: border-box; margin-top: 20px; } .section-sortable-wrapper { overflow: hidden; width: 49%; float: left; } .section-sortable-wrapper h5 { font-size: 100%; margin: 0 10px -10px 0; text-align: center; color: #d3d3d3; } .sectionpicker .ui-sortable { border: 1px solid #d3d3d3; min-height: 100px; } .sectionpicker .sectionpicker-msg { width: 100%; margin-bottom: 1em; text-decoration: underline; text-align: center; } .sectionpicker .section-sortable-wrapper:nth-child(2n) { margin-right: 2%; } .sectionpicker li { overflow: hidden; cursor: move; transition: background-color 0.1s, color 0.1s; } .sectionpicker li.newitem { background-color: #278ab7; color: #eee; } .sectionpicker li .helper-text { display: none; } .sectionpicker li.newitem .helper-text { display: inline-block; } .sectionpicker li i { transition: background-color 0.1s, color 0.1s; } .sectionpicker li.newitem i, .sectionpicker li.newitem a{ color: #eee; } .sectionpicker li a { text-decoration: none; } .sectionpicker li .iconlinks { float:right; margin-left: 5px; } .sectionpicker .helper-text { float: right; display: inline-block; font-size: 80%; margin-left: 30px; text-decoration: underline; } .sectionpicker .shrk-new-section-button { float: right; } .sectionpicker .spinner { margin-top: 5px; } .ui-state-default { border: 1px solid #d3d3d3; background-color: #e6e6e6; font-weight: normal; color: #555555; } .ui-state-default:hover { background-color: #D6D6D6; } .ui-state-highlight { border: 1px dashed #DFDFDF; background-color: #F1F1F1; } #section-sortable1 li, #section-sortable2 li { margin: 6px 6px; padding: 5px; font-size: 1.2em; width: auto; } .op-upload-wrap .screenshot .of-option-image { width: 100%; margin: 10px 0px; } /* Portfolio post type */ .column-imagepfl .gallery_items_wrap { margin-top: -3px; } .column-imagepfl .gallery_items_wrap img { border: 1px solid #ccc; height: 45px; width: 45px; float: left; margin: 0px 2px 2px 0px; } .column-imagepfl .gallery_items_wrap .post-thumbnail img{ border: 1px solid red; } .column-imagepfl { width: 20%; } .column-type { width: 15%; } .postbox .section-gallery_items .gallery_items_wrap li { overflow: hidden; } .postbox .section-gallery_items .gallery_items_wrap li { border: 1px solid #ccc; margin: 0px 5px 5px 0px; display: inline-block; line-height: 0em; } .postbox .section-gallery_items .gallery_items_wrap li img { width: 100px; height: 100px; } .postbox .postpreview-iframe { width: 100%; min-height: 400px; } .wpb_edit_form_elements .styled_preview_block { width: 100%; } .wpb_edit_form_elements .styled_preview_block iframe { width: 100%; height: 150px; /* position: absolute; */ border: 1px solid #ccc } .wpb_edit_form_elements .styled_preview_block input { display: none; } .wpb_edit_form_elements .icon_picker_block { border: 1px solid #BEBEBE; } .wpb_edit_form_elements .icon_picker_block ul { height: 180px; margin: 0; overflow: auto; } .wpb_edit_form_elements .icon_picker_block input { display: none; } .wpb_edit_form_elements .icon_picker_block ul li { border: 1px solid #ddd; color: #ccc; text-align: center; padding: 10px 0; width: 40px; min-height: 25px; float: left; cursor: pointer; font-size: 26px; margin: 3px 4px; } .wpb_edit_form_elements .icon_picker_block ul li:hover { border: 1px solid #000; color: #000; } .wpb_edit_form_elements .icon_picker_block ul li.selected { border: 1px solid #6B6B6B; color: #6B6B6B; } .vc_element-icon.icon-wpb-shrk { background-image: url('../images/vc-icon-50x50.png'); width: 32px; height: 32px; background-size: cover; } .vc_element-icon.icon-woo-shrk { background-image: url('../images/woo-100x100.png'); width: 32px; height: 32px; background-size: cover; } .vc_element-icon.icon-woo-slider-shrk { background-image: url('../images/woo-slider-100x100.png'); width: 32px; height: 32px; background-size: cover; } .wpb_edit_form_elements .text_slides_block .text_slides .text_slide_field { padding-right: 50px; } .wpb_edit_form_elements .text_slides_block .text_slides li { position: relative; } .wpb_edit_form_elements .text_slides_block .text_slides li i { font-size: 18px; line-height: 32px; width: 32px; text-align: center; color: #aaa; position: absolute; top: 0px; right: 0px; } .wpb_edit_form_elements .text_slides_block .text_slides li i:nth-child(2n) { right: 30px; } .wpb_edit_form_elements .text_slides_block .text_slides li i.remove { } .wpb_edit_form_elements .text_slides_block .text_slides li i.reorder { cursor: n-resize; } .wpb_edit_form_elements ul.icons { text-indent: 0; margin-left: 0; } /* Custom view vertically align text */ .wpb_content_element > .wpb_element_wrapper .wpb_element_title.vertical-center > i.vc_element-icon { float: none; display: inline-block; vertical-align: middle; } .wpb_content_element > .wpb_element_wrapper .wpb_element_title.vertical-center > span { vertical-align: middle; } .wpb_shrk_slabtext .text_rows { overflow: hidden; } /* Meta boxes */ .postbox .shrk-separator { margin-top: 1em; } .shrk-input.of-color-alpha { padding-left: 3px; text-align: center; } .postbox .inside .section { margin-bottom: 24px; padding-bottom: 10px; display: table; width: 100%; box-sizing: border-box; } .postbox .inside .section.section-separator { border-bottom: 0; } .postbox .section .metabox_table { display: table-row; width: 100%; box-sizing: border-box; } .postbox .section .metabox_table > * { vertical-align: middle; box-sizing: border-box; } .postbox .section .metabox_table .heading { display: table-cell; padding-right: 10px; width: 30%; } .postbox .section .metabox_table .heading h4 { margin: 0px 0; } .postbox .section .metabox_table .option { display: table-cell; width: 32%; } .postbox .section .metabox_table .description { display: table-cell; padding-left: 10px; width: 30%; } .postbox .section .metabox_table .option .of-radio { margin: 0 5px 5px 0; } .postbox .section .metabox_table .option .op-upload-wrap .of-input { width: 100%; box-sizing: border-box; } .postbox .section .metabox_table .option .op-upload-wrap .upload_button_div .button { margin: 5px 5px 10px 0; } .postbox .section .metabox_table .option .op-upload-wrap .screenshot, .postbox .section .metabox_table .option .op-upload-wrap .video_preview { border: 1px solid #ccc; } /* in side context */ #side-sortables .section .metabox_table { display: block; } #side-sortables .section .metabox_table > .heading, #side-sortables .section .metabox_table > .option, #side-sortables .section .metabox_table > .description { display: block; width: 100%; } #side-sortables .section .metabox_table > .heading { margin: 1em 0; } #side-sortables .section .metabox_table > .description { padding: 0.2em 0 0 0; opacity: 0.7; } #side-sortables .section { margin-bottom: 0; } .postbox .section .metabox_table .option .of-color-alpha, .postbox .section .metabox_table .option .wp-color-result { margin:0; } .postbox .section .metabox_table .option .range-input-container .range_value, .postbox .section .metabox_table .option .range-input-container .range_preview { clear: both; float:left; text-align: center; color: #777; } .postbox .section .metabox_table .description .default-value { color: #AAA; font-style: italic; } /* sectionpicker */ .section-sectionspicker .metabox_table { } .section-sectionspicker .heading { display: block !important; padding-right: 10px; width: 30%; float:left; margin-top: 20px; } .section-sectionspicker .option { display: block !important; float:right; width: 70% !important; } .section-sectionspicker .description { display: block !important; padding-left: 0px !important; padding-right: 30px; width: 30% !important; float: left; position: absolute; margin-top: 40px; } /* textarea editor */ .postbox .section-textarea_editor .metabox_table .heading { width: 10%; min-width: 80px; } .postbox .section-textarea_editor .metabox_table .option { width: 90%; } .postbox .section-textarea_editor .metabox_table .description { display: none; } .nav-menus-php .mega-menu-checkbox { color: red; opacity: 0; visibility: hidden; transition: color 0.1s linear 0.1s, opacity 0.2s linear 1s, visibility 0s linear 1.2s; } .nav-menus-php .menu-item-depth-0 .mega-menu-checkbox { color: initial; opacity: 1; visibility: visible; transition-delay: 0s; } /* redux small tweaks */ .admin-color-fresh .redux-sidebar .redux-group-menu li.activeChild.hasSubSections:not(.empty_section) a { background-color: #23282D; text-shadow: none; } .admin-color-fresh .redux-sidebar .redux-group-menu li.activeChild.hasSubSections:not(.empty_section) a:hover { color: #1e8cbe; background: #0d0e10; } #redux-header .rAds { visibility: hidden; } .redux-container #redux-header { background-image: url('../images/redux_head_bg.jpg'); background-position: 50% 50%; background-size: cover; background-repeat: no-repeat; } .redux-sidebar [id='10_section_group_li_a'] i.el-photo { transform: rotate(180deg); /* Rotate photo icon from elusive icons */ } .redux-field.wbc_importer .theme-browser .theme.active .theme-actions, .redux-field.wbc_importer .theme-browser .theme .theme-actions { position: absolute; top: auto; bottom: 0; right: 0; transform: none; } /* Hide pagesections related redux options when pt not registered */ .require-pagesections-posttype { display: none; } .pagesections-enabled .require-pagesections-posttype { display: block; } .pagesections-enabled tr.require-pagesections-posttype { display: table-row; } /* Minor WooCommerce styles */ #woocommerce-coupon-data ul.wc-tabs li.shrk-product-videos_options a::before, #woocommerce-product-data ul.wc-tabs li.shrk-product-videos_options a::before, .woocommerce ul.wc-tabs li.shrk-product-videos_options a::before { content: "\f236"; } /* woocommerce styles step over redux styles... */ .redux-main .form-table-section-indented { width: 95%; margin-left: 5% !important; }PKH\ .admin.phpnu[PKH\2unn:aioseop_module_class.phpnu[PKH\Լ f.f.Iodisplay/credits-content.phpnu[PKH\display/notices/.notices.phpnu[PKH\\ff(Fdisplay/notices/review-plugin-notice.phpnu[PKH\$$display/notices/index.phpnu[PKH\0&&qdisplay/notices/wc-detected-notice.phpnu[PKH\d +*display/notices/sitemap-indexes-notice.phpnu[PKH\+ee*display/notices/blog-visibility-notice.phpnu[PKH\vM50!0!wdisplay/general-metaboxes.phpnu[PKH\FbE4display/notice-default.phpnu[PKH\display/notice-aioseop.phpnu[PKH\$$display/index.phpnu[PKH\Idisplay/.display.phpnu[PKH\78<<display/welcome.phpnu[PKH\BܸDD display/welcome-content.phpnu[PKH\d display/dashboard_widget.phpnu[PKH\4display/menu.phpnu[PKH\BWzz"aioseop_module_manager.phpnu[PKH\eOeOimages/wheel.500.jpgnu[PKR\LV66images/transparent.gifnu[PKR\΁3images/ion-android-cart.pngnu[PKR\xkimages/vc-icon-50x50.pngnu[PKR\[vG-G-#Wcss/spectrum/redux-spectrum.min.cssnu[PKR\<[D<D<# css/spectrum/redux-spectrum.cssnu[PKR\cjU//` css/admin-style.cssnu[PK11F