diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/.gitignore b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/.gitignore new file mode 100644 index 000000000..b7be1910b --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/.gitignore @@ -0,0 +1,44 @@ +*.log +wp-config.php +wp-content/advanced-cache.php +wp-content/backup-db/ +wp-content/backups/ +wp-content/blogs.dir/ +wp-content/cache/ +wp-content/upgrade/ +wp-content/uploads/ +wp-content/mu-plugins/ +wp-content/wp-cache-config.php +wp-content/plugins/hello.php + +/.htaccess +/license.txt +/readme.html +/sitemap.xml +/sitemap.xml.gz + +.DS_Store + +# Grunt +/build/ +/node_modules/ +npm-debug.log + +# Composer +composer.lock +/vendor/ + +# Dev +/dev-lib/ + +# Tests +tests/data/ +tests/includes/ +coverage/html/ + +# ENV files +.env + +# IDE +.vscode +cloudinary-image-management-and-manipulation-in-the-cloud-cdn diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/api.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/api.php deleted file mode 100644 index 1370b48da..000000000 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/api.php +++ /dev/null @@ -1,40 +0,0 @@ -rate_limit_reset_at = strtotime($response->headers["X-FeatureRateLimit-Reset"]); - $this->rate_limit_allowed = intval($response->headers["X-FeatureRateLimit-Limit"]); - $this->rate_limit_remaining = intval($response->headers["X-FeatureRateLimit-Remaining"]); - } - } - - // Create class alias for old class - \class_alias(\Cloudinary\Api::class, CloudinaryApi::class); - - // This tricks IDE and marks old class as deprecated - if (! \class_exists(CloudinaryApi::class)) { // essentially this is "if(false)" - /** @deprecated use \Cloudinary\Api */ - class CloudinaryApi {} - } - diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/autoload.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/autoload.php deleted file mode 100644 index 0c318a2ea..000000000 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/autoload.php +++ /dev/null @@ -1,27 +0,0 @@ -=' ) ) { + require_once __DIR__ . '/instance.php'; +} else { + if ( defined( 'WP_CLI' ) ) { + WP_CLI::warning( _cloudinary_php_version_text() ); + } else { + add_action( 'admin_notices', '_cloudinary_php_version_error' ); + } } -class CloudinaryPlugin -{ - public function __construct() - { - $this->cloudinary_upgrade(); - register_uninstall_hook('uninstall.php', ''); - - add_action('admin_init', array($this, 'config')); - add_action('admin_menu', array($this, 'cloudinary_options_page')); - - add_filter('manage_media_columns', array($this, 'media_lib_add_upload_column')); - add_action('manage_media_custom_column', array($this, 'media_lib_upload_column_value'), 0, 2); - add_action('admin_footer-upload.php', array($this, 'media_lib_upload_admin_footer')); - add_action('load-upload.php', array($this, 'media_lib_upload_action')); - add_action('admin_notices', array($this, 'media_lib_upload_notices')); - - add_action('media_buttons', array($this, 'media_cloudinary'), 11); - add_action('wp_ajax_cloudinary_update_options', array($this, 'ajax_update_options')); - add_filter('wp_get_attachment_url', array($this, 'fix_url'), 1, 2); - add_filter('image_downsize', array($this, 'remote_resize'), 1, 3); - - add_action('wp_ajax_cloudinary_register_image', array($this, 'ajax_register_image')); - - if (class_exists('WP_CLI')) { - $command = new Cloudinary\Cli($this); - \WP_CLI::add_command('cloudinary-import', $command); - } - } - - /** - * Backwards compatibility. - */ - public function CloudinaryPlugin() - { - self::__construct(); - } - - /** - * Called from client side when user adds image to Cloudinary. - * - * wp_send_json prints json result and dies(exits) immediately - */ - public function ajax_register_image() - { - if (empty($_POST) || !check_admin_referer('cloudinary_register_image')) { - wp_send_json(array('message' => 'Sorry, your nonce did not verify.', 'error' => true)); - } - - $post_id = $_POST['post_id']; - $attachment_id = &$_POST['attachment_id']; - $url = $_POST['url']; - - if (!empty($post_id) && !current_user_can('edit_post', $post_id)) { - wp_send_json(array('message' => 'Permission denied.', 'error' => true)); - } - if (!empty($attachment_id) && !current_user_can('edit_post', $attachment_id)) { - wp_send_json(array('message' => 'Permission denied.', 'error' => true)); - } - if (empty($url)) { - wp_send_json(array('message' => 'Missing URL.', 'error' => true)); - } - - $id = $this->register_image($url, $post_id, $attachment_id, null, $_POST['width'], $_POST['height']); - wp_send_json(array('success' => true, 'attachment_id' => $id)); - } - - public function register_image($url, $post_id, $attachment_id, $original_attachment, $width, $height) - { - $info = pathinfo($url); - $public_id = $info['filename']; - $mime_types = array('png' => 'image/png', 'jpg' => 'image/jpeg', 'pdf' => 'application/pdf', 'gif' => 'image/gif', 'bmp' => 'image/bmp'); - $type = $mime_types[$info['extension']]; - $meta = null; - if ($original_attachment) { - $md = wp_get_attachment_metadata($attachment_id); - $meta = $md['image_meta']; - $title = $original_attachment->post_title; - $caption = $original_attachment->post_content; - } else { - $title = null; - $caption = null; - $meta = null; - } - if (!$title) { - $title = $public_id; - } - if (!$caption) { - $caption = ''; - } - if (!$meta) { - $meta = array( - 'aperture' => 0, - 'credit' => '', - 'camera' => '', - 'caption' => $caption, - 'created_timestamp' => 0, - 'copyright' => '', - 'focal_length' => 0, - 'iso' => 0, - 'shutter_speed' => 0, - 'title' => $title, ); - } - - $attachment = array( - 'post_mime_type' => $type, - 'guid' => $url, - 'post_parent' => $post_id, - 'post_title' => $title, - 'post_content' => $caption, ); - if ($attachment_id && is_numeric($attachment_id)) { - $attachment['ID'] = intval($attachment_id); - } - - // Save the data - $id = wp_insert_attachment($attachment, $url, $post_id); - if (!is_wp_error($id)) { - $metadata = array('image_meta' => $meta, 'width' => $width, 'height' => $height, 'cloudinary' => true); - wp_update_attachment_metadata($id, $metadata); - } - - return $id; - } - - public function migrate_away($attach_id) - { - $current_attachment = get_post($attach_id); - $metadata = wp_get_attachment_metadata($attach_id); - $url = wp_get_attachment_url($attach_id); - if (!Cloudinary::option_get($metadata, 'cloudinary')) { - return 'Not a Cloudinary image'; - } - - $uploads = wp_upload_dir(str_replace('-', '/', substr($current_attachment->post_date, 0, 7))); - $url_info = pathinfo($url); - $public_id = rawurldecode($url_info['basename']); - $filename = wp_unique_filename($uploads['path'], $public_id, null); - $fullpathfilename = $uploads['path'].'/'.$filename; - - $response = wp_remote_get($url); - - if (is_wp_error($response)) { - $error = $response->get_error_message(); - - return $public_id.' cannot be migrate away. '.$error; - } - - if ($response['response']['code'] != 200) { - $error = $response['headers']['x-cld-error']; - if (!$error) { - $error = "Unable to migrate away $url"; - } - - return $public_id.' cannot be migrate away. '.$error; - } - $image_string = $response['body']; - $fileSaved = file_put_contents($uploads['path'].'/'.$filename, $image_string); - if (!$fileSaved) { - return 'The file cannot be saved.'; - } - $attachment = array( - 'ID' => $attach_id, - 'guid' => $uploads['url'].'/'.$filename, - 'cloudinary' => null, - ); - $attrs = array('post_mime_type', 'post_title', 'post_content', 'post_status', 'post_author', 'post_name', 'post_date'); - foreach ($attrs as $key) { - $attachment[$key] = $current_attachment->$key; - } - - $attach_id = wp_insert_attachment($attachment, $fullpathfilename, $current_attachment->post_parent); - if (!$attach_id) { - return 'Failed to save record into database.'; - } - require_once ABSPATH.'wp-admin'.'/includes/image.php'; - $attach_data = wp_generate_attachment_metadata($attach_id, $fullpathfilename); - wp_update_attachment_metadata($attach_id, $attach_data); - - $new_src = wp_get_attachment_image_src($attach_id, null); - $errors = array(); - $this->update_image_src_all($attach_id, $attach_data, $url, $new_src[0], false, $errors); - if (count($errors) > 0) { - return 'Cannot migrate the following posts - '.implode(', ', array_keys($errors)); - } - - return null; - } - - /** - * @deprecated - * Convert metadata from cloudinary response to plugin-friendly format - * - * @param array $remote_meta - metadata returned by Cloudinary API - * - * @return array - extracted metadata - */ - public function extract_metadata($remote_meta) - { - trigger_error('Method '.__METHOD__.' is deprecated', E_USER_DEPRECATED); - $meta = array( - 'aperture' => 0, - 'credit' => '', - 'camera' => '', - 'caption' => '', - 'created_timestamp' => 0, - 'copyright' => '', - 'focal_length' => 0, - 'iso' => 0, - 'shutter_speed' => 0, - 'title' => '', - ); - $meta['title'] = $this->extract_meta_value($remote_meta, array('Headline', 'ObjectName')); - $caption = $this->extract_meta_value($remote_meta, array('Caption-Abstract')); - if (!empty($caption)) { - if (empty($meta['title'])) { - if (strlen($caption) < 80) { - $meta['title'] = $caption; - } else { - $meta['caption'] = $caption; - } - } elseif ($caption != $meta['title']) { - $meta['caption'] = $caption; - } - } - $meta['credit'] = $this->extract_meta_value($remote_meta, array('Artist', 'Author', 'Credit', 'By-line')); - if (!empty($remote_meta['DateCreated']) and !empty($remote_meta['TimeCreated'])) { // created date and time - $meta['created_timestamp'] = strtotime($remote_meta['DateCreated'].' '.$remote_meta['TimeCreated']); - } - $meta['copyright'] = $this->extract_meta_value($remote_meta, array('Copyright', 'CopyrightNotice')); - if (!empty($remote_meta['Title'])) { - $meta['title'] = trim($remote_meta['Title']); - } - if (!empty($remote_meta['ImageDescription'])) { - if (empty($meta['title']) && strlen($remote_meta['ImageDescription']) < 80) { - // Assume the title is stored in ImageDescription - $meta['title'] = trim($remote_meta['ImageDescription']); - if (!empty($remote_meta['UserComment']) && trim($remote_meta['UserComment']) != $meta['title']) { - $meta['caption'] = trim($remote_meta['UserComment']); - } - } elseif (trim($remote_meta['ImageDescription']) != $meta['title']) { - $meta['caption'] = trim($remote_meta['ImageDescription']); - } - } elseif (!empty($remote_meta['Comments']) && trim($remote_meta['Comments']) != $meta['title']) { - $meta['caption'] = trim($remote_meta['Comments']); - } - - $meta['camera'] = $this->extract_meta_value($remote_meta, array('Model')); - if (!empty($remote_meta['DateTimeDigitized'])) { - $meta['created_timestamp'] = wp_exif_date2ts($remote_meta['DateTimeDigitized']); - } - $meta['iso'] = $this->extract_meta_value($remote_meta, array('ISO'), 0); - - if (!empty($remote_meta['FNumber'])) { - $meta['aperture'] = round(wp_exif_frac2dec($remote_meta['FNumber']), 2); - } - if (!empty($remote_meta['FocalLength'])) { - $meta['focal_length'] = (string) wp_exif_frac2dec($remote_meta['FocalLength']); - } - if (!empty($remote_meta['ExposureTime'])) { - $meta['shutter_speed'] = (string) wp_exif_frac2dec($remote_meta['ExposureTime']); - } - - return $meta; - } - - /** - * @deprecated - */ - public function extract_meta_value($info, $keys, $default = '') - { - trigger_error('Method '.__METHOD__.' is deprecated', E_USER_DEPRECATED); - foreach ($keys as $key) { - if (!empty($info[$key])) { - return trim($info[$key]); - } - } - - return $default; - } - - public function get_wp_sizes() - { - if (isset($this->sizes)) { - return $this->sizes; - } - // make thumbnails and other intermediate sizes - global $_wp_additional_image_sizes; - $sizes = array(); - - foreach (get_intermediate_image_sizes() as $s) { - $sizes[$s] = array('width' => '', 'height' => '', 'crop' => false); - if (isset($_wp_additional_image_sizes[$s]['width'])) { - $sizes[$s]['width'] = intval($_wp_additional_image_sizes[$s]['width']); - } // For theme-added sizes - else { - $sizes[$s]['width'] = get_option("{$s}_size_w"); - } // For default sizes set in options - if (isset($_wp_additional_image_sizes[$s]['height'])) { - $sizes[$s]['height'] = intval($_wp_additional_image_sizes[$s]['height']); - } // For theme-added sizes - else { - $sizes[$s]['height'] = get_option("{$s}_size_h"); - } // For default sizes set in options - if (isset($_wp_additional_image_sizes[$s]['crop'])) { - $sizes[$s]['crop'] = intval($_wp_additional_image_sizes[$s]['crop']); - } // For theme-added sizes - else { - $sizes[$s]['crop'] = get_option("{$s}_crop"); - } // For default sizes set in options - } - - $this->sizes = apply_filters('intermediate_image_sizes_advanced', $sizes); - - return $this->sizes; - } - - public function fix_url($url, $post_id) - { - $metadata = wp_get_attachment_metadata($post_id); - if (Cloudinary::option_get($metadata, 'cloudinary') && preg_match('#^.*?/(https?://.*)#', $url, $matches)) { - return $matches[1]; - } - - return $url; - } - - /** - * Build Cloudinary URL for resized image. - * - * @param string $url - original image url - * @param array $metadata - original image metadata - * @param string|array $size - target size. Can be array with width, height parameters, or - * string with predefined sizes, see $this->get_wp_sizes for available values - * - * @return false|array Array containing the image URL, width, height, and boolean for whether - * the image is an intermediate size. False on failure. - */ - public function build_resize_url($url, $metadata, $size) - { - // Check if this is a Cloudinary URL - if (!preg_match('#(.*?)/(v[0-9]+/.*)$#', $url, $matches)) { - return false; - } - - if (!$size) { - return array($url, $metadata['width'], $metadata['height'], false); - } - - if (is_string($size)) { - $available_sizes = $this->get_wp_sizes(); - // Unsupported custom size or 'full' image return as is, indicating that it was not changed - if (!array_key_exists($size, $available_sizes)) { - return array($url, $metadata['width'], $metadata['height'], false); - } - - $wanted = $available_sizes[$size]; - $crop = $wanted['crop']; - } elseif (is_array($size)) { - $wanted = array('width' => $size[0], 'height' => $size[1]); - $crop = false; - } else { - // Unsupported argument - return false; - } - - $transformation = ''; - $src_w = $dst_w = $metadata['width']; - $src_h = $dst_h = $metadata['height']; - if ($crop) { - $resized = image_resize_dimensions($metadata['width'], $metadata['height'], $wanted['width'], $wanted['height'], true); - if ($resized) { - list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $resized; - $transformation = "c_crop,h_$src_h,w_$src_w,x_$src_x,y_$src_y/"; - } - } - - list($width, $height) = image_constrain_size_for_editor($dst_w, $dst_h, $size); - if ($width != $src_w || $height != $src_h) { - $transformation = $transformation."h_$height,w_$width/"; - } - - $url = "$matches[1]/$transformation$matches[2]"; - - return array($url, $width, $height, true); - } - - /** - * Filter for image_downsize wordpress function. - * - * See https://codex.wordpress.org/Function_Reference/image_downsize - * - * @return false|array Array containing the image URL, width, height, and boolean for whether - * the image is an intermediate size. False on failure. - */ - public function remote_resize($dummy, $post_id, $size) - { - $url = wp_get_attachment_url($post_id); - $metadata = wp_get_attachment_metadata($post_id); - if (!Cloudinary::option_get($metadata, 'cloudinary')) { - return false; - } - - return $this->build_resize_url($url, $metadata, $size); - } - - /* Upgrade */ - public function cloudinary_upgrade() - { - $current_version = get_option('cloudinary_version'); - if (cloudinary_VERSION != $current_version) { - if ($current_version && version_compare($current_version, '1.0.4', '<')) { - /* cloudinary_url used to be stored in a configuration table. migrate to an option */ - global $wpdb; - $table_name_account = $wpdb->prefix.'cloudinary_config'; - $myrows = $wpdb->get_results("SELECT * FROM $table_name_account where user_id = 1"); - if (!empty($myrows)) { - $cloudinary_url = trim($myrows[0]->cloudinary_url); - update_option('cloudinary_url', $cloudinary_url); - } - /* drop table in database */ - $wpdb->query("DROP TABLE IF EXISTS $table_name_account"); - } - update_option('cloudinary_version', cloudinary_VERSION); - } - } - - /* Configure Cloudinary integration if settings available */ - public function config() - { - $cloudinary_url = get_option('cloudinary_url'); - if ($cloudinary_url) { - Cloudinary::config_from_url($cloudinary_url); - Cloudinary::$USER_PLATFORM = self::get_user_platform(); - } - } - - /** - * Provides USER_PLATFORM string that is prepended to USER_AGENT string that is passed to the Cloudinary servers. - * - * Sample value: CloudinaryWordPress/1.2.3 (WordPress 4.5.6) - * - * @return string USER_PLATFORM - */ - private static function get_user_platform() - { - return sprintf(CLOUDINARY_USER_PLATFORM_TEMPLATE, cloudinary_VERSION, get_bloginfo('version')); - } - - public function configured() - { - return Cloudinary::config_get('api_secret') && Cloudinary::config_get('cloud_name') && Cloudinary::config_get('api_key'); - } - - /* Configure menus */ - public function cloudinary_options_page() - { - $this->config(); // This is called before admin_init - $settings_item = CLOUDINARY_UNIQUE_ID.'/options.php'; - $library_item = CLOUDINARY_UNIQUE_ID.'/library.php'; - - $main_action = $this->configured() ? $library_item : $settings_item; - add_menu_page('Cloudinary Menu', 'Cloudinary', 'manage_options', $main_action, null, plugins_url(CLOUDINARY_UNIQUE_ID.'/images/favicon.png')); - add_submenu_page($main_action, 'Cloudinary Media Library', 'Media library', 'publish_pages', $main_action); - add_submenu_page($main_action, 'Cloudinary Settings', 'Settings', 'manage_options', $settings_item); - } - - public function ajax_update_options() - { - if (empty($_POST) || !check_admin_referer('cloudinary_update_options')) { - echo 'Sorry, your nonce did not verify.'; - } else { - $cloudinary_url = str_replace('CLOUDINARY_URL=', '', trim($_POST['cloudinary_url'])); - Cloudinary::config_from_url($cloudinary_url); - if ($this->configured()) { - update_option('cloudinary_url', $cloudinary_url); - $url = $this->prepare_cloudinary_media_lib_url('check'); - $args = array('method' => 'GET', 'timeout' => 5, 'redirection' => 5, 'httpversion' => '1.0', 'blocking' => true, 'headers' => array(), - 'body' => null, 'cookies' => array(), 'sslverify' => false, ); - $response = wp_remote_get($url, $args); - if (is_wp_error($response)) { - echo 'Cannot access Cloudinary (error '.$response->get_error_message().') - Verify your CLOUDINARY_URL'; - } elseif ($response['response']['code'] == '200') { - echo 'success'; - } else { - echo 'Cannot access Cloudinary (error '.$response['response']['code'].') - Verify your CLOUDINARY_URL'; - } - } else { - echo 'Invalid CLOUDINARY_URL. Must match the following format: cloudinary://api_key:api_secret@cloud_name'; - } - } - die(); - } - - public function update_image_src_all($attachment_id, $attachment_metadata, $old_url, $new_url, $migrate_in, &$errors) - { - $query = new WP_Query( - array( - 'post_type' => 'any', - 'post_status' => 'publish,pending,draft,auto-draft,future,private', - 's' => "wp-image-{$attachment_id}", - ) - ); - - while ($query->have_posts()) { - $query->the_post(); - $this->update_image_src($query->post, $attachment_id, $attachment_metadata, $old_url, $new_url, $migrate_in, $errors); - } - } - - public function update_image_src($post, $attachment_id, $attachment_metadata, $old_url, $new_url, $migrate_in, &$errors) - { - $this->get_wp_sizes(); - $post_content = $post->post_content; - preg_match_all('~~i', $post->post_content, $images); - foreach ($images[0] as $img) { - if (preg_match('~class *= *["\']([^"\']+)["\']~i', $img, $class) && preg_match('~wp-image-(\d+)~i', $class[1], $id) && $id[1] == $attachment_id) { - $wanted_size = null; - if (preg_match('~size-([a-zA-Z0-9_\-]+)~i', $class[1], $size)) { - if (isset($this->sizes[$size[1]])) { - $wanted_size = $size[1]; - } elseif ('full' == $size[1]) { - // default url requested - } else { - // Unknown transformation. - if ($migrate_in) { - continue; // Skip - } else { - error_log('Cannot automatically migrate image - non-standard image size detected '.$size[1]); - $errors[$post->ID] = true; - - return false; - } - } - } - if (preg_match('~src *= *["\']([^"\']+)["\']~i', $img, $src)) { - if ($migrate_in) { - // Migrate In - list($new_img_src) = $this->build_resize_url($new_url, $attachment_metadata, $wanted_size); - if ($new_img_src) { - $post_content = str_replace($src[1], $new_img_src, $post_content); - } - } else { - // Migrate Out - list($old_img_src) = $this->build_resize_url($old_url, $attachment_metadata, $wanted_size); - if ($old_img_src) { - //Compare URLs ignoring secure protocol - if (str_replace('https://', 'http://', $old_img_src) != str_replace('https://', 'http://', $src[1])) { - error_log('Cannot automatically migrate image - non-standard image url detected '.$src[1]." expected $old_img_src requested size $wanted_size"); - $errors[$post->ID] = true; - - return false; - } - if (!isset($wanted_size)) { - $wanted_size = 'full'; - } - list($new_img_src) = image_downsize($attachment_id, $wanted_size); - if (!$new_img_src) { - error_log('Cannot automatically migrate image - failed to downsize '.$src[1].' to '.$wanted_size); - $errors[$post->ID] = true; - - return false; - } - $post_content = str_replace($src[1], $new_img_src, $post_content); - } - } - } - } - // Also replace original link with new link, for hrefs - $post_content = str_replace($old_url, $new_url, $post_content); - } - if ($post_content != $post->post_content) { - return wp_update_post(array('post_content' => $post_content, 'ID' => $post->ID)); - } - - return false; - } - - public function init_media_lib_integration($xdmremote, $autoShow) - { - $cloudinary_js_dir = plugins_url('/js', __FILE__); - wp_enqueue_script('jquery'); - wp_enqueue_script('cld-xdm', $cloudinary_js_dir.'/easyXDM.min.js'); - wp_enqueue_script('cld-json2', $cloudinary_js_dir.'/json2.min.js'); - wp_enqueue_script('cld-js', $cloudinary_js_dir.'/cloudinary.js?cv='.cloudinary_VERSION); - $cloudinary_css_dir = plugins_url('/css', __FILE__); - wp_enqueue_style('cld-css', $cloudinary_css_dir.'/cloudinary.css?cv='.cloudinary_VERSION); - - $xdmbase = plugins_url('', __FILE__); - $xdmremotehelper = CLOUDINARY_BASE_URL.'/easyXDM.name.html'; - $xdmautoshow = $autoShow ? 'true' : 'false'; - $ajaxurl = wp_nonce_url(admin_url('admin-ajax.php'), 'cloudinary_register_image'); - - return "". - ""; - } - - public function media_cloudinary($editor_id = 'content') - { - $xdmremote = $this->prepare_cloudinary_media_lib_url('wp_post'); - if (!$xdmremote) { - return ''; - } - - echo $this->init_media_lib_integration($xdmremote, false). - ''.__('Cloudinary Upload/Insert').''; - - return null; - } - - public function media_lib_add_upload_column($cols) - { - $cols['media_url'] = 'Cloudinary'; - - return $cols; - } - - public function media_lib_upload_column_value($column_name, $attachment_id) - { - if ('media_url' == $column_name) { - $metadata = wp_get_attachment_metadata($attachment_id); - if (is_array($metadata) && Cloudinary::option_get($metadata, 'cloudinary')) { - $src = plugins_url('/images/edit_icon.png', __FILE__); - echo " Uploaded"; - } elseif (Cloudinary::config_get('api_secret')) { - $action_url = wp_nonce_url('?', 'bulk-media'); - echo "Upload to Cloudinary"; - } - } - } - - public function media_lib_upload_admin_footer() - { - if (!$this->configured()) { - return; - } - $img_l = plugins_url('/images/ajax-loader.gif', __FILE__); ?> - - guid; - if (empty($full_path)) { - return 'Unsupported attachment type'; - } - } - - try { - $result = \Cloudinary\Uploader::upload($full_path, array('use_filename' => true)); - } catch (Exception $e) { - return $e->getMessage(); - } - - $post_parent = null; - if ($migrate) { - $old_url = wp_get_attachment_url($attachment_id); - $post_parent = $attachment->post_parent; - } else { - $attachment_id = null; - } - - $this->register_image($result['secure_url'], $post_parent, $attachment_id, $attachment, $result['width'], $result['height']); - - if ($migrate) { - $errors = array(); - $this->update_image_src_all($attachment_id, $result, $old_url, $result['secure_url'], true, $errors); - if (count($errors) > 0) { - return 'Cannot migrate the following posts - '.implode(', ', $errors); - } - } - - return null; - } - - public function media_lib_upload_action() - { - $wp_list_table = _get_list_table('WP_Media_List_Table'); - $action = $wp_list_table->current_action(); - $sendback = wp_get_referer(); - - global $pagenow; - if ('upload.php' == $pagenow && isset($_REQUEST['cloud_upload']) && (int) $_REQUEST['cloud_upload']) { - if (!$this->configured()) { - echo 'Please setup environment to upload images to cloudinary'; - exit(); - } - - check_admin_referer('bulk-media'); - // Single image upload - $error = $this->upload_to_cloudinary($_REQUEST['cloud_upload'], true); - $_REQUEST = array(); - if ($error) { - $errors = array($error => 1); - $successes = 0; - } else { - $errors = array(); - $successes = 1; - } - - $this->return_to_media_lib($errors, $successes, 'upload_cloudinary', $sendback); - } - if ('upload_cloudinary' === $action || 'migrate_away_cloudinary' === $action) { - if (!$this->configured()) { - echo 'Please setup environment to upload images to cloudinary'; - exit(); - } - - // Multiple images upload - check_admin_referer('bulk-media'); - - $post_ids = array(); - if (isset($_REQUEST['media'])) { - $post_ids = $_REQUEST['media']; - } elseif (isset($_REQUEST['ids'])) { - $post_ids = explode(',', $_REQUEST['ids']); - } - - $successes = 0; - $errors = array(); - foreach ($post_ids as $k => $post_id) { - $error = 'upload_cloudinary' === $action ? $this->upload_to_cloudinary($post_id, true) : $this->migrate_away($post_id); - if ($error) { - if (isset($errors[$error])) { - $errors[$error] += 1; - } else { - $errors[$error] = 1; - } - } else { - ++$successes; - } - } - $this->return_to_media_lib($errors, $successes, $action, $sendback); - } - } - - public function return_to_media_lib($errors, $successes, $action, $sendback) - { - $image = 1 == $successes ? 'image' : 'images'; - $action_message = 'upload_cloudinary' === $action ? ' uploaded to cloudinary.' : ' migrated away from cloudinary.'; - $message = number_format_i18n($successes).' '.$image.$action_message; - - if (!empty($errors)) { - $errors_count = array_sum($errors); - $errors_count_message = 1 == $errors_count ? 'error' : 'errors'; - $message = "$message ".number_format_i18n($errors_count)." failed because of the following $errors_count_message: "; - foreach ($errors as $error => $error_count) { - $message = $message.$error; - if ($error_count > 1) { - $message = $message.' ('.number_format_i18n($error_count).' times)'; - } - $message = $message.'. '; - } - } - $location = add_query_arg(array('cloudinary_message' => urlencode($message)), $sendback); - wp_redirect($location); - exit(); - } - - public function media_lib_upload_notices() - { - global $post_type, $pagenow; - if ('upload.php' == $pagenow && 'attachment' == $post_type && Cloudinary::option_get($_REQUEST, 'cloudinary_message')) { - $message = htmlentities($_REQUEST['cloudinary_message'], ENT_NOQUOTES); - echo "

{$message}

"; - } - if ('upload.php' == $pagenow && Cloudinary::option_get($_REQUEST, 'cloud_upload')) { - $message = 'Sorry, this file format is not supported.'; - echo "

{$message}

"; - } - } - - public function prepare_cloudinary_media_lib_url($mode) - { - if (!$this->configured()) { - return null; - } - $params = array('timestamp' => time(), 'mode' => $mode, 'plugin_version' => cloudinary_VERSION); - $params['signature'] = Cloudinary::api_sign_request($params, Cloudinary::config_get('api_secret')); - $params['api_key'] = Cloudinary::config_get('api_key'); - $query = http_build_query($params); - - return CLOUDINARY_BASE_URL."/console/media_library/cms?$query"; - } +/** + * Admin notice for incompatible versions of PHP. + */ +function _cloudinary_php_version_error() { + printf( '

%s

', esc_html( _cloudinary_php_version_text() ) ); } -$cloudinary_plugin = new CloudinaryPlugin(); +/** + * String describing the minimum PHP version. + * + * @return string + */ +function _cloudinary_php_version_text() { + return __( 'Cloudinary plugin error: Your version of PHP is too old to run this plugin. You must be running PHP 5.6 or higher.', 'cloudinary' ); +} diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/cloudinary_api.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/cloudinary_api.php deleted file mode 100644 index e6f3f12b0..000000000 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/cloudinary_api.php +++ /dev/null @@ -1,12 +0,0 @@ -li{display:inline-block}.settings-tabs>li a{padding:.6em}.settings-tabs>li a.active{background-color:#fff}.settings-tab-section{padding:20px 0 0;max-width:1030px;position:relative}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard{display:flex;align-items:flex-start;align-content:flex-start;margin-top:40px}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-description{width:55%;margin:0 auto 0 0}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-content{width:35%;margin:0 auto}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-content .dashicons{color:#9ea3a8}.settings-tab-section.cloudinary-welcome .settings-tab-section-card{margin-top:0}.settings-tab-section-fields .field-heading th{display:block;width:auto;color:#23282d;font-size:1.1em;margin:1em 0}.settings-tab-section-fields .field-heading td{display:none;visibility:hidden}.settings-tab-section-fields .regular-textarea{width:100%;height:60px}.settings-tab-section-fields .dashicons{text-decoration:none;vertical-align:middle}.settings-tab-section-fields a .dashicons{color:#5f5f5f}.settings-tab-section-fields-dashboard-error{font-size:1.2em;color:#5f5f5f}.settings-tab-section-fields-dashboard-error .dashicons{color:#ac0000}.settings-tab-section-fields-dashboard-error .button{font-size:1.1em;height:40px;line-height:40px;padding-right:40px;padding-left:40px}.settings-tab-section-fields-dashboard-success{font-size:1.2em;color:#23282d}.settings-tab-section-fields-dashboard-success.expanded{padding-top:40px}.settings-tab-section-fields-dashboard-success .dashicons{color:#4fb651}.settings-tab-section-fields-dashboard-success .button{font-size:1.1em;height:40px;line-height:40px;padding-right:40px;padding-left:40px}.settings-tab-section-fields-dashboard-success .description{color:#5f5f5f;font-weight:400;margin-top:12px}.settings-tab-section-card{box-sizing:border-box;border:1px solid #e5e5e5;background-color:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.07);padding:20px 23px;margin-top:12px}.settings-tab-section-card .dashicons{font-size:1.4em}.settings-tab-section-card h2{font-size:1.8em;font-weight:400;margin-top:0}.settings-tab-section-card.pull-right{width:450px;padding:12px;float:right;position:relative;z-index:10}.settings-tab-section-card.pull-right img.settings-image{box-shadow:0 2px 4px 0 rgba(0,0,0,.5);border:1px solid #979797;margin-top:12px}.settings-tab-section-card.pull-right h3,.settings-tab-section-card.pull-right h4{margin-top:0}.settings-tab-section .field-row-cloudinary_url,.settings-tab-section .field-row-signup{display:block}.settings-tab-section .field-row-cloudinary_url td,.settings-tab-section .field-row-cloudinary_url th,.settings-tab-section .field-row-signup td,.settings-tab-section .field-row-signup th{display:block;width:auto;padding:10px 0 0}.settings-tab-section .field-row-cloudinary_url td .sign-up,.settings-tab-section .field-row-cloudinary_url th .sign-up,.settings-tab-section .field-row-signup td .sign-up,.settings-tab-section .field-row-signup th .sign-up{vertical-align:baseline}.settings-tab-section.connect .form-table{display:inline-block;width:auto;max-width:580px}.settings-valid{color:#558b2f;font-size:30px}.settings-valid-field{border-color:#558b2f!important}.settings-invalid-field{border-color:#dd2c00!important}.sync .spinner{display:inline-block;visibility:visible;float:none;margin:0 5px 0 0}.sync-media,.sync-media-progress{display:none}.sync-media-progress-outer{height:20px;margin:20px 0 10px;width:500px;background-color:#e5e5e5;position:relative}.sync-media-progress-outer .progress-bar{width:0;height:20px;background-color:#558b2f;transition:width .25s}.sync-media-progress-notice{color:#dd2c00}.sync-media-resource{width:100px;display:inline-block}.sync-media-error{color:#dd2c00}.sync-count{font-weight:700}.sync-details{margin-top:10px}.sync .button.start-sync,.sync .button.stop-sync{display:none;padding:0 16px}.sync .button.start-sync .dashicons,.sync .button.stop-sync .dashicons{line-height:2.2em}.sync .progress-text{padding:12px 4px 12px 12px;display:inline-block;font-weight:700}.sync .completed{max-width:300px;display:none}.cloudinary-widget{height:100%}.cloudinary-widget-wrapper{height:100%;overflow:hidden;background-image:url("data:image/svg+xml;base64,PHN2ZyBjbGFzcz0ic3Bpbm5lciIgdmlld0JveD0iLTQgLTQgMTUxIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48c3R5bGU+QGtleWZyYW1lcyBjb2xvcnN7MCUsdG97c3Ryb2tlOiMwMDc4ZmZ9NTAle3N0cm9rZTojMGUyZjVhfX1Aa2V5ZnJhbWVzIGRhc2h7MCUsdG97c3Ryb2tlLWRhc2hvZmZzZXQ6NTYwfTUwJXtzdHJva2UtZGFzaG9mZnNldDowfX1ALXdlYmtpdC1rZXlmcmFtZXMgY29sb3JzezAlLHRve3N0cm9rZTojMDA3OGZmfTUwJXtzdHJva2U6IzBlMmY1YX19QC13ZWJraXQta2V5ZnJhbWVzIGRhc2h7MCUsdG97c3Ryb2tlLWRhc2hvZmZzZXQ6NTYwfTUwJXtzdHJva2UtZGFzaG9mZnNldDowfX08L3N0eWxlPjxwYXRoIGQ9Ik0xMjEuNjYzIDkwLjYzOGMtMS43OTYgMC05OS4zMy0uNDk4LTEwMS40NzQtMS40NzhDOC42ODUgODMuODc3IDEuMjUgNzIuMTk2IDEuMjUgNTkuMzk2YzAtMTYuNjU2IDEyLjc5Ny0zMC42MSAyOS4wNTItMzIuMzIzIDcuNDktMTUuNzA2IDIzLjE4Ni0yNS43MDcgNDAuNzE0LTI1LjcwNyAyMC45OCAwIDM5LjIxNSAxNC43NTIgNDMuOTQ1IDM0LjkwNyAxNS4wOS4yNDUgMjcuMjkgMTIuNjMgMjcuMjkgMjcuODIyIDAgMTEuOTY4LTcuNzM4IDIyLjU1LTE5LjI1NiAyNi4zMyIgc3Ryb2tlLXdpZHRoPSI5IiBzdHJva2UtbGluZWNhcD0icm91bmQiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46Y2VudGVyOy13ZWJraXQtYW5pbWF0aW9uOmRhc2ggMnMgZWFzZS1pbi1vdXQgaW5maW5pdGUsY29sb3JzIDhzIGVhc2UtaW4tb3V0IGluZmluaXRlO2FuaW1hdGlvbjpkYXNoIDJzIGVhc2UtaW4tb3V0IGluZmluaXRlLGNvbG9ycyA4cyBlYXNlLWluLW91dCBpbmZpbml0ZSIgc3Ryb2tlLWRhc2hhcnJheT0iMjgwIi8+PC9zdmc+");background-repeat:no-repeat;background-position:50%;background-size:150px}.attachment-actions .button.edit-attachment,.attachment-info .edit-attachment{display:none}.global-transformations-preview{position:relative;max-width:600px}.global-transformations-spinner{display:none}.global-transformations-button.button-primary{display:none;position:absolute;z-index:100}.global-transformations-url{margin-bottom:5px;margin-top:5px}.global-transformations-url-transformation{max-width:100px;overflow:hidden;text-overflow:ellipsis;color:#51a3ff}.global-transformations-url-file{color:#f2d864}.global-transformations-url-link{display:block;padding:16px;background-color:#262c35;text-decoration:none;color:#fff;border-radius:6px;overflow:hidden;text-overflow:ellipsis}.global-transformations-url-link:hover{color:#888;text-decoration:underline}.cld-tax-order-list-item{border:1px solid #efefef;padding:4px;margin:0 0 -1px;background-color:#fff}.cld-tax-order-list-item.no-items{color:#888;text-align:center;display:none}.cld-tax-order-list-item.no-items:last-child{display:block}.cld-tax-order-list-item.ui-sortable-helper{box-shadow:0 2px 5px rgba(0,0,0,.2)}.cld-tax-order-list-item-placeholder{background-color:#efefef;height:45px;margin:0}.cld-tax-order-list-item-handle{cursor:grab;margin-right:4px;color:#999}.cld-tax-order-list-type{width:45%;display:inline-block;margin-right:8px}.cld-tax-order-list-type input{margin-right:4px!important}.cloudinary-media-library{position:relative;margin-left:-20px}@media screen and (max-width:782px){.cloudinary-media-library{margin-left:-10px}} \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/cloudinary.svg b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/cloudinary.svg new file mode 100644 index 000000000..0b2a81765 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/cloudinary.svg @@ -0,0 +1,13 @@ + + + +Generated by IcoMoon + + + + + + + + + \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.eot b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.eot new file mode 100644 index 000000000..8a843affc Binary files /dev/null and b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.eot differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.ttf b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.ttf new file mode 100644 index 000000000..71b6556b5 Binary files /dev/null and b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.ttf differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.woff b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.woff new file mode 100644 index 000000000..1fd991274 Binary files /dev/null and b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/fonts/cloudinary.woff differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/logo.svg b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/logo.svg new file mode 100644 index 000000000..5e651d548 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/logo.svg @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/_variables.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/_variables.scss new file mode 100644 index 000000000..78f9b9443 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/_variables.scss @@ -0,0 +1,7 @@ +// Colours +$color-green : #558b2f; +$color-red : #dd2c00; +$color-light-grey : #e5e5e5; +$color-white : #ffffff; +$color-blue : #0078ff; +$color-orange : #fd9d2c; diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_brand.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_brand.scss new file mode 100755 index 000000000..3e80e6340 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_brand.scss @@ -0,0 +1,95 @@ +@font-face { + font-family: 'cloudinary'; + src: url('fonts/cloudinary.eot?fj77m5'); + src: url('fonts/cloudinary.eot?fj77m5#iefix') format('embedded-opentype'), + url('fonts/cloudinary.ttf?fj77m5') format('truetype'), + url('fonts/cloudinary.woff?fj77m5') format('woff'), + url('fonts/cloudinary.svg?fj77m5#cloudinary') format('svg'); + font-weight: normal; + font-style: normal; +} + +.dashicons { + &-cloudinary { + /* use !important to prevent issues with browser extensions that change fonts */ + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + &:before { + font-family: 'cloudinary' !important; + content: '\e900'; + } + + &.success { + color: $color-green; + } + + &.error { + color: $color-red; + + &:before { + content: '\e901'; + } + } + + &.warning { + color: $color-orange; + + &:before { + content: '\e902'; + } + } + + &.warning { + color: $color-orange; + } + + &.warning { + color: $color-orange; + } + } +} + +.column-cld_status { + width: 5.5em; + + .dashicons { + &-cloudinary { + display: inline-block; + + &:before { + font-size: 1.8rem; + } + } + } +} + +.form-field, .form-table { + .error-notice { + display: none; + color: $color-red; + } + + input.cld-field:invalid { + border-color: $color-red; + + + .error-notice { + display: inline-block; + } + } +} + +.cloudinary-welcome { + background-image: url("logo.svg"); + background-repeat: no-repeat; + background-size: 153px; + background-position: top 12px right 20px; +} diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_global_transformations.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_global_transformations.scss new file mode 100644 index 000000000..729b1b18e --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_global_transformations.scss @@ -0,0 +1,51 @@ +.global { + &-transformations { + &-preview { + position : relative; + max-width : 600px; + } + + &-spinner { + display : none; + } + + &-button.button-primary { + display : none; + position : absolute; + z-index : 100; + } + + &-url { + margin-bottom : 5px; + margin-top : 5px; + + + &-transformation { + max-width : 100px; + overflow : hidden; + text-overflow : ellipsis; + color : #51A3FF; + } + + &-file { + color : #f2d864; + } + + &-link { + display : block; + padding : 16px; + background-color : #262c35; + text-decoration : none; + color : #fff; + border-radius : 6px; + overflow : hidden; + text-overflow : ellipsis; + + &:hover { + color : #888888; + text-decoration : underline; + } + } + } + } +} diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_media_library.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_media_library.scss new file mode 100644 index 000000000..a8f7455cc --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_media_library.scss @@ -0,0 +1,11 @@ +.cloudinary { + &-media { + &-library { + position: relative; + margin-left: -20px; + @media screen and (max-width: 782px) { + margin-left: -10px; + } + } + } +} diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_settings.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_settings.scss new file mode 100644 index 000000000..43e543615 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_settings.scss @@ -0,0 +1,210 @@ +.settings { + &-image { + max-width : 100%; + padding-top : 5px; + } + + &-tabs { + + > li { + display : inline-block; + + a { + padding : .6em; + + &.active { + background-color : #ffffff; + } + } + } + } + + &-tab { + + &-section { + padding : 20px 0 0 0; + max-width : 1030px; + position : relative; + + &.cloudinary-welcome & { + &-fields { + &-dashboard { + display : flex; + align-items : flex-start; + align-content : flex-start; + margin-top : 40px; + + &-description { + width : 55%; + margin : 0 auto 0 0; + } + + &-content { + width : 35%; + margin : 0 auto; + + .dashicons { + color : #9EA3A8; + } + } + } + } + + &-card { + margin-top : 0; + } + } + + &-fields { + .field-heading { + th { + display : block; + width : auto; + color : #23282d; + font-size : 1.1em; + margin : 1em 0; + } + + td { + display : none; + visibility : hidden; + } + } + + .regular-textarea { + width : 100%; + height : 60px; + } + + .dashicons { + text-decoration : none; + vertical-align : middle; + } + + a .dashicons { + color : #5F5F5F; + } + + &-dashboard { + &-error { + font-size : 1.2em; + color : #5F5F5F; + + .dashicons { + color : #AC0000; + } + + .button { + font-size : 1.1em; + height : 40px; + line-height : 40px; + padding-right : 40px; + padding-left : 40px; + } + } + + &-success { + font-size : 1.2em; + color : #23282d; + + &.expanded { + padding-top : 40px; + } + + .dashicons { + color : #4FB651; + } + + .button { + font-size : 1.1em; + height : 40px; + line-height : 40px; + padding-right : 40px; + padding-left : 40px; + } + + .description { + color : #5F5F5F; + font-weight : normal; + margin-top : 12px; + } + } + } + } + + &-card { + box-sizing : border-box; + border : 1px solid #E5E5E5; + background-color : #FFFFFF; + box-shadow : 0 1px 1px 0 rgba(0, 0, 0, 0.07); + padding : 20px 23px; + margin-top : 12px; + + .dashicons { + font-size : 1.4em; + } + + h2 { + font-size : 1.8em; + font-weight : normal; + margin-top : 0; + } + + &.pull-right { + width : 450px; + padding : 12px; + float : right; + position : relative; + z-index : 10; + + img.settings-image { + box-shadow : 0 2px 4px 0 rgba(0, 0, 0, 0.5); + border : 1px solid #979797; + margin-top : 12px; + } + + & h4, h3 { + margin-top : 0; + } + } + } + + .field-row-cloudinary_url, .field-row-signup { + display : block; + + td, th { + display : block; + width : auto; + padding : 10px 0 0; + + .sign-up { + vertical-align : baseline; + } + } + } + + &.connect { + .form-table { + display : inline-block; + width : auto; + max-width : 580px; + } + } + } + } + + &-valid { + color : $color-green; + font-size : 30px; + + &-field { + border-color : $color-green !important; + } + } + + &-invalid { + &-field { + border-color : $color-red !important; + } + } +} diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_sync.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_sync.scss new file mode 100644 index 000000000..d5536a061 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_sync.scss @@ -0,0 +1,74 @@ +.sync { + .spinner { + display : inline-block; + visibility : visible; + float : none; + margin : 0 5px 0 0; + } + + &-media { + + display : none; + + &-progress { + display : none; + + &-outer { + height : 20px; + margin : 20px 0 10px; + width : 500px; + background-color : $color-light-grey; + position : relative; + + .progress-bar { + width : 0; + height : 20px; + background-color : $color-green; + transition : width 250ms; + } + } + + &-notice { + color : $color-red; + } + } + + &-resource { + width : 100px; + display : inline-block; + } + + &-error { + color : $color-red; + } + } + + &-count { + font-weight : bold; + } + + &-details { + margin-top : 10px; + } + + .button.stop-sync, .button.start-sync { + display : none; + padding : 0 16px; + + .dashicons { + line-height : 2.2em; + } + } + + .progress-text { + padding : 12px 4px 12px 12px; + display : inline-block; + font-weight : bold; + } + + .completed { + max-width : 300px; + display : none; + } +} + diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_terms_order.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_terms_order.scss new file mode 100644 index 000000000..eeaf54b89 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_terms_order.scss @@ -0,0 +1,53 @@ +.cld { + &-tax { + &-order { + + + &-list { + &-item { + border: 1px solid #efefef; + padding: 4px; + margin: 0 0 -1px; + background-color: $color-white; + + &.no-items { + color: #888; + text-align: center; + display: none; + + &:last-child { + display: block; + } + } + + &.ui-sortable-helper { + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + } + + &-placeholder { + background-color: #efefef; + height: 45px; + margin: 0; + } + + &-handle { + cursor: grab; + margin-right: 4px; + color: #999; + } + + } + + &-type { + width: 45%; + display: inline-block; + margin-right: 8px; + + input { + margin-right: 4px !important; + } + } + } + } + } +} diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_widget.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_widget.scss new file mode 100644 index 000000000..5629e0a1c --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_widget.scss @@ -0,0 +1,25 @@ +.cloudinary { + &-widget { + height: 100%; + + &-wrapper { + height: 100%; + overflow: hidden; + background-image: url("data:image/svg+xml;base64,PHN2ZyBjbGFzcz0ic3Bpbm5lciIgdmlld0JveD0iLTQgLTQgMTUxIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbCiAgICAgIEBrZXlmcmFtZXMgY29sb3JzIHsKICAgICAgICAwJSB7IHN0cm9rZTogIzAwNzhGRjsgfQogICAgICAgICAgNTAlIHsgc3Ryb2tlOiAjMGUyZjVhOyB9CiAgICAgICAgICAxMDAlIHsgc3Ryb2tlOiAjMDA3OEZGOyB9CiAgICAgIH0KCiAgICAgIEBrZXlmcmFtZXMgZGFzaCB7CiAgICAgICAwJSB7IHN0cm9rZS1kYXNob2Zmc2V0OiA1NjA7IH0KICAgICAgIDUwJSB7CiAgICAgICAgICBzdHJva2UtZGFzaG9mZnNldDogMDsKICAgICAgIH0KICAgICAgIDEwMCUgeyAgIHN0cm9rZS1kYXNob2Zmc2V0OiA1NjA7IH0KICAgICAgfQogICAgICBALXdlYmtpdC1rZXlmcmFtZXMgY29sb3JzIHsKICAgICAgICAwJSB7IHN0cm9rZTogIzAwNzhmZjsgfQogICAgICAgICAgNTAlIHsgc3Ryb2tlOiAjMGUyZjVhOyB9CiAgICAgICAgICAxMDAlIHsgc3Ryb2tlOiAjMDA3OGZmOyB9CiAgICAgIH0KCiAgICAgIEAtd2Via2l0LWtleWZyYW1lcyBkYXNoIHsKICAgICAgIDAlIHsgc3Ryb2tlLWRhc2hvZmZzZXQ6IDU2MDsgfQogICAgICAgNTAlIHsKICAgICAgICAgIHN0cm9rZS1kYXNob2Zmc2V0OiAwOwogICAgICAgfQogICAgICAgMTAwJSB7ICAgc3Ryb2tlLWRhc2hvZmZzZXQ6IDU2MDsKICAgICAgIH0KICAgICAgfQogICAgICAucGF0aCB7CiAgICAgICAgc3Ryb2tlLWRhc2hhcnJheTogMjgwOwogICAgICAgIHN0cm9rZS1kYXNob2Zmc2V0OiAwOwogICAgICAgIHRyYW5zZm9ybS1vcmlnaW46IGNlbnRlcjsKICAgICAgICAtd2Via2l0LWFuaW1hdGlvbjoKICAgICAgICAgIGRhc2ggMnMgZWFzZS1pbi1vdXQgaW5maW5pdGUsIGNvbG9ycyA4cyBlYXNlLWluLW91dCBpbmZpbml0ZTsKICAgICAgICBhbmltYXRpb246CiAgICAgICAgICBkYXNoIDJzIGVhc2UtaW4tb3V0IGluZmluaXRlLCBjb2xvcnMgOHMgZWFzZS1pbi1vdXQgaW5maW5pdGU7CiAgICAgIH0KICAgIF1dPjwvc3R5bGU+CiAgPHBhdGggY2xhc3M9InBhdGgiIGQ9Ik0xMjEuNjYzIDkwLjYzOGMtMS43OTYgMC05OS4zMy0uNDk4LTEwMS40NzQtMS40NzhDOC42ODUgODMuODc3IDEuMjUgNzIuMTk2IDEuMjUgNTkuMzk2YzAtMTYuNjU2IDEyLjc5Ny0zMC42MSAyOS4wNTItMzIuMzIzIDcuNDktMTUuNzA2IDIzLjE4Ni0yNS43MDcgNDAuNzE0LTI1LjcwNyAyMC45OCAwIDM5LjIxNSAxNC43NTIgNDMuOTQ1IDM0LjkwNyAxNS4wOS4yNDUgMjcuMjkgMTIuNjMgMjcuMjkgMjcuODIyIDAgMTEuOTY4LTcuNzM4IDIyLjU1LTE5LjI1NiAyNi4zMyIgc3Ryb2tlLXdpZHRoPSI5IiBzdHJva2UtbGluZWNhcD0icm91bmQiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPgo8L3N2Zz4K"); + background-repeat: no-repeat; + background-position: center; + background-size: 150px; + } + } +} + +.attachment-info { + .edit-attachment { + display: none; + } +} +.attachment-actions{ + .button.edit-attachment{ + display: none; + } +} diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.eot b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.eot new file mode 100755 index 000000000..8a843affc Binary files /dev/null and b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.eot differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.svg b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.svg new file mode 100755 index 000000000..0b2a81765 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.svg @@ -0,0 +1,13 @@ + + + +Generated by IcoMoon + + + + + + + + + \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.ttf b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.ttf new file mode 100755 index 000000000..71b6556b5 Binary files /dev/null and b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.ttf differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.woff b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.woff new file mode 100755 index 000000000..1fd991274 Binary files /dev/null and b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/fonts/cloudinary.woff differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/logo-icon.svg b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/logo-icon.svg new file mode 100644 index 000000000..5c684461e --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/logo-icon.svg @@ -0,0 +1,69 @@ + + + + + + + + + + diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/logo.svg b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/logo.svg new file mode 100644 index 000000000..5e651d548 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/logo.svg @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/main.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/main.scss new file mode 100644 index 000000000..219223b3f --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/main.scss @@ -0,0 +1,10 @@ +// Vars +@import "variables"; +// Components +@import "components/brand"; +@import "components/settings"; +@import "components/sync"; +@import "components/widget"; +@import "components/global_transformations"; +@import "components/terms_order"; +@import "components/media_library"; diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/easyXDM.name.html b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/easyXDM.name.html deleted file mode 100644 index cc403b16e..000000000 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/easyXDM.name.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/easyxdm.swf b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/easyxdm.swf deleted file mode 100644 index 0a8200503..000000000 Binary files a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/easyxdm.swf and /dev/null differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/ajax-loader.gif b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/ajax-loader.gif deleted file mode 100644 index c69e93723..000000000 Binary files a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/ajax-loader.gif and /dev/null differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/ask_icon.png b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/ask_icon.png deleted file mode 100644 index 03b86d750..000000000 Binary files a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/ask_icon.png and /dev/null differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/edit_icon.png b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/edit_icon.png deleted file mode 100644 index 3028e58e1..000000000 Binary files a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/edit_icon.png and /dev/null differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/favicon.png b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/favicon.png deleted file mode 100644 index 710c90700..000000000 Binary files a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/favicon.png and /dev/null differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/logo.png b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/logo.png deleted file mode 100644 index ba8140b4f..000000000 Binary files a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/images/logo.png and /dev/null differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/instance.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/instance.php new file mode 100644 index 000000000..bc0c3edda --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/instance.php @@ -0,0 +1,31 @@ + {\n\n\tconst {attributes: {overwrite_transformations, transformations}, setAttributes} = props;\n\tif ( !transformations ) {\n\t\treturn null;\n\t}\n\treturn (\n\t\t\n\t\t\t {\n\t\t\t\t\tsetAttributes( {overwrite_transformations: value} );\n\t\t\t\t}}\n\t\t\t/>\n\t\t\n\t);\n};\n\nconst cldFilterBlocksEdit = ( BlockEdit ) => {\n\n\tconst EnhancedBlockEdit = function( props ) {\n\t\tconst {name} = props;\n\n\t\tlet inspectorControls;\n\t\tif ( 'core/image' === name || 'core/video' === name ) {\n\t\t\tinspectorControls = cldImageInspectorControls( props );\n\t\t}\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{inspectorControls}\n\t\t\t\t\n\t\t\t\n\t\t);\n\n\t};\n\n\treturn EnhancedBlockEdit;\n};\nconst cldImageInspectorControls = ( props ) => {\n\tconst {attributes: {id}, setAttributes, isSelected} = props;\n\n\tif ( !isSelected || !id ) {\n\t\treturn null;\n\t}\n\tlet media = wp.data.select( 'core' ).getMedia( id );\n\n\tif ( media && media.transformations ) {\n\t\tsetAttributes( {transformations: true} );\n\t}\n\treturn (\n\t\t\n\t\t\t\n\t\t\n\t);\n};\n\nwp.hooks.addFilter( 'editor.BlockEdit', 'cloudinary/filterEdit', cldFilterBlocksEdit, 20 );\n\nconst cldfilterBlocksSave = ( element, blockType, attributes ) => {\n\n\tif ( 'core/image' === blockType.name && attributes.overwrite_transformations ) {\n\n\t\tlet children = cloneElement( element.props.children );\n\t\tlet classname = children.props.children[ 0 ].props.className ? children.props.children[ 0 ].props.className : '';\n\t\tlet child = cloneElement( children.props.children[ 0 ], {className: classname + ' cld-overwrite'} );\n\t\tlet neChildren = cloneElement( children, {children: [ child, false ]} );\n\t\treturn cloneElement( element, {children: neChildren} );\n\n\t}\n\tif ( 'core/video' === blockType.name && attributes.overwrite_transformations ) {\n\t\tlet children = cloneElement( element.props.children[ 0 ], {className: ' cld-overwrite'} );\n\t\treturn cloneElement( element, {children: children} );\n\t}\n\n\treturn element;\n};\nwp.hooks.addFilter( 'blocks.getSaveElement', 'cloudinary/filterSave', cldfilterBlocksSave );\n","(function() { module.exports = this[\"wp\"][\"blockEditor\"]; }());","(function() { module.exports = this[\"wp\"][\"components\"]; }());","(function() { module.exports = this[\"wp\"][\"element\"]; }());","(function() { module.exports = this[\"wp\"][\"i18n\"]; }());"],"sourceRoot":""} \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/cloudinary.js b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/cloudinary.js index 8e632a8b3..af8feaaef 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/cloudinary.js +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/cloudinary.js @@ -1,158 +1 @@ -jQuery(function() { - var xdmConfig = jQuery('#cloudinary-library-config'); - if (xdmConfig.length == 0) return; - - function close_media_library() { - jQuery('#cloudinary-library').hide(); - jQuery('#wpcontent').css('margin-left', '165px'); - jQuery('#wpbody').css('height', 'auto').css('overflow', 'visible'); - } - - function add_to_gallery(json) { - var ajaxurl = xdmConfig.data("ajaxurl"); - var data = { - action: 'cloudinary_register_image', - url: json.src, - width: json.width, - height: json.height, - post_id: jQuery('#post_ID').val() - }; - jQuery.post(ajaxurl, data, function(json) { - if (json.error) { - alert(json.message); - } else { - jQuery('.cloudinary_message').html('Image successfully added to gallery'); - } - }); - } - - function insert_into_post(json) { - var src = json.src; - var href = json.href; - delete json.message; - delete json.src; - delete json.href; - var image = jQuery('').attr('src', src); - if (json.align && json.align != '') { - image.addClass('align' + json.align); - delete json.align; - } - jQuery.each(json, function(key, value) { - if (value != null && value != "") { - image.attr(key, value); - } - }); - var ajaxurl = xdmConfig.data("ajaxurl"); - var data = { - action: 'cloudinary_register_image', - url: src, - width: json.width, - height: json.height, - post_id: jQuery('#post_ID').val() - }; - if (typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && tinyMCE.activeEditor.selection) { - var html = tinyMCE.activeEditor.selection.getContent({format : 'html'}); - var match = html.match(/wp-image-(\d+)/); - if (match) data.attachment_id = match[1]; - } - - jQuery.post(ajaxurl, data, function(json) { - if (json.error) { - alert(json.message); - if (data.attachment_id) { - image.addClass('wp-image-' + data.attachment_id); - } - } else { - image.addClass('wp-image-' + json.attachment_id); - } - if (href && href != '') { - image = jQuery('').attr('href', href).append(image); - } - if (typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && tinyMCE.activeEditor.selection) { - tinyMCE.activeEditor.selection.setContent(jQuery('
').append(image).html()); - } else { - send_to_editor(jQuery('
').append(image).html()); - } - }); - } - - function update_window_dimensions() { - if (jQuery('#cloudinary-library').is(':visible')) { - var footer = jQuery('#footer').size() > 0 ? jQuery('#footer') : jQuery('#wpfooter'); - var body_height = jQuery('body').height() - jQuery(footer).outerHeight(true); - jQuery('#wpcontent').css('margin-left', '156px'); - jQuery('#wpbody').css('height', body_height).css('overflow', 'hidden'); - jQuery('#cloudinary-library, #cloudinary-library iframe').css('height', body_height); - } - } - - var controller = { - socket: new easyXDM.Socket({ - name: xdmConfig.data("base") + "/easyXDM.name.html", - swf: xdmConfig.data("base") + "/easyxdm.swf", - remote: xdmConfig.data("remote"), - remoteHelper: xdmConfig.data("remotehelper"), - container: "cloudinary-library", - props: {style: {width: "100%", height: "80%"}}, - onMessage: function(message, origin){ - var json = JSON.parse(message); - switch (json.message) { - case "insert_into_post": - close_media_library(); - insert_into_post(json); - break; - case "add_to_gallary": - case "add_to_gallery": - close_media_library(); - add_to_gallery(json); - break; - case "done": - close_media_library(); - break; - } - }, - onReady: function() { - controller.resizeWatcher(); - } - }), - currentWidth: 0, - currentHeight: 0, - resizeWatcher: function() { - jQuery(window).resize(update_window_dimensions); - } - }; - - function register_edit_image() { - var buttons = jQuery('.mce-toolbar-grp.mce-inline-toolbar-grp.mce-container.mce-panel'); - if (buttons.length > 0) { - var img = jQuery('').attr({src: xdmConfig.data("base")+"/images/edit_icon.png" , id: "cld_editbtn", width: "24", height: "24", title: "Cloudinary Edit Image"}).appendTo(buttons); - img.mousedown(function() { - var html = tinyMCE.activeEditor.selection.getContent({format : 'html'}); - jQuery(this).parents('.mce-toolbar-grp.mce-inline-toolbar-grp.mce-container.mce-panel').hide(); - controller.socket.postMessage(JSON.stringify({ - message: "edit_image", - html: html - })); - jQuery('#cloudinary-library').show(); - update_window_dimensions(); - }); - } else { - setTimeout(register_edit_image, 10); - } - } - if (typeof(tinyMCE) != 'undefined') - register_edit_image(); - - jQuery(document).on('click', '.cloudinary_add_media', function() { - jQuery('.cloudinary_message').html(''); - jQuery('#cloudinary-library').show(); - update_window_dimensions(); - return false; - }); - - var div = jQuery('
').hide().appendTo(jQuery('#wpbody-content')); - if (xdmConfig.data("autoshow")) { - div.show(); - setTimeout(function() { update_window_dimensions()}, 1); - } -}); +!function(e){var t={};function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{}};return e[n].call(s.exports,s,s.exports,i),s.l=!0,s.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)i.d(n,s,function(t){return e[t]}.bind(null,s));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=3)}([function(e,t){window,jQuery,jQuery(document).ready((function(e){e(document).on("tabs.init",(function(){var t=e(".settings-tab-trigger"),i=e(".settings-tab-section");e(this).on("click",".settings-tab-trigger",(function(n){var s=e(this),a=e(s.attr("href"));n.preventDefault(),t.removeClass("active"),i.removeClass("active"),s.addClass("active"),a.addClass("active"),e(document).trigger("settings.tabbed",s)})),e(".cld-field").not('[data-condition="false"]').each((function(){const t=e(this),i=t.data("condition");for(let n in i){const s=i[n],a=e("#field-"+n),o=t.closest("tr");a.on("change init",(function(){this.value===s||this.checked?o.show():o.hide()})),a.trigger("init")}})),e("#field-cloudinary_url").on("input change",(function(){let t=e(this),i=t.val();new RegExp(/^(cloudinary:\/\/){1}(\d)*[:]{1}[^:@]*[@]{1}[^@]*$/g).test(i)?(t.addClass("settings-valid-field"),t.removeClass("settings-invalid-field")):(t.removeClass("settings-valid-field"),t.addClass("settings-invalid-field"))})).trigger("change")})),e(".render-trigger[data-event]").each((function(){var t=e(this),i=t.data("event");t.trigger(i,this)}))}))},function(e,t){if(wp.media&&window.CLDN){wp.media.events.on("editor:image-edit",(function(e){e.metadata.cldoverwrite=null,e.image.className.split(" ").indexOf("cld-overwrite")>=0&&(e.metadata.cldoverwrite="true")})),wp.media.events.on("editor:image-update",(function(e){let t=e.image.className.split(" ");e.metadata.cldoverwrite&&-1===t.indexOf("cld-overwrite")?t.push("cld-overwrite"):!e.metadata.cldoverwrite&&t.indexOf("cld-overwrite")>=0&&delete t[t.indexOf("cld-overwrite")],e.image.className=t.join(" ")}));let e=null,t=wp.media.string.props;wp.media.string.props=function(i,n){return i.cldoverwrite&&(i.classes=["cld-overwrite"],e=!0),t(i,n)},wp.media.post=function(t,i){if("send-attachment-to-editor"===t){let t=wp.media.editor.get().state().get("selection").get(i.attachment);t.attributes.transformations&&(i.attachment.transformations=t.attributes.transformations),(i.html.indexOf("cld-overwrite")>-1||!0===e)&&(i.attachment.cldoverwrite=!0,e=null)}return wp.ajax.post(t,i)};wp.media.controller.Library;let i=wp.media.view.MediaFrame.Select,n=wp.media.view.MediaFrame.Post,s=wp.media.view.MediaFrame.ImageDetails,a=wp.media.view.MediaFrame.VideoDetails,o=wp.media.View.extend({tagName:"div",className:"cloudinary-widget",template:wp.template("cloudinary-dam"),active:!1,toolbar:null,frame:null,ready:function(){let e=this.controller,t=this.model.get("selection"),i=this.model.get("library"),n=wp.media.model.Attachment;if(CLDN.mloptions.multiple=e.options.multiple,this.cid!==this.active){if(CLDN.mloptions.inline_container="#cloudinary-dam-"+e.cid,1===t.length){var s=n.get(t.models[0].id);void 0!==s.attributes.public_id&&(CLDN.mloptions.asset={resource_id:s.attributes.public_id})}else CLDN.mloptions.asset=null;window.ml=cloudinary.openMediaLibrary(CLDN.mloptions,{insertHandler:function(s){for(let a=0;a=100&&void 0!==e.started?(this.submitButton.style.display=this.hide,this.stopButton.style.display=this.show):e.pending>0?(this.submitButton.style.display=this.show,this.stopButton.style.display=this.hide):e.processing>0?this.stopButton.style.display=this.show:this.stopButton.style.display=this.hide,e.percent<100?(this.barSyncCount.innerText=e.total,this.progressCount.innerText=e.done,this.progress.style.display=this.show):(this.completed.style.display=this.show,this.progress.style.display=this.hide)},_start:function(e){e.preventDefault(),a.stopButton.style.display=a.show,a.submitButton.style.display=a.hide,a.pushAttachments()},_reset:function(e){a.submitButton.style.display=a.hide,a.getStatus()},_init:function(e){"undefined"!=typeof cloudinaryApi&&((document.attachEvent?"complete"===document.readyState:"loading"!==document.readyState)?e():document.addEventListener("DOMContentLoaded",e))}};var o=a;a._init((function(){a._reset(),a.submitButton.addEventListener("click",a._start),a.stopButton.addEventListener("click",a.stopSync)}));var r=i(1),l=i.n(r);const d={sample:{image:document.getElementById("transformation-sample-image"),video:document.getElementById("transformation-sample-video")},preview:{image:document.getElementById("sample-image"),video:document.getElementById("sample-video")},fields:document.getElementsByClassName("cld-field"),button:{image:document.getElementById("refresh-image-preview"),video:document.getElementById("refresh-video-preview")},spinner:{image:document.getElementById("image-loader"),video:document.getElementById("video-loader")},activeItem:null,elements:{image:[],video:[]},_placeItem:function(e){null!==e&&(e.style.display="block",e.style.visibility="visible",e.style.position="absolute",e.style.top=e.parentElement.clientHeight/2-e.clientHeight/2+"px",e.style.left=e.parentElement.clientWidth/2-e.clientWidth/2+"px")},_setLoading:function(e){this.button[e].style.display="block",this._placeItem(this.button[e]),this.preview[e].style.opacity="0.1"},_build:function(e){this.sample[e].innerHTML="",this.elements[e]=[];for(let t of this.fields){if(e!==t.dataset.context)continue;let i=t.value.trim();if(i.length){if("select-one"===t.type){if("none"===i)continue;i=t.dataset.meta+"_"+i}else{let e=t.dataset.context;i=this._transformations(i,e,!0)}i&&this.elements[e].push(i)}}let t="";this.elements[e].length&&(t="/"+this.elements[e].join(",").replace(/ /g,"%20")),this.sample[e].textContent=t,this.sample[e].parentElement.href="https://res.cloudinary.com/demo/"+this.sample[e].parentElement.innerText.trim().replace("../","").replace(/ /g,"%20")},_clearLoading:function(e){this.spinner[e].style.visibility="hidden",this.activeItem=null,this.preview[e].style.opacity=1},_refresh:function(e,t){e&&e.preventDefault();let i=this,n=CLD_GLOBAL_TRANSFORMATIONS[t].preview_url+i.elements[t].join(",")+CLD_GLOBAL_TRANSFORMATIONS[t].file;if(this.button[t].style.display="none",this._placeItem(this.spinner[t]),"image"===t){let e=new Image;e.onload=function(){i.preview[t].src=this.src,i._clearLoading(t),e.remove()},e.onerror=function(){alert(CLD_GLOBAL_TRANSFORMATIONS[t].error),i._clearLoading(t)},e.src=n}else{let e=i._transformations(i.elements[t].join(","),t);samplePlayer.source({publicId:"dog",transformation:e}),i._clearLoading(t)}},_transformations:function(e,t,i=!1){let n=CLD_GLOBAL_TRANSFORMATIONS[t].valid_types,s=null,a=e.split("/"),o=[];for(let e=0;et.makeItem(e)),e}onChange(t){super.onChange(t);let i=this.pickItem(t);if(i)if(e[this.props.slug].indexOf(i.id)>=0)this.makeItem(i);else{let e=jQuery('[data-item="'+i.id+'"]');e.length&&e.remove()}}pickItem(e){if("number"==typeof e){for(let t in this.state.availableTerms)if(this.state.availableTerms[t].id===e)return this.state.availableTerms[t]}else{let t;if(e.length>this.state.selectedTerms.length)for(let i in e)-1===this.state.selectedTerms.indexOf(e[i])&&(t=e[i]);else for(let i in this.state.selectedTerms)-1===e.indexOf(this.state.selectedTerms[i])&&(t=this.state.selectedTerms[i]);for(let e in this.state.availableTerms)if(this.state.availableTerms[e].name===t)return this.state.availableTerms[e]}}makeElement(e,t){return jQuery("#templ-term-item").html().replace(/{id}/g,e.id).replace(/{name}/g,e.name)}}return function(e){return t(n,e)}};wp.hooks.addFilter("editor.PostTaxonomyType","cld",i)}const m={wpWrap:document.getElementById("wpwrap"),wpContent:document.getElementById("wpbody-content"),libraryWrap:document.getElementById("cloudinary-embed"),_init:function(){let e=this;"undefined"!=typeof CLD_ML&&(cloudinary.openMediaLibrary(CLD_ML.mloptions,{insertHandler:function(e){alert("Import is not yet implemented.")}}),window.addEventListener("resize",(function(t){e._resize()})),e._resize())},_resize:function(){let e=getComputedStyle(this.wpContent);this.libraryWrap.style.height=this.wpWrap.offsetHeight-parseInt(e.getPropertyValue("padding-bottom"))+"px"}};var h=m;m._init();i(2);i.d(t,"cloudinary",(function(){return f}));window.$=window.jQuery;const f={settings:s.a,sync:o,widget:l.a,Global_Transformations:c,Terms_Order:p,Media_Library:h}}]); \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/easyXDM.min.js b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/easyXDM.min.js deleted file mode 100644 index 866079570..000000000 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/easyXDM.min.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * easyXDM - * http://easyxdm.net/ - * Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -(function(N,d,p,K,k,H){var b=this;var n=Math.floor(Math.random()*10000);var q=Function.prototype;var Q=/^((http.?:)\/\/([^:\/\s]+)(:\d+)*)/;var R=/[\-\w]+\/\.\.\//;var F=/([^:])\/\//g;var I="";var o={};var M=N.easyXDM;var U="easyXDM_";var E;var y=false;var i;var h;function C(X,Z){var Y=typeof X[Z];return Y=="function"||(!!(Y=="object"&&X[Z]))||Y=="unknown"}function u(X,Y){return !!(typeof(X[Y])=="object"&&X[Y])}function r(X){return Object.prototype.toString.call(X)==="[object Array]"}function c(){var Z="Shockwave Flash",ad="application/x-shockwave-flash";if(!t(navigator.plugins)&&typeof navigator.plugins[Z]=="object"){var ab=navigator.plugins[Z].description;if(ab&&!t(navigator.mimeTypes)&&navigator.mimeTypes[ad]&&navigator.mimeTypes[ad].enabledPlugin){i=ab.match(/\d+/g)}}if(!i){var Y;try{Y=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");i=Array.prototype.slice.call(Y.GetVariable("$version").match(/(\d+),(\d+),(\d+),(\d+)/),1);Y=null}catch(ac){}}if(!i){return false}var X=parseInt(i[0],10),aa=parseInt(i[1],10);h=X>9&&aa>0;return true}var v,x;if(C(N,"addEventListener")){v=function(Z,X,Y){Z.addEventListener(X,Y,false)};x=function(Z,X,Y){Z.removeEventListener(X,Y,false)}}else{if(C(N,"attachEvent")){v=function(X,Z,Y){X.attachEvent("on"+Z,Y)};x=function(X,Z,Y){X.detachEvent("on"+Z,Y)}}else{throw new Error("Browser not supported")}}var W=false,J=[],L;if("readyState" in d){L=d.readyState;W=L=="complete"||(~navigator.userAgent.indexOf("AppleWebKit/")&&(L=="loaded"||L=="interactive"))}else{W=!!d.body}function s(){if(W){return}W=true;for(var X=0;X')}else{ac=d.createElement("IFRAME");ac.name=Y.props.name}ac.id=ac.name=Y.props.name;delete Y.props.name;if(typeof Y.container=="string"){Y.container=d.getElementById(Y.container)}if(!Y.container){T(ac.style,{position:"absolute",top:"-2000px",left:"0px"});Y.container=d.body}var ab=Y.props.src;Y.props.src="javascript:false";T(ac,Y.props);ac.border=ac.frameBorder=0;ac.allowTransparency=true;Y.container.appendChild(ac);if(Y.onLoad){v(ac,"load",Y.onLoad)}if(Y.usePost){var aa=Y.container.appendChild(d.createElement("form")),X;aa.target=ac.name;aa.action=ab;aa.method="POST";if(typeof(Y.usePost)==="object"){for(var Z in Y.usePost){if(Y.usePost.hasOwnProperty(Z)){if(E){X=d.createElement('')}else{X=d.createElement("INPUT");X.name=Z}X.value=Y.usePost[Z];aa.appendChild(X)}}}aa.submit();aa.parentNode.removeChild(aa)}else{ac.src=ab}Y.props.src=ab;return ac}function V(aa,Z){if(typeof aa=="string"){aa=[aa]}var Y,X=aa.length;while(X--){Y=aa[X];Y=new RegExp(Y.substr(0,1)=="^"?Y:("^"+Y.replace(/(\*)/g,".$1").replace(/\?/g,".")+"$"));if(Y.test(Z)){return true}}return false}function l(Z){var ae=Z.protocol,Y;Z.isHost=Z.isHost||t(S.xdm_p);y=Z.hash||false;if(!Z.props){Z.props={}}if(!Z.isHost){Z.channel=S.xdm_c.replace(/["'<>\\]/g,"");Z.secret=S.xdm_s;Z.remote=S.xdm_e.replace(/["'<>\\]/g,"");ae=S.xdm_p;if(Z.acl&&!V(Z.acl,Z.remote)){throw new Error("Access denied for "+Z.remote)}}else{Z.remote=B(Z.remote);Z.channel=Z.channel||"default"+n++;Z.secret=Math.random().toString(16).substring(2);if(t(ae)){if(j(p.href)==j(Z.remote)){ae="4"}else{if(C(N,"postMessage")||C(d,"postMessage")){ae="1"}else{if(Z.swf&&C(N,"ActiveXObject")&&c()){ae="6"}else{if(navigator.product==="Gecko"&&"frameElement" in N&&navigator.userAgent.indexOf("WebKit")==-1){ae="5"}else{if(Z.remoteHelper){ae="2"}else{ae="0"}}}}}}}Z.protocol=ae;switch(ae){case"0":T(Z,{interval:100,delay:2000,useResize:true,useParent:false,usePolling:false},true);if(Z.isHost){if(!Z.local){var ac=p.protocol+"//"+p.host,X=d.body.getElementsByTagName("img"),ad;var aa=X.length;while(aa--){ad=X[aa];if(ad.src.substring(0,ac.length)===ac){Z.local=ad.src;break}}if(!Z.local){Z.local=N}}var ab={xdm_c:Z.channel,xdm_p:0};if(Z.local===N){Z.usePolling=true;Z.useParent=true;Z.local=p.protocol+"//"+p.host+p.pathname+p.search;ab.xdm_e=Z.local;ab.xdm_pa=1}else{ab.xdm_e=B(Z.local)}if(Z.container){Z.useResize=false;ab.xdm_po=1}Z.remote=P(Z.remote,ab)}else{T(Z,{channel:S.xdm_c,remote:S.xdm_e,useParent:!t(S.xdm_pa),usePolling:!t(S.xdm_po),useResize:Z.useParent?false:Z.useResize})}Y=[new o.stack.HashTransport(Z),new o.stack.ReliableBehavior({}),new o.stack.QueueBehavior({encode:true,maxLength:4000-Z.remote.length}),new o.stack.VerifyBehavior({initiate:Z.isHost})];break;case"1":Y=[new o.stack.PostMessageTransport(Z)];break;case"2":Z.remoteHelper=B(Z.remoteHelper);Y=[new o.stack.NameTransport(Z),new o.stack.QueueBehavior(),new o.stack.VerifyBehavior({initiate:Z.isHost})];break;case"3":Y=[new o.stack.NixTransport(Z)];break;case"4":Y=[new o.stack.SameOriginTransport(Z)];break;case"5":Y=[new o.stack.FrameElementTransport(Z)];break;case"6":if(!i){c()}Y=[new o.stack.FlashTransport(Z)];break}Y.push(new o.stack.QueueBehavior({lazy:Z.lazy,remove:true}));return Y}function D(aa){var ab,Z={incoming:function(ad,ac){this.up.incoming(ad,ac)},outgoing:function(ac,ad){this.down.outgoing(ac,ad)},callback:function(ac){this.up.callback(ac)},init:function(){this.down.init()},destroy:function(){this.down.destroy()}};for(var Y=0,X=aa.length;Y<\/script>')}}};(function(){var X={};o.Fn={set:function(Y,Z){X[Y]=Z},get:function(Z,Y){var aa=X[Z];if(Y){delete X[Z]}return aa}}}());o.Socket=function(Y){var X=D(l(Y).concat([{incoming:function(ab,aa){Y.onMessage(ab,aa)},callback:function(aa){if(Y.onReady){Y.onReady(aa)}}}])),Z=j(Y.remote);this.origin=j(Y.remote);this.destroy=function(){X.destroy()};this.postMessage=function(aa){X.outgoing(aa,Z)};X.init()};o.Rpc=function(Z,Y){if(Y.local){for(var ab in Y.local){if(Y.local.hasOwnProperty(ab)){var aa=Y.local[ab];if(typeof aa==="function"){Y.local[ab]={method:aa}}}}}var X=D(l(Z).concat([new o.stack.RpcBehavior(this,Y),{callback:function(ac){if(Z.onReady){Z.onReady(ac)}}}]));this.origin=j(Z.remote);this.destroy=function(){X.destroy()};X.init()};o.stack.SameOriginTransport=function(Y){var Z,ab,aa,X;return(Z={outgoing:function(ad,ae,ac){aa(ad);if(ac){ac()}},destroy:function(){if(ab){ab.parentNode.removeChild(ab);ab=null}},onDOMReady:function(){X=j(Y.remote);if(Y.isHost){T(Y.props,{src:P(Y.remote,{xdm_e:p.protocol+"//"+p.host+p.pathname,xdm_c:Y.channel,xdm_p:4}),name:U+Y.channel+"_provider"});ab=A(Y);o.Fn.set(Y.channel,function(ac){aa=ac;K(function(){Z.up.callback(true)},0);return function(ad){Z.up.incoming(ad,X)}})}else{aa=m().Fn.get(Y.channel,true)(function(ac){Z.up.incoming(ac,X)});K(function(){Z.up.callback(true)},0)}},init:function(){G(Z.onDOMReady,Z)}})};o.stack.FlashTransport=function(aa){var ac,X,ab,ad,Y,ae;function af(ah,ag){K(function(){ac.up.incoming(ah,ad)},0)}function Z(ah){var ag=aa.swf+"?host="+aa.isHost;var aj="easyXDM_swf_"+Math.floor(Math.random()*10000);o.Fn.set("flash_loaded"+ah.replace(/[\-.]/g,"_"),function(){o.stack.FlashTransport[ah].swf=Y=ae.firstChild;var ak=o.stack.FlashTransport[ah].queue;for(var al=0;al"}return(ac={outgoing:function(ah,ai,ag){Y.postMessage(aa.channel,ah.toString());if(ag){ag()}},destroy:function(){try{Y.destroyChannel(aa.channel)}catch(ag){}Y=null;if(X){X.parentNode.removeChild(X);X=null}},onDOMReady:function(){ad=aa.remote;o.Fn.set("flash_"+aa.channel+"_init",function(){K(function(){ac.up.callback(true)})});o.Fn.set("flash_"+aa.channel+"_onMessage",af);aa.swf=B(aa.swf);var ah=z(aa.swf);var ag=function(){o.stack.FlashTransport[ah].init=true;Y=o.stack.FlashTransport[ah].swf;Y.createChannel(aa.channel,aa.secret,j(aa.remote),aa.isHost);if(aa.isHost){if(h&&aa.swfNoThrottle){T(aa.props,{position:"fixed",right:0,top:0,height:"20px",width:"20px"})}T(aa.props,{src:P(aa.remote,{xdm_e:j(p.href),xdm_c:aa.channel,xdm_p:6,xdm_s:aa.secret}),name:U+aa.channel+"_provider"});X=A(aa)}};if(o.stack.FlashTransport[ah]&&o.stack.FlashTransport[ah].init){ag()}else{if(!o.stack.FlashTransport[ah]){o.stack.FlashTransport[ah]={queue:[ag]};Z(ah)}else{o.stack.FlashTransport[ah].queue.push(ag)}}},init:function(){G(ac.onDOMReady,ac)}})};o.stack.PostMessageTransport=function(aa){var ac,ad,Y,Z;function X(ae){if(ae.origin){return j(ae.origin)}if(ae.uri){return j(ae.uri)}if(ae.domain){return p.protocol+"//"+ae.domain}throw"Unable to retrieve the origin of the event"}function ab(af){var ae=X(af);if(ae==Z&&af.data.substring(0,aa.channel.length+1)==aa.channel+" "){ac.up.incoming(af.data.substring(aa.channel.length+1),ae)}}return(ac={outgoing:function(af,ag,ae){Y.postMessage(aa.channel+" "+af,ag||Z);if(ae){ae()}},destroy:function(){x(N,"message",ab);if(ad){Y=null;ad.parentNode.removeChild(ad);ad=null}},onDOMReady:function(){Z=j(aa.remote);if(aa.isHost){var ae=function(af){if(af.data==aa.channel+"-ready"){Y=("postMessage" in ad.contentWindow)?ad.contentWindow:ad.contentWindow.document;x(N,"message",ae);v(N,"message",ab);K(function(){ac.up.callback(true)},0)}};v(N,"message",ae);T(aa.props,{src:P(aa.remote,{xdm_e:j(p.href),xdm_c:aa.channel,xdm_p:1}),name:U+aa.channel+"_provider"});ad=A(aa)}else{v(N,"message",ab);Y=("postMessage" in N.parent)?N.parent:N.parent.document;Y.postMessage(aa.channel+"-ready",Z);K(function(){ac.up.callback(true)},0)}},init:function(){G(ac.onDOMReady,ac)}})};o.stack.FrameElementTransport=function(Y){var Z,ab,aa,X;return(Z={outgoing:function(ad,ae,ac){aa.call(this,ad);if(ac){ac()}},destroy:function(){if(ab){ab.parentNode.removeChild(ab);ab=null}},onDOMReady:function(){X=j(Y.remote);if(Y.isHost){T(Y.props,{src:P(Y.remote,{xdm_e:j(p.href),xdm_c:Y.channel,xdm_p:5}),name:U+Y.channel+"_provider"});ab=A(Y);ab.fn=function(ac){delete ab.fn;aa=ac;K(function(){Z.up.callback(true)},0);return function(ad){Z.up.incoming(ad,X)}}}else{if(d.referrer&&j(d.referrer)!=S.xdm_e){N.top.location=S.xdm_e}aa=N.frameElement.fn(function(ac){Z.up.incoming(ac,X)});Z.up.callback(true)}},init:function(){G(Z.onDOMReady,Z)}})};o.stack.NameTransport=function(ab){var ac;var ae,ai,aa,ag,ah,Y,X;function af(al){var ak=ab.remoteHelper+(ae?"#_3":"#_2")+ab.channel;ai.contentWindow.sendMessage(al,ak)}function ad(){if(ae){if(++ag===2||!ae){ac.up.callback(true)}}else{af("ready");ac.up.callback(true)}}function aj(ak){ac.up.incoming(ak,Y)}function Z(){if(ah){K(function(){ah(true)},0)}}return(ac={outgoing:function(al,am,ak){ah=ak;af(al)},destroy:function(){ai.parentNode.removeChild(ai);ai=null;if(ae){aa.parentNode.removeChild(aa);aa=null}},onDOMReady:function(){ae=ab.isHost;ag=0;Y=j(ab.remote);ab.local=B(ab.local);if(ae){o.Fn.set(ab.channel,function(al){if(ae&&al==="ready"){o.Fn.set(ab.channel,aj);ad()}});X=P(ab.remote,{xdm_e:ab.local,xdm_c:ab.channel,xdm_p:2});T(ab.props,{src:X+"#"+ab.channel,name:U+ab.channel+"_provider"});aa=A(ab)}else{ab.remoteHelper=ab.remote;o.Fn.set(ab.channel,aj)}var ak=function(){var al=ai||this;x(al,"load",ak);o.Fn.set(ab.channel+"_load",Z);(function am(){if(typeof al.contentWindow.sendMessage=="function"){ad()}else{K(am,50)}}())};ai=A({props:{src:ab.local+"#_4"+ab.channel},onLoad:ak})},init:function(){G(ac.onDOMReady,ac)}})};o.stack.HashTransport=function(Z){var ac;var ah=this,af,aa,X,ad,am,ab,al;var ag,Y;function ak(ao){if(!al){return}var an=Z.remote+"#"+(am++)+"_"+ao;((af||!ag)?al.contentWindow:al).location=an}function ae(an){ad=an;ac.up.incoming(ad.substring(ad.indexOf("_")+1),Y)}function aj(){if(!ab){return}var an=ab.location.href,ap="",ao=an.indexOf("#");if(ao!=-1){ap=an.substring(ao)}if(ap&&ap!=ad){ae(ap)}}function ai(){aa=setInterval(aj,X)}return(ac={outgoing:function(an,ao){ak(an)},destroy:function(){N.clearInterval(aa);if(af||!ag){al.parentNode.removeChild(al)}al=null},onDOMReady:function(){af=Z.isHost;X=Z.interval;ad="#"+Z.channel;am=0;ag=Z.useParent;Y=j(Z.remote);if(af){T(Z.props,{src:Z.remote,name:U+Z.channel+"_provider"});if(ag){Z.onLoad=function(){ab=N;ai();ac.up.callback(true)}}else{var ap=0,an=Z.delay/50;(function ao(){if(++ap>an){throw new Error("Unable to reference listenerwindow")}try{ab=al.contentWindow.frames[U+Z.channel+"_consumer"]}catch(aq){}if(ab){ai();ac.up.callback(true)}else{K(ao,50)}}())}al=A(Z)}else{ab=N;ai();if(ag){al=parent;ac.up.callback(true)}else{T(Z,{props:{src:Z.remote+"#"+Z.channel+new Date(),name:U+Z.channel+"_consumer"},onLoad:function(){ac.up.callback(true)}});al=A(Z)}}},init:function(){G(ac.onDOMReady,ac)}})};o.stack.ReliableBehavior=function(Y){var aa,ac;var ab=0,X=0,Z="";return(aa={incoming:function(af,ad){var ae=af.indexOf("_"),ag=af.substring(0,ae).split(",");af=af.substring(ae+1);if(ag[0]==ab){Z="";if(ac){ac(true);ac=null}}if(af.length>0){aa.down.outgoing(ag[1]+","+ab+"_"+Z,ad);if(X!=ag[1]){X=ag[1];aa.up.incoming(af,ad)}}},outgoing:function(af,ad,ae){Z=af;ac=ae;aa.down.outgoing(X+","+(++ab)+"_"+af,ad)}})};o.stack.QueueBehavior=function(Z){var ac,ad=[],ag=true,aa="",af,X=0,Y=false,ab=false;function ae(){if(Z.remove&&ad.length===0){w(ac);return}if(ag||ad.length===0||af){return}ag=true;var ah=ad.shift();ac.down.outgoing(ah.data,ah.origin,function(ai){ag=false;if(ah.callback){K(function(){ah.callback(ai)},0)}ae()})}return(ac={init:function(){if(t(Z)){Z={}}if(Z.maxLength){X=Z.maxLength;ab=true}if(Z.lazy){Y=true}else{ac.down.init()}},callback:function(ai){ag=false;var ah=ac.up;ae();ah.callback(ai)},incoming:function(ak,ai){if(ab){var aj=ak.indexOf("_"),ah=parseInt(ak.substring(0,aj),10);aa+=ak.substring(aj+1);if(ah===0){if(Z.encode){aa=k(aa)}ac.up.incoming(aa,ai);aa=""}}else{ac.up.incoming(ak,ai)}},outgoing:function(al,ai,ak){if(Z.encode){al=H(al)}var ah=[],aj;if(ab){while(al.length!==0){aj=al.substring(0,X);al=al.substring(aj.length);ah.push(aj)}while((aj=ah.shift())){ad.push({data:ah.length+"_"+aj,origin:ai,callback:ah.length===0?ak:null})}}else{ad.push({data:al,origin:ai,callback:ak})}if(Y){ac.down.init()}else{ae()}},destroy:function(){af=true;ac.down.destroy()}})};o.stack.VerifyBehavior=function(ab){var ac,aa,Y,Z=false;function X(){aa=Math.random().toString(16).substring(2);ac.down.outgoing(aa)}return(ac={incoming:function(af,ad){var ae=af.indexOf("_");if(ae===-1){if(af===aa){ac.up.callback(true)}else{if(!Y){Y=af;if(!ab.initiate){X()}ac.down.outgoing(af)}}}else{if(af.substring(0,ae)===Y){ac.up.incoming(af.substring(ae+1),ad)}}},outgoing:function(af,ad,ae){ac.down.outgoing(aa+"_"+af,ad,ae)},callback:function(ad){if(ab.initiate){X()}}})};o.stack.RpcBehavior=function(ad,Y){var aa,af=Y.serializer||O();var ae=0,ac={};function X(ag){ag.jsonrpc="2.0";aa.down.outgoing(af.stringify(ag))}function ab(ag,ai){var ah=Array.prototype.slice;return function(){var aj=arguments.length,al,ak={method:ai};if(aj>0&&typeof arguments[aj-1]==="function"){if(aj>1&&typeof arguments[aj-2]==="function"){al={success:arguments[aj-2],error:arguments[aj-1]};ak.params=ah.call(arguments,0,aj-2)}else{al={success:arguments[aj-1]};ak.params=ah.call(arguments,0,aj-1)}ac[""+(++ae)]=al;ak.id=ae}else{ak.params=ah.call(arguments,0)}if(ag.namedParams&&ak.params.length===1){ak.params=ak.params[0]}X(ak)}}function Z(an,am,ai,al){if(!ai){if(am){X({id:am,error:{code:-32601,message:"Procedure not found."}})}return}var ak,ah;if(am){ak=function(ao){ak=q;X({id:am,result:ao})};ah=function(ao,ap){ah=q;var aq={id:am,error:{code:-32099,message:ao}};if(ap){aq.error.data=ap}X(aq)}}else{ak=ah=q}if(!r(al)){al=[al]}try{var ag=ai.method.apply(ai.scope,al.concat([ak,ah]));if(!t(ag)){ak(ag)}}catch(aj){ah(aj.message)}}return(aa={incoming:function(ah,ag){var ai=af.parse(ah);if(ai.method){if(Y.handle){Y.handle(ai,X)}else{Z(ai.method,ai.id,Y.local[ai.method],ai.params)}}else{var aj=ac[ai.id];if(ai.error){if(aj.error){aj.error(ai.error)}}else{if(aj.success){aj.success(ai.result)}}delete ac[ai.id]}},init:function(){if(Y.remote){for(var ag in Y.remote){if(Y.remote.hasOwnProperty(ag)){ad[ag]=ab(Y.remote[ag],ag)}}}aa.down.init()},destroy:function(){for(var ag in Y.remote){if(Y.remote.hasOwnProperty(ag)&&ad.hasOwnProperty(ag)){delete ad[ag]}}aa.down.destroy()}})};b.easyXDM=o})(window,document,location,window.setTimeout,decodeURIComponent,encodeURIComponent); \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/jquery.bt.js b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/jquery.bt.js deleted file mode 100644 index 1dfed66d6..000000000 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/jquery.bt.js +++ /dev/null @@ -1,1242 +0,0 @@ -/* - * jQuery File Upload Plugin 3.7.1 - * - * Copyright 2010, Sebastian Tschan, AQUANTUM - * Licensed under the MIT license: - * http://creativecommons.org/licenses/MIT/ - * - * https://blueimp.net - * http://www.aquantum.de - */ - -/*jslint browser: true */ -/*global File, FileReader, FormData, unescape, jQuery */ - - -/* - * @name BeautyTips - * @desc a tooltips/baloon-help plugin for jQuery - * - * @author Jeff Robbins - Lullabot - http://www.lullabot.com - * @version 0.9.5 release candidate 1 (5/20/2009) - */ - -jQuery.bt = {version: '0.9.5-rc1'}; - -/* - * @type jQuery - * @cat Plugins/bt - * @requires jQuery v1.2+ (not tested on versions prior to 1.2.6) - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * Encourage development. If you use BeautyTips for anything cool - * or on a site that people have heard of, please drop me a note. - * - jeff ^at lullabot > com - * - * No guarantees, warranties, or promises of any kind - * - */ - -;(function($) { - /** - * @credit Inspired by Karl Swedberg's ClueTip - * (http://plugins.learningjquery.com/cluetip/), which in turn was inspired - * by Cody Lindley's jTip (http://www.codylindley.com) - * - * @fileoverview - * Beauty Tips is a jQuery tooltips plugin which uses the canvas drawing element - * in the HTML5 spec in order to dynamically draw tooltip "talk bubbles" around - * the descriptive help text associated with an item. This is in many ways - * similar to Google Maps which both provides similar talk-bubbles and uses the - * canvas element to draw them. - * - * The canvas element is supported in modern versions of FireFox, Safari, and - * Opera. However, Internet Explorer needs a separate library called ExplorerCanvas - * included on the page in order to support canvas drawing functions. ExplorerCanvas - * was created by Google for use with their web apps and you can find it here: - * http://excanvas.sourceforge.net/ - * - * Beauty Tips was written to be simple to use and pretty. All of its options - * are documented at the bottom of this file and defaults can be overwritten - * globally for the entire page, or individually on each call. - * - * By default each tooltip will be positioned on the side of the target element - * which has the most free space. This is affected by the scroll position and - * size of the current window, so each Beauty Tip is redrawn each time it is - * displayed. It may appear above an element at the bottom of the page, but when - * the page is scrolled down (and the element is at the top of the page) it will - * then appear below it. Additionally, positions can be forced or a preferred - * order can be defined. See examples below. - * - * To fix z-index problems in IE6, include the bgiframe plugin on your page - * http://plugins.jquery.com/project/bgiframe - BeautyTips will automatically - * recognize it and use it. - * - * BeautyTips also works with the hoverIntent plugin - * http://cherne.net/brian/resources/jquery.hoverIntent.html - * see hoverIntent example below for usage - * - * Usage - * The function can be called in a number of ways. - * $(selector).bt(); - * $(selector).bt('Content text'); - * $(selector).bt('Content text', {option1: value, option2: value}); - * $(selector).bt({option1: value, option2: value}); - * - * For more/better documentation and lots of examples, visit the demo page included with the distribution - * - */ - - jQuery.fn.bt = function(content, options) { - - if (typeof content != 'string') { - var contentSelect = true; - options = content; - content = false; - } - else { - var contentSelect = false; - } - - // if hoverIntent is installed, use that as default instead of hover - if (jQuery.fn.hoverIntent && jQuery.bt.defaults.trigger == 'hover') { - jQuery.bt.defaults.trigger = 'hoverIntent'; - } - - return this.each(function(index) { - - var opts = jQuery.extend(false, jQuery.bt.defaults, jQuery.bt.options, options); - - // clean up the options - opts.spikeLength = numb(opts.spikeLength); - opts.spikeGirth = numb(opts.spikeGirth); - opts.overlap = numb(opts.overlap); - - var ajaxTimeout = false; - - /** - * This is sort of the "starting spot" for the this.each() - * These are the init functions to handle the .bt() call - */ - - if (opts.killTitle) { - $(this).find('[title]').andSelf().each(function() { - if (!$(this).attr('bt-xTitle')) { - $(this).attr('bt-xTitle', $(this).attr('title')).attr('title', ''); - } - }); - } - - if (typeof opts.trigger == 'string') { - opts.trigger = [opts.trigger]; - } - if (opts.trigger[0] == 'hoverIntent') { - var hoverOpts = jQuery.extend(opts.hoverIntentOpts, { - over: function() { - this.btOn(); - }, - out: function() { - this.btOff(); - }}); - $(this).hoverIntent(hoverOpts); - - } - else if (opts.trigger[0] == 'hover') { - $(this).hover( - function() { - this.btOn(); - }, - function() { - this.btOff(); - } - ); - } - else if (opts.trigger[0] == 'now') { - // toggle the on/off right now - // note that 'none' gives more control (see below) - if ($(this).hasClass('bt-active')) { - this.btOff(); - } - else { - this.btOn(); - } - } - else if (opts.trigger[0] == 'none') { - // initialize the tip with no event trigger - // use javascript to turn on/off tip as follows: - // $('#selector').btOn(); - // $('#selector').btOff(); - } - else if (opts.trigger.length > 1 && opts.trigger[0] != opts.trigger[1]) { - $(this) - .bind(opts.trigger[0], function() { - this.btOn(); - }) - .bind(opts.trigger[1], function() { - this.btOff(); - }); - } - else { - // toggle using the same event - $(this).bind(opts.trigger[0], function() { - if ($(this).hasClass('bt-active')) { - this.btOff(); - } - else { - this.btOn(); - } - }); - } - - - /** - * The BIG TURN ON - * Any element that has been initiated - */ - this.btOn = function () { - if (typeof $(this).data('bt-box') == 'object') { - // if there's already a popup, remove it before creating a new one. - this.btOff(); - } - - // trigger preBuild function - // preBuild has no argument since the box hasn't been built yet - opts.preBuild.apply(this); - - // turn off other tips - $(jQuery.bt.vars.closeWhenOpenStack).btOff(); - - // add the class to the target element (for hilighting, for example) - // bt-active is always applied to all, but activeClass can apply another - $(this).addClass('bt-active ' + opts.activeClass); - - if (contentSelect && opts.ajaxPath == null) { - // bizarre, I know - if (opts.killTitle) { - // if we've killed the title attribute, it's been stored in 'bt-xTitle' so get it.. - $(this).attr('title', $(this).attr('bt-xTitle')); - } - // then evaluate the selector... title is now in place - content = $.isFunction(opts.contentSelector) ? opts.contentSelector.apply(this) : eval(opts.contentSelector); - if (opts.killTitle) { - // now remove the title again, so we don't get double tips - $(this).attr('title', ''); - } - } - - // ---------------------------------------------- - // All the Ajax(ish) stuff is in this next bit... - // ---------------------------------------------- - if (opts.ajaxPath != null && content == false) { - if (typeof opts.ajaxPath == 'object') { - var url = eval(opts.ajaxPath[0]); - url += opts.ajaxPath[1] ? ' ' + opts.ajaxPath[1] : ''; - } - else { - var url = opts.ajaxPath; - } - var off = url.indexOf(" "); - if ( off >= 0 ) { - var selector = url.slice(off, url.length); - url = url.slice(0, off); - } - - // load any data cached for the given ajax path - var cacheData = opts.ajaxCache ? $(document.body).data('btCache-' + url.replace(/\./g, '')) : null; - if (typeof cacheData == 'string') { - content = selector ? $("
").append(cacheData.replace(//g, "")).find(selector) : cacheData; - } - else { - var target = this; - - // set up the options - var ajaxOpts = jQuery.extend(false, - { - type: opts.ajaxType, - data: opts.ajaxData, - cache: opts.ajaxCache, - url: url, - complete: function(XMLHttpRequest, textStatus) { - if (textStatus == 'success' || textStatus == 'notmodified') { - if (opts.ajaxCache) { - $(document.body).data('btCache-' + url.replace(/\./g, ''), XMLHttpRequest.responseText); - } - ajaxTimeout = false; - content = selector ? - // Create a dummy div to hold the results - $("
") - // inject the contents of the document in, removing the scripts - // to avoid any 'Permission Denied' errors in IE - .append(XMLHttpRequest.responseText.replace(//g, "")) - - // Locate the specified elements - .find(selector) : - - // If not, just inject the full result - XMLHttpRequest.responseText; - - } - else { - if (textStatus == 'timeout') { - // if there was a timeout, we don't cache the result - ajaxTimeout = true; - } - content = opts.ajaxError.replace(/%error/g, XMLHttpRequest.statusText); - } - // if the user rolls out of the target element before the ajax request comes back, don't show it - if ($(target).hasClass('bt-active')) { - target.btOn(); - } - } - }, opts.ajaxOpts); - // do the ajax request - jQuery.ajax(ajaxOpts); - // load the throbber while the magic happens - content = opts.ajaxLoading; - } - } - // - - - // now we start actually figuring out where to place the tip - - // figure out how to compensate for the shadow, if present - var shadowMarginX = 0; // extra added to width to compensate for shadow - var shadowMarginY = 0; // extra added to height - var shadowShiftX = 0; // amount to shift the tip horizontally to allow for shadow - var shadowShiftY = 0; // amount to shift vertical - - if (opts.shadow && !shadowSupport()) { - // if browser doesn't support drop shadows, turn them off - opts.shadow = false; - // and bring in the noShadows options - jQuery.extend(opts, opts.noShadowOpts); - } - - if (opts.shadow) { - // figure out horizontal placement - if (opts.shadowBlur > Math.abs(opts.shadowOffsetX)) { - shadowMarginX = opts.shadowBlur * 2; - } - else { - shadowMarginX = opts.shadowBlur + Math.abs(opts.shadowOffsetX); - } - shadowShiftX = (opts.shadowBlur - opts.shadowOffsetX) > 0 ? opts.shadowBlur - opts.shadowOffsetX : 0; - - // now vertical - if (opts.shadowBlur > Math.abs(opts.shadowOffsetY)) { - shadowMarginY = opts.shadowBlur * 2; - } - else { - shadowMarginY = opts.shadowBlur + Math.abs(opts.shadowOffsetY); - } - shadowShiftY = (opts.shadowBlur - opts.shadowOffsetY) > 0 ? opts.shadowBlur - opts.shadowOffsetY : 0; - } - - if (opts.offsetParent){ - // if offsetParent is defined by user - var offsetParent = $(opts.offsetParent); - var offsetParentPos = offsetParent.offset(); - var pos = $(this).offset(); - var top = numb(pos.top) - numb(offsetParentPos.top) + numb($(this).css('margin-top')) - shadowShiftY; // IE can return 'auto' for margins - var left = numb(pos.left) - numb(offsetParentPos.left) + numb($(this).css('margin-left')) - shadowShiftX; - } - else { - // if the target element is absolutely positioned, use its parent's offsetParent instead of its own - var offsetParent = ($(this).css('position') == 'absolute') ? $(this).parents().eq(0).offsetParent() : $(this).offsetParent(); - var pos = $(this).btPosition(); - var top = numb(pos.top) + numb($(this).css('margin-top')) - shadowShiftY; // IE can return 'auto' for margins - var left = numb(pos.left) + numb($(this).css('margin-left')) - shadowShiftX; - } - - var width = $(this).btOuterWidth(); - var height = $(this).outerHeight(); - - if (typeof content == 'object') { - // if content is a DOM object (as opposed to text) - // use a clone, rather than removing the original element - // and ensure that it's visible - var original = content; - var clone = $(original).clone(true).show(); - // also store a reference to the original object in the clone data - // and a reference to the clone in the original - var origClones = $(original).data('bt-clones') || []; - origClones.push(clone); - $(original).data('bt-clones', origClones); - $(clone).data('bt-orig', original); - $(this).data('bt-content-orig', {original: original, clone: clone}); - content = clone; - } - if (typeof content == 'null' || content == '') { - // if content is empty, bail out... - return; - } - - // create the tip content div, populate it, and style it - var $text = $('
').append(content).css({padding: opts.padding, position: 'absolute', width: (opts.shrinkToFit ? 'auto' : opts.width), zIndex: opts.textzIndex, left: shadowShiftX, top: shadowShiftY}).css(opts.cssStyles); - // create the wrapping box which contains text and canvas - // put the content in it, style it, and append it to the same offset parent as the target - var $box = $('
').append($text).addClass(opts.cssClass).css({position: 'absolute', width: opts.width, zIndex: opts.wrapperzIndex, visibility:'hidden'}).appendTo(offsetParent); - - // use bgiframe to get around z-index problems in IE6 - // http://plugins.jquery.com/project/bgiframe - if (jQuery.fn.bgiframe) { - $text.bgiframe(); - $box.bgiframe(); - } - - $(this).data('bt-box', $box); - - // see if the text box will fit in the various positions - var scrollTop = numb($(document).scrollTop()); - var scrollLeft = numb($(document).scrollLeft()); - var docWidth = numb($(window).width()); - var docHeight = numb($(window).height()); - var winRight = scrollLeft + docWidth; - var winBottom = scrollTop + docHeight; - var space = new Object(); - var thisOffset = $(this).offset(); - space.top = thisOffset.top - scrollTop; - space.bottom = docHeight - ((thisOffset + height) - scrollTop); - space.left = thisOffset.left - scrollLeft; - space.right = docWidth - ((thisOffset.left + width) - scrollLeft); - var textOutHeight = numb($text.outerHeight()); - var textOutWidth = numb($text.btOuterWidth()); - if (opts.positions.constructor == String) { - opts.positions = opts.positions.replace(/ /, '').split(','); - } - if (opts.positions[0] == 'most') { - // figure out which is the largest - var position = 'top'; // prime the pump - for (var pig in space) { // <------- pigs in space! - position = space[pig] > space[position] ? pig : position; - } - } - else { - for (var x in opts.positions) { - var position = opts.positions[x]; - // @todo: acommodate shadow space in the following lines... - if ((position == 'left' || position == 'right') && space[position] > textOutWidth + opts.spikeLength) { - break; - } - else if ((position == 'top' || position == 'bottom') && space[position] > textOutHeight + opts.spikeLength) { - break; - } - } - } - - // horizontal (left) offset for the box - var horiz = left + ((width - textOutWidth) * .5); - // vertical (top) offset for the box - var vert = top + ((height - textOutHeight) * .5); - var points = new Array(); - var textTop, textLeft, textRight, textBottom, textTopSpace, textBottomSpace, textLeftSpace, textRightSpace, crossPoint, textCenter, spikePoint; - - // Yes, yes, this next bit really could use to be condensed - // each switch case is basically doing the same thing in slightly different ways - switch(position) { - - // =================== TOP ======================= - case 'top': - // spike on bottom - $text.css('margin-bottom', opts.spikeLength + 'px'); - $box.css({top: (top - $text.outerHeight(true)) + opts.overlap, left: horiz}); - // move text left/right if extends out of window - textRightSpace = (winRight - opts.windowMargin) - ($text.offset().left + $text.btOuterWidth(true)); - var xShift = shadowShiftX; - if (textRightSpace < 0) { - // shift it left - $box.css('left', (numb($box.css('left')) + textRightSpace) + 'px'); - xShift -= textRightSpace; - } - // we test left space second to ensure that left of box is visible - textLeftSpace = ($text.offset().left + numb($text.css('margin-left'))) - (scrollLeft + opts.windowMargin); - if (textLeftSpace < 0) { - // shift it right - $box.css('left', (numb($box.css('left')) - textLeftSpace) + 'px'); - xShift += textLeftSpace; - } - textTop = $text.btPosition().top + numb($text.css('margin-top')); - textLeft = $text.btPosition().left + numb($text.css('margin-left')); - textRight = textLeft + $text.btOuterWidth(); - textBottom = textTop + $text.outerHeight(); - textCenter = {x: textLeft + ($text.btOuterWidth()*opts.centerPointX), y: textTop + ($text.outerHeight()*opts.centerPointY)}; - // points[points.length] = {x: x, y: y}; - points[points.length] = spikePoint = {y: textBottom + opts.spikeLength, x: ((textRight-textLeft) * .5) + xShift, type: 'spike'}; - crossPoint = findIntersectX(spikePoint.x, spikePoint.y, textCenter.x, textCenter.y, textBottom); - // make sure that the crossPoint is not outside of text box boundaries - crossPoint.x = crossPoint.x < textLeft + opts.spikeGirth/2 + opts.cornerRadius ? textLeft + opts.spikeGirth/2 + opts.cornerRadius : crossPoint.x; - crossPoint.x = crossPoint.x > (textRight - opts.spikeGirth/2) - opts.cornerRadius ? (textRight - opts.spikeGirth/2) - opts.CornerRadius : crossPoint.x; - points[points.length] = {x: crossPoint.x - (opts.spikeGirth/2), y: textBottom, type: 'join'}; - points[points.length] = {x: textLeft, y: textBottom, type: 'corner'}; // left bottom corner - points[points.length] = {x: textLeft, y: textTop, type: 'corner'}; // left top corner - points[points.length] = {x: textRight, y: textTop, type: 'corner'}; // right top corner - points[points.length] = {x: textRight, y: textBottom, type: 'corner'}; // right bottom corner - points[points.length] = {x: crossPoint.x + (opts.spikeGirth/2), y: textBottom, type: 'join'}; - points[points.length] = spikePoint; - break; - - // =================== LEFT ======================= - case 'left': - // spike on right - $text.css('margin-right', opts.spikeLength + 'px'); - $box.css({top: vert + 'px', left: ((left - $text.btOuterWidth(true)) + opts.overlap) + 'px'}); - // move text up/down if extends out of window - textBottomSpace = (winBottom - opts.windowMargin) - ($text.offset().top + $text.outerHeight(true)); - var yShift = shadowShiftY; - if (textBottomSpace < 0) { - // shift it up - $box.css('top', (numb($box.css('top')) + textBottomSpace) + 'px'); - yShift -= textBottomSpace; - } - // we ensure top space second to ensure that top of box is visible - textTopSpace = ($text.offset().top + numb($text.css('margin-top'))) - (scrollTop + opts.windowMargin); - if (textTopSpace < 0) { - // shift it down - $box.css('top', (numb($box.css('top')) - textTopSpace) + 'px'); - yShift += textTopSpace; - } - textTop = $text.btPosition().top + numb($text.css('margin-top')); - textLeft = $text.btPosition().left + numb($text.css('margin-left')); - textRight = textLeft + $text.btOuterWidth(); - textBottom = textTop + $text.outerHeight(); - textCenter = {x: textLeft + ($text.btOuterWidth()*opts.centerPointX), y: textTop + ($text.outerHeight()*opts.centerPointY)}; - points[points.length] = spikePoint = {x: textRight + opts.spikeLength, y: ((textBottom-textTop) * .5) + yShift, type: 'spike'}; - crossPoint = findIntersectY(spikePoint.x, spikePoint.y, textCenter.x, textCenter.y, textRight); - // make sure that the crossPoint is not outside of text box boundaries - crossPoint.y = crossPoint.y < textTop + opts.spikeGirth/2 + opts.cornerRadius ? textTop + opts.spikeGirth/2 + opts.cornerRadius : crossPoint.y; - crossPoint.y = crossPoint.y > (textBottom - opts.spikeGirth/2) - opts.cornerRadius ? (textBottom - opts.spikeGirth/2) - opts.cornerRadius : crossPoint.y; - points[points.length] = {x: textRight, y: crossPoint.y + opts.spikeGirth/2, type: 'join'}; - points[points.length] = {x: textRight, y: textBottom, type: 'corner'}; // right bottom corner - points[points.length] = {x: textLeft, y: textBottom, type: 'corner'}; // left bottom corner - points[points.length] = {x: textLeft, y: textTop, type: 'corner'}; // left top corner - points[points.length] = {x: textRight, y: textTop, type: 'corner'}; // right top corner - points[points.length] = {x: textRight, y: crossPoint.y - opts.spikeGirth/2, type: 'join'}; - points[points.length] = spikePoint; - break; - - // =================== BOTTOM ======================= - case 'bottom': - // spike on top - $text.css('margin-top', opts.spikeLength + 'px'); - $box.css({top: (top + height) - opts.overlap, left: horiz}); - // move text up/down if extends out of window - textRightSpace = (winRight - opts.windowMargin) - ($text.offset().left + $text.btOuterWidth(true)); - var xShift = shadowShiftX; - if (textRightSpace < 0) { - // shift it left - $box.css('left', (numb($box.css('left')) + textRightSpace) + 'px'); - xShift -= textRightSpace; - } - // we ensure left space second to ensure that left of box is visible - textLeftSpace = ($text.offset().left + numb($text.css('margin-left'))) - (scrollLeft + opts.windowMargin); - if (textLeftSpace < 0) { - // shift it right - $box.css('left', (numb($box.css('left')) - textLeftSpace) + 'px'); - xShift += textLeftSpace; - } - textTop = $text.btPosition().top + numb($text.css('margin-top')); - textLeft = $text.btPosition().left + numb($text.css('margin-left')); - textRight = textLeft + $text.btOuterWidth(); - textBottom = textTop + $text.outerHeight(); - textCenter = {x: textLeft + ($text.btOuterWidth()*opts.centerPointX), y: textTop + ($text.outerHeight()*opts.centerPointY)}; - points[points.length] = spikePoint = {x: ((textRight-textLeft) * .5) + xShift, y: shadowShiftY, type: 'spike'}; - crossPoint = findIntersectX(spikePoint.x, spikePoint.y, textCenter.x, textCenter.y, textTop); - // make sure that the crossPoint is not outside of text box boundaries - crossPoint.x = crossPoint.x < textLeft + opts.spikeGirth/2 + opts.cornerRadius ? textLeft + opts.spikeGirth/2 + opts.cornerRadius : crossPoint.x; - crossPoint.x = crossPoint.x > (textRight - opts.spikeGirth/2) - opts.cornerRadius ? (textRight - opts.spikeGirth/2) - opts.cornerRadius : crossPoint.x; - points[points.length] = {x: crossPoint.x + opts.spikeGirth/2, y: textTop, type: 'join'}; - points[points.length] = {x: textRight, y: textTop, type: 'corner'}; // right top corner - points[points.length] = {x: textRight, y: textBottom, type: 'corner'}; // right bottom corner - points[points.length] = {x: textLeft, y: textBottom, type: 'corner'}; // left bottom corner - points[points.length] = {x: textLeft, y: textTop, type: 'corner'}; // left top corner - points[points.length] = {x: crossPoint.x - (opts.spikeGirth/2), y: textTop, type: 'join'}; - points[points.length] = spikePoint; - break; - - // =================== RIGHT ======================= - case 'right': - // spike on left - $text.css('margin-left', (opts.spikeLength + 'px')); - $box.css({top: vert + 'px', left: ((left + width) - opts.overlap) + 'px'}); - // move text up/down if extends out of window - textBottomSpace = (winBottom - opts.windowMargin) - ($text.offset().top + $text.outerHeight(true)); - var yShift = shadowShiftY; - if (textBottomSpace < 0) { - // shift it up - $box.css('top', (numb($box.css('top')) + textBottomSpace) + 'px'); - yShift -= textBottomSpace; - } - // we ensure top space second to ensure that top of box is visible - textTopSpace = ($text.offset().top + numb($text.css('margin-top'))) - (scrollTop + opts.windowMargin); - if (textTopSpace < 0) { - // shift it down - $box.css('top', (numb($box.css('top')) - textTopSpace) + 'px'); - yShift += textTopSpace; - } - textTop = $text.btPosition().top + numb($text.css('margin-top')); - textLeft = $text.btPosition().left + numb($text.css('margin-left')); - textRight = textLeft + $text.btOuterWidth(); - textBottom = textTop + $text.outerHeight(); - textCenter = {x: textLeft + ($text.btOuterWidth()*opts.centerPointX), y: textTop + ($text.outerHeight()*opts.centerPointY)}; - points[points.length] = spikePoint = {x: shadowShiftX, y: ((textBottom-textTop) * .5) + yShift, type: 'spike'}; - crossPoint = findIntersectY(spikePoint.x, spikePoint.y, textCenter.x, textCenter.y, textLeft); - // make sure that the crossPoint is not outside of text box boundaries - crossPoint.y = crossPoint.y < textTop + opts.spikeGirth/2 + opts.cornerRadius ? textTop + opts.spikeGirth/2 + opts.cornerRadius : crossPoint.y; - crossPoint.y = crossPoint.y > (textBottom - opts.spikeGirth/2) - opts.cornerRadius ? (textBottom - opts.spikeGirth/2) - opts.cornerRadius : crossPoint.y; - points[points.length] = {x: textLeft, y: crossPoint.y - opts.spikeGirth/2, type: 'join'}; - points[points.length] = {x: textLeft, y: textTop, type: 'corner'}; // left top corner - points[points.length] = {x: textRight, y: textTop, type: 'corner'}; // right top corner - points[points.length] = {x: textRight, y: textBottom, type: 'corner'}; // right bottom corner - points[points.length] = {x: textLeft, y: textBottom, type: 'corner'}; // left bottom corner - points[points.length] = {x: textLeft, y: crossPoint.y + opts.spikeGirth/2, type: 'join'}; - points[points.length] = spikePoint; - break; - } // - - var canvas = document.createElement('canvas'); - $(canvas).attr('width', (numb($text.btOuterWidth(true)) + opts.strokeWidth*2 + shadowMarginX)).attr('height', (numb($text.outerHeight(true)) + opts.strokeWidth*2 + shadowMarginY)).appendTo($box).css({position: 'absolute', zIndex: opts.boxzIndex}); - - - // if excanvas is set up, we need to initialize the new canvas element - if (typeof G_vmlCanvasManager != 'undefined') { - canvas = G_vmlCanvasManager.initElement(canvas); - } - - if (opts.cornerRadius > 0) { - // round the corners! - var newPoints = new Array(); - var newPoint; - for (var i=0; i 0) { - $box.css('top', (numb($box.css('top')) - (opts.shadowOffsetX + opts.shadowBlur - shadowOverlap))); - } - break; - case 'right': - if (shadowShiftX - shadowOverlap > 0) { - $box.css('left', (numb($box.css('left')) + shadowShiftX - shadowOverlap)); - } - break; - case 'bottom': - if (shadowShiftY - shadowOverlap > 0) { - $box.css('top', (numb($box.css('top')) + shadowShiftY - shadowOverlap)); - } - break; - case 'left': - if (opts.shadowOffsetY + opts.shadowBlur - shadowOverlap > 0) { - $box.css('left', (numb($box.css('left')) - (opts.shadowOffsetY + opts.shadowBlur - shadowOverlap))); - } - break; - } - } - - drawIt.apply(ctx, [points], opts.strokeWidth); - ctx.fillStyle = opts.fill; - if (opts.shadow) { - ctx.shadowOffsetX = opts.shadowOffsetX; - ctx.shadowOffsetY = opts.shadowOffsetY; - ctx.shadowBlur = opts.shadowBlur; - ctx.shadowColor = opts.shadowColor; - } - ctx.closePath(); - ctx.fill(); - if (opts.strokeWidth > 0) { - ctx.shadowColor = 'rgba(0, 0, 0, 0)'; //remove shadow from stroke - ctx.lineWidth = opts.strokeWidth; - ctx.strokeStyle = opts.strokeStyle; - ctx.beginPath(); - drawIt.apply(ctx, [points], opts.strokeWidth); - ctx.closePath(); - ctx.stroke(); - } - - // trigger preShow function - // function receives the box element (the balloon wrapper div) as an argument - opts.preShow.apply(this, [$box[0]]); - - // switch from visibility: hidden to display: none so we can run animations - $box.css({display:'none', visibility: 'visible'}); - - // Here's where we show the tip - opts.showTip.apply(this, [$box[0]]); - - if (opts.overlay) { - // EXPERIMENTAL AND FOR TESTING ONLY!!!! - var overlay = $('
').css({ - position: 'absolute', - backgroundColor: 'blue', - top: top, - left: left, - width: width, - height: height, - opacity: '.2' - }).appendTo(offsetParent); - $(this).data('overlay', overlay); - } - - if ((opts.ajaxPath != null && opts.ajaxCache == false) || ajaxTimeout) { - // if ajaxCache is not enabled or if there was a server timeout, - // remove the content variable so it will be loaded again from server - content = false; - } - - // stick this element into the clickAnywhereToClose stack - if (opts.clickAnywhereToClose) { - jQuery.bt.vars.clickAnywhereStack.push(this); - $(document).click(jQuery.bt.docClick); - } - - // stick this element into the closeWhenOthersOpen stack - if (opts.closeWhenOthersOpen) { - jQuery.bt.vars.closeWhenOpenStack.push(this); - } - - // trigger postShow function - // function receives the box element (the balloon wrapper div) as an argument - opts.postShow.apply(this, [$box[0]]); - - - }; // - - this.btOff = function() { - - var box = $(this).data('bt-box'); - - // trigger preHide function - // function receives the box element (the balloon wrapper div) as an argument - opts.preHide.apply(this, [box]); - - var i = this; - - // set up the stuff to happen AFTER the tip is hidden - i.btCleanup = function(){ - var box = $(i).data('bt-box'); - var contentOrig = $(i).data('bt-content-orig'); - var overlay = $(i).data('bt-overlay'); - if (typeof box == 'object') { - $(box).remove(); - $(i).removeData('bt-box'); - } - if (typeof contentOrig == 'object') { - var clones = $(contentOrig.original).data('bt-clones'); - $(contentOrig).data('bt-clones', arrayRemove(clones, contentOrig.clone)); - } - if (typeof overlay == 'object') { - $(overlay).remove(); - $(i).removeData('bt-overlay'); - } - - // remove this from the stacks - jQuery.bt.vars.clickAnywhereStack = arrayRemove(jQuery.bt.vars.clickAnywhereStack, i); - jQuery.bt.vars.closeWhenOpenStack = arrayRemove(jQuery.bt.vars.closeWhenOpenStack, i); - - // remove the 'bt-active' and activeClass classes from target - $(i).removeClass('bt-active ' + opts.activeClass); - - // trigger postHide function - // no box argument since it has been removed from the DOM - opts.postHide.apply(i); - - } - - opts.hideTip.apply(this, [box, i.btCleanup]); - - }; // - - var refresh = this.btRefresh = function() { - this.btOff(); - this.btOn(); - }; - - }); // - - - function drawIt(points, strokeWidth) { - this.moveTo(points[0].x, points[0].y); - for (i=1;i - - /** - * For odd stroke widths, round to the nearest .5 pixel to avoid antialiasing - * http://developer.mozilla.org/en/Canvas_tutorial/Applying_styles_and_colors - */ - function round5(num, strokeWidth) { - var ret; - strokeWidth = numb(strokeWidth); - if (strokeWidth%2) { - ret = num; - } - else { - ret = Math.round(num - .5) + .5; - } - return ret; - }; // - - /** - * Ensure that a number is a number... or zero - */ - function numb(num) { - return parseInt(num) || 0; - }; // - - /** - * Remove an element from an array - */ - function arrayRemove(arr, elem) { - var x, newArr = new Array(); - for (x in arr) { - if (arr[x] != elem) { - newArr.push(arr[x]); - } - } - return newArr; - }; // - - /** - * Does the current browser support canvas? - * This is a variation of http://code.google.com/p/browser-canvas-support/ - */ - function canvasSupport() { - var canvas_compatible = false; - try { - canvas_compatible = !!(document.createElement('canvas').getContext('2d')); // S60 - } catch(e) { - canvas_compatible = !!(document.createElement('canvas').getContext); // IE - } - return canvas_compatible; - } - - /** - * Does the current browser support canvas drop shadows? - */ - function shadowSupport() { - - // to test for drop shadow support in the current browser, uncomment the next line - // return true; - - // until a good feature-detect is found, we have to look at user agents - try { - var userAgent = navigator.userAgent.toLowerCase(); - if (/webkit/.test(userAgent)) { - // WebKit.. let's go! - return true; - } - else if (/gecko|mozilla/.test(userAgent) && parseFloat(userAgent.match(/firefox\/(\d+(?:\.\d+)+)/)[1]) >= 3.1){ - // Mozilla 3.1 or higher - return true; - } - } - catch(err) { - // if there's an error, just keep going, we'll assume that drop shadows are not supported - } - - return false; - - } // - - /** - * Given two points, find a point which is dist pixels from point1 on a line to point2 - */ - function betweenPoint(point1, point2, dist) { - // figure out if we're horizontal or vertical - var y, x; - if (point1.x == point2.x) { - // vertical - y = point1.y < point2.y ? point1.y + dist : point1.y - dist; - return {x: point1.x, y: y}; - } - else if (point1.y == point2.y) { - // horizontal - x = point1.x < point2.x ? point1.x + dist : point1.x - dist; - return {x:x, y: point1.y}; - } - }; // - - function centerPoint(arcStart, corner, arcEnd) { - var x = corner.x == arcStart.x ? arcEnd.x : arcStart.x; - var y = corner.y == arcStart.y ? arcEnd.y : arcStart.y; - var startAngle, endAngle; - if (arcStart.x < arcEnd.x) { - if (arcStart.y > arcEnd.y) { - // arc is on upper left - startAngle = (Math.PI/180)*180; - endAngle = (Math.PI/180)*90; - } - else { - // arc is on upper right - startAngle = (Math.PI/180)*90; - endAngle = 0; - } - } - else { - if (arcStart.y > arcEnd.y) { - // arc is on lower left - startAngle = (Math.PI/180)*270; - endAngle = (Math.PI/180)*180; - } - else { - // arc is on lower right - startAngle = 0; - endAngle = (Math.PI/180)*270; - } - } - return {x: x, y: y, type: 'center', startAngle: startAngle, endAngle: endAngle}; - }; // - - /** - * Find the intersection point of two lines, each defined by two points - * arguments are x1, y1 and x2, y2 for r1 (line 1) and r2 (line 2) - * It's like an algebra party!!! - */ - function findIntersect(r1x1, r1y1, r1x2, r1y2, r2x1, r2y1, r2x2, r2y2) { - - if (r2x1 == r2x2) { - return findIntersectY(r1x1, r1y1, r1x2, r1y2, r2x1); - } - if (r2y1 == r2y2) { - return findIntersectX(r1x1, r1y1, r1x2, r1y2, r2y1); - } - - // m = (y1 - y2) / (x1 - x2) // <-- how to find the slope - // y = mx + b // the 'classic' linear equation - // b = y - mx // how to find b (the y-intersect) - // x = (y - b)/m // how to find x - var r1m = (r1y1 - r1y2) / (r1x1 - r1x2); - var r1b = r1y1 - (r1m * r1x1); - var r2m = (r2y1 - r2y2) / (r2x1 - r2x2); - var r2b = r2y1 - (r2m * r2x1); - - var x = (r2b - r1b) / (r1m - r2m); - var y = r1m * x + r1b; - - return {x: x, y: y}; - }; // - - /** - * Find the y intersection point of a line and given x vertical - */ - function findIntersectY(r1x1, r1y1, r1x2, r1y2, x) { - if (r1y1 == r1y2) { - return {x: x, y: r1y1}; - } - var r1m = (r1y1 - r1y2) / (r1x1 - r1x2); - var r1b = r1y1 - (r1m * r1x1); - - var y = r1m * x + r1b; - - return {x: x, y: y}; - }; // - - /** - * Find the x intersection point of a line and given y horizontal - */ - function findIntersectX(r1x1, r1y1, r1x2, r1y2, y) { - if (r1x1 == r1x2) { - return {x: r1x1, y: y}; - } - var r1m = (r1y1 - r1y2) / (r1x1 - r1x2); - var r1b = r1y1 - (r1m * r1x1); - - // y = mx + b // your old friend, linear equation - // x = (y - b)/m // linear equation solved for x - var x = (y - r1b) / r1m; - - return {x: x, y: y}; - - }; // - - }; // - - /** - * jQuery's compat.js (used in Drupal's jQuery upgrade module, overrides the $().position() function - * this is a copy of that function to allow the plugin to work when compat.js is present - * once compat.js is fixed to not override existing functions, this function can be removed - * and .btPosion() can be replaced with .position() above... - */ - jQuery.fn.btPosition = function() { - - function num(elem, prop) { - return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0; - }; - - var left = 0, top = 0, results; - - if ( this[0] ) { - // Get *real* offsetParent - var offsetParent = this.offsetParent(), - - // Get correct offsets - offset = this.offset(), - parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset(); - - // Subtract element margins - // note: when an element has margin: auto the offsetLeft and marginLeft - // are the same in Safari causing offset.left to incorrectly be 0 - offset.top -= num( this, 'marginTop' ); - offset.left -= num( this, 'marginLeft' ); - - // Add offsetParent borders - parentOffset.top += num( offsetParent, 'borderTopWidth' ); - parentOffset.left += num( offsetParent, 'borderLeftWidth' ); - - // Subtract the two offsets - results = { - top: offset.top - parentOffset.top, - left: offset.left - parentOffset.left - }; - } - - return results; - }; // - - - /** - * jQuery's dimensions.js overrides the $().btOuterWidth() function - * this is a copy of original jQuery's outerWidth() function to - * allow the plugin to work when dimensions.js is present - */ - jQuery.fn.btOuterWidth = function(margin) { - - function num(elem, prop) { - return elem[0] && parseInt(jQuery.curCSS(elem[0], prop, true), 10) || 0; - }; - - return this["innerWidth"]() - + num(this, "borderLeftWidth") - + num(this, "borderRightWidth") - + (margin ? num(this, "marginLeft") - + num(this, "marginRight") : 0); - - }; // - - /** - * A convenience function to run btOn() (if available) - * for each selected item - */ - jQuery.fn.btOn = function() { - return this.each(function(index){ - if (jQuery.isFunction(this.btOn)) { - this.btOn(); - } - }); - }; // - - /** - * - * A convenience function to run btOff() (if available) - * for each selected item - */ - jQuery.fn.btOff = function() { - return this.each(function(index){ - if (jQuery.isFunction(this.btOff)) { - this.btOff(); - } - }); - }; // - - jQuery.bt.vars = {clickAnywhereStack: [], closeWhenOpenStack: []}; - - /** - * This function gets bound to the document's click event - * It turns off all of the tips in the click-anywhere-to-close stack - */ - jQuery.bt.docClick = function(e) { - if (!e) { - var e = window.event; - }; - // if clicked element is a child of neither a tip NOR a target - // and there are tips in the stack - if (!$(e.target).parents().andSelf().filter('.bt-wrapper, .bt-active').length && jQuery.bt.vars.clickAnywhereStack.length) { - // if clicked element isn't inside tip, close tips in stack - $(jQuery.bt.vars.clickAnywhereStack).btOff(); - $(document).unbind('click', jQuery.bt.docClick); - } - }; // - - /** - * Defaults for the beauty tips - * - * Note this is a variable definition and not a function. So defaults can be - * written for an entire page by simply redefining attributes like so: - * - * jQuery.bt.options.width = 400; - * - * Be sure to use *jQuery.bt.options* and not jQuery.bt.defaults when overriding - * - * This would make all Beauty Tips boxes 400px wide. - * - * Each of these options may also be overridden during - * - * Can be overriden globally or at time of call. - * - */ - jQuery.bt.defaults = { - trigger: 'hover', // trigger to show/hide tip - // use [on, off] to define separate on/off triggers - // also use space character to allow multiple to trigger - // examples: - // ['focus', 'blur'] // focus displays, blur hides - // 'dblclick' // dblclick toggles on/off - // ['focus mouseover', 'blur mouseout'] // multiple triggers - // 'now' // shows/hides tip without event - // 'none' // use $('#selector').btOn(); and ...btOff(); - // 'hoverIntent' // hover using hoverIntent plugin (settings below) - // note: - // hoverIntent becomes default if available - - clickAnywhereToClose: true, // clicking anywhere outside of the tip will close it - closeWhenOthersOpen: false, // tip will be closed before another opens - stop >= 2 tips being on - - shrinkToFit: false, // should short single-line content get a narrower balloon? - width: '200px', // width of tooltip box - - padding: '10px', // padding for content (get more fine grained with cssStyles) - spikeGirth: 10, // width of spike - spikeLength: 15, // length of spike - overlap: 0, // spike overlap (px) onto target (can cause problems with 'hover' trigger) - overlay: false, // display overlay on target (use CSS to style) -- BUGGY! - killTitle: true, // kill title tags to avoid double tooltips - - textzIndex: 9999, // z-index for the text - boxzIndex: 9998, // z-index for the "talk" box (should always be less than textzIndex) - wrapperzIndex: 9997, - offsetParent: null, // DOM node to append the tooltip into. - // Must be positioned relative or absolute. Can be selector or object - positions: ['most'], // preference of positions for tip (will use first with available space) - // possible values 'top', 'bottom', 'left', 'right' as an array in order of - // preference. Last value will be used if others don't have enough space. - // or use 'most' to use the area with the most space - fill: "#FFFFFF", // fill color for the tooltip box, you can use any CSS-style color definition method - // http://www.w3.org/TR/css3-color/#numerical - not all methods have been tested - - windowMargin: 10, // space (px) to leave between text box and browser edge - - strokeWidth: 1, // width of stroke around box, **set to 0 for no stroke** - strokeStyle: "#000", // color/alpha of stroke - - cornerRadius: 5, // radius of corners (px), set to 0 for square corners - - // following values are on a scale of 0 to 1 with .5 being centered - - centerPointX: .5, // the spike extends from center of the target edge to this point - centerPointY: .5, // defined by percentage horizontal (x) and vertical (y) - - shadow: false, // use drop shadow? (only displays in Safari and FF 3.1) - experimental - shadowOffsetX: 2, // shadow offset x (px) - shadowOffsetY: 2, // shadow offset y (px) - shadowBlur: 3, // shadow blur (px) - shadowColor: "#000", // shadow color/alpha - shadowOverlap: false, // when shadows overlap the target element it can cause problem with hovering - // set this to true to overlap or set to a numeric value to define the amount of overlap - noShadowOpts: {strokeStyle: '#999'}, // use this to define 'fall-back' options for browsers which don't support drop shadows - - cssClass: 'target_link', // CSS class to add to the box wrapper div (of the TIP) - cssStyles: {}, // styles to add the text box - // example: {fontFamily: 'Georgia, Times, serif', fontWeight: 'bold'} - - activeClass: 'bt-active', // class added to TARGET element when its BeautyTip is active - - contentSelector: "$(this).attr('title')", // if there is no content argument, use this selector to retrieve the title - // a function which returns the content may also be passed here - - ajaxPath: null, // if using ajax request for content, this contains url and (opt) selector - // this will override content and contentSelector - // examples (see jQuery load() function): - // '/demo.html' - // '/help/ajax/snip' - // '/help/existing/full div#content' - - // ajaxPath can also be defined as an array - // in which case, the first value will be parsed as a jQuery selector - // the result of which will be used as the ajaxPath - // the second (optional) value is the content selector as above - // examples: - // ["$(this).attr('href')", 'div#content'] - // ["$(this).parents('.wrapper').find('.title').attr('href')"] - // ["$('#some-element').val()"] - - ajaxError: 'ERROR: %error', - // error text, use "%error" to insert error from server - ajaxLoading: 'Loading...', // yes folks, it's the blink tag! - ajaxData: {}, // key/value pairs - ajaxType: 'GET', // 'GET' or 'POST' - ajaxCache: true, // cache ajax results and do not send request to same url multiple times - ajaxOpts: {}, // any other ajax options - timeout, passwords, processing functions, etc... - // see http://docs.jquery.com/Ajax/jQuery.ajax#options - - preBuild: function(){}, // function to run before popup is built - preShow: function(box){}, // function to run before popup is displayed - showTip: function(box){ - $(box).show(); - }, - postShow: function(box){}, // function to run after popup is built and displayed - - preHide: function(box){}, // function to run before popup is removed - hideTip: function(box, callback) { - $(box).hide(); - callback(); // you MUST call "callback" at the end of your animations - }, - postHide: function(){}, // function to run after popup is removed - - hoverIntentOpts: { // options for hoverIntent (if installed) - interval: 300, // http://cherne.net/brian/resources/jquery.hoverIntent.html - timeout: 500 - } - - }; // - - jQuery.bt.options = {}; - -})(jQuery); - -// @todo -// use larger canvas (extend to edge of page when windowMargin is active) -// add options to shift position of tip vert/horiz and position of spike tip -// create drawn (canvas) shadows -// use overlay to allow overlap with hover -// experiment with making tooltip a subelement of the target -// handle non-canvas-capable browsers elegantly diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/jquery.form.js b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/jquery.form.js deleted file mode 100644 index aedd6491c..000000000 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/jquery.form.js +++ /dev/null @@ -1,1132 +0,0 @@ -/*! - * jQuery Form Plugin - * version: 3.23 (11-DEC-2012) - * @requires jQuery v1.5 or later - * - * Examples and documentation at: http://malsup.com/jquery/form/ - * Project repository: https://github.com/malsup/form - * Dual licensed under the MIT and GPL licenses: - * http://malsup.github.com/mit-license.txt - * http://malsup.github.com/gpl-license-v2.txt - */ -/*global ActiveXObject alert */ -;(function($) { -"use strict"; - -/* - Usage Note: - ----------- - Do not use both ajaxSubmit and ajaxForm on the same form. These - functions are mutually exclusive. Use ajaxSubmit if you want - to bind your own submit handler to the form. For example, - - $(document).ready(function() { - $('#myForm').on('submit', function(e) { - e.preventDefault(); // <-- important - $(this).ajaxSubmit({ - target: '#output' - }); - }); - }); - - Use ajaxForm when you want the plugin to manage all the event binding - for you. For example, - - $(document).ready(function() { - $('#myForm').ajaxForm({ - target: '#output' - }); - }); - - You can also use ajaxForm with delegation (requires jQuery v1.7+), so the - form does not have to exist when you invoke ajaxForm: - - $('#myForm').ajaxForm({ - delegation: true, - target: '#output' - }); - - When using ajaxForm, the ajaxSubmit function will be invoked for you - at the appropriate time. -*/ - -/** - * Feature detection - */ -var feature = {}; -feature.fileapi = $("").get(0).files !== undefined; -feature.formdata = window.FormData !== undefined; - -/** - * ajaxSubmit() provides a mechanism for immediately submitting - * an HTML form using AJAX. - */ -$.fn.ajaxSubmit = function(options) { - /*jshint scripturl:true */ - - // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) - if (!this.length) { - log('ajaxSubmit: skipping submit process - no element selected'); - return this; - } - - var method, action, url, $form = this; - - if (typeof options == 'function') { - options = { success: options }; - } - - method = this.attr('method'); - action = this.attr('action'); - url = (typeof action === 'string') ? $.trim(action) : ''; - url = url || window.location.href || ''; - if (url) { - // clean url (don't include hash vaue) - url = (url.match(/^([^#]+)/)||[])[1]; - } - - options = $.extend(true, { - url: url, - success: $.ajaxSettings.success, - type: method || 'GET', - iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' - }, options); - - // hook for manipulating the form data before it is extracted; - // convenient for use with rich editors like tinyMCE or FCKEditor - var veto = {}; - this.trigger('form-pre-serialize', [this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); - return this; - } - - // provide opportunity to alter form data before it is serialized - if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSerialize callback'); - return this; - } - - var traditional = options.traditional; - if ( traditional === undefined ) { - traditional = $.ajaxSettings.traditional; - } - - var elements = []; - var qx, a = this.formToArray(options.semantic, elements); - if (options.data) { - options.extraData = options.data; - qx = $.param(options.data, traditional); - } - - // give pre-submit callback an opportunity to abort the submit - if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSubmit callback'); - return this; - } - - // fire vetoable 'validate' event - this.trigger('form-submit-validate', [a, this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); - return this; - } - - var q = $.param(a, traditional); - if (qx) { - q = ( q ? (q + '&' + qx) : qx ); - } - if (options.type.toUpperCase() == 'GET') { - options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; - options.data = null; // data is null for 'get' - } - else { - options.data = q; // data is the query string for 'post' - } - - var callbacks = []; - if (options.resetForm) { - callbacks.push(function() { $form.resetForm(); }); - } - if (options.clearForm) { - callbacks.push(function() { $form.clearForm(options.includeHidden); }); - } - - // perform a load on the target only if dataType is not provided - if (!options.dataType && options.target) { - var oldSuccess = options.success || function(){}; - callbacks.push(function(data) { - var fn = options.replaceTarget ? 'replaceWith' : 'html'; - $(options.target)[fn](data).each(oldSuccess, arguments); - }); - } - else if (options.success) { - callbacks.push(options.success); - } - - options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg - var context = options.context || this ; // jQuery 1.4+ supports scope context - for (var i=0, max=callbacks.length; i < max; i++) { - callbacks[i].apply(context, [data, status, xhr || $form, $form]); - } - }; - - // are there files to upload? - - // [value] (issue #113), also see comment: - // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219 - var fileInputs = $('input[type=file]:enabled[value!=""]', this); - - var hasFileInputs = fileInputs.length > 0; - var mp = 'multipart/form-data'; - var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); - - var fileAPI = feature.fileapi && feature.formdata; - log("fileAPI :" + fileAPI); - var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI; - - var jqxhr; - - // options.iframe allows user to force iframe mode - // 06-NOV-09: now defaulting to iframe mode if file input is detected - if (options.iframe !== false && (options.iframe || shouldUseFrame)) { - // hack to fix Safari hang (thanks to Tim Molendijk for this) - // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d - if (options.closeKeepAlive) { - $.get(options.closeKeepAlive, function() { - jqxhr = fileUploadIframe(a); - }); - } - else { - jqxhr = fileUploadIframe(a); - } - } - else if ((hasFileInputs || multipart) && fileAPI) { - jqxhr = fileUploadXhr(a); - } - else { - jqxhr = $.ajax(options); - } - - $form.removeData('jqxhr').data('jqxhr', jqxhr); - - // clear element array - for (var k=0; k < elements.length; k++) - elements[k] = null; - - // fire 'notify' event - this.trigger('form-submit-notify', [this, options]); - return this; - - // utility fn for deep serialization - function deepSerialize(extraData){ - var serialized = $.param(extraData).split('&'); - var len = serialized.length; - var result = {}; - var i, part; - for (i=0; i < len; i++) { - // #252; undo param space replacement - serialized[i] = serialized[i].replace(/\+/g,' '); - part = serialized[i].split('='); - result[decodeURIComponent(part[0])] = decodeURIComponent(part[1]); - } - return result; - } - - // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz) - function fileUploadXhr(a) { - var formdata = new FormData(); - - for (var i=0; i < a.length; i++) { - formdata.append(a[i].name, a[i].value); - } - - if (options.extraData) { - var serializedData = deepSerialize(options.extraData); - for (var p in serializedData) - if (serializedData.hasOwnProperty(p)) - formdata.append(p, serializedData[p]); - } - - options.data = null; - - var s = $.extend(true, {}, $.ajaxSettings, options, { - contentType: false, - processData: false, - cache: false, - type: method || 'POST' - }); - - if (options.uploadProgress) { - // workaround because jqXHR does not expose upload property - s.xhr = function() { - var xhr = jQuery.ajaxSettings.xhr(); - if (xhr.upload) { - xhr.upload.onprogress = function(event) { - var percent = 0; - var position = event.loaded || event.position; /*event.position is deprecated*/ - var total = event.total; - if (event.lengthComputable) { - percent = Math.ceil(position / total * 100); - } - options.uploadProgress(event, position, total, percent); - }; - } - return xhr; - }; - } - - s.data = null; - var beforeSend = s.beforeSend; - s.beforeSend = function(xhr, o) { - o.data = formdata; - if(beforeSend) - beforeSend.call(this, xhr, o); - }; - return $.ajax(s); - } - - // private function for handling file uploads (hat tip to YAHOO!) - function fileUploadIframe(a) { - var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle; - var useProp = !!$.fn.prop; - var deferred = $.Deferred(); - - if ($('[name=submit],[id=submit]', form).length) { - // if there is an input with a name or id of 'submit' then we won't be - // able to invoke the submit fn on the form (at least not x-browser) - alert('Error: Form elements must not have name or id of "submit".'); - deferred.reject(); - return deferred; - } - - if (a) { - // ensure that every serialized input is still enabled - for (i=0; i < elements.length; i++) { - el = $(elements[i]); - if ( useProp ) - el.prop('disabled', false); - else - el.removeAttr('disabled'); - } - } - - s = $.extend(true, {}, $.ajaxSettings, options); - s.context = s.context || s; - id = 'jqFormIO' + (new Date().getTime()); - if (s.iframeTarget) { - $io = $(s.iframeTarget); - n = $io.attr('name'); - if (!n) - $io.attr('name', id); - else - id = n; - } - else { - $io = $('