diff options
Diffstat (limited to '')
-rw-r--r-- | admin/picture_coi.php | 97 | ||||
-rw-r--r-- | admin/picture_modify.php | 5 | ||||
-rw-r--r-- | admin/themes/default/template/picture_coi.tpl | 66 | ||||
-rw-r--r-- | admin/themes/default/template/picture_modify.tpl | 7 | ||||
-rw-r--r-- | i.php | 96 | ||||
-rw-r--r-- | include/dblayer/functions_mysql.inc.php | 6 | ||||
-rw-r--r-- | include/derivative.inc.php | 11 | ||||
-rw-r--r-- | include/derivative_params.inc.php | 6 | ||||
-rw-r--r-- | include/derivative_std_params.inc.php | 8 | ||||
-rw-r--r-- | install/db/116-database.php | 48 | ||||
-rw-r--r-- | install/piwigo_structure-mysql.sql | 1 | ||||
-rw-r--r-- | themes/default/js/plugins/Jcrop.gif | bin | 0 -> 329 bytes | |||
-rw-r--r-- | themes/default/js/plugins/jquery.Jcrop.css | 35 | ||||
-rw-r--r-- | themes/default/js/plugins/jquery.Jcrop.js | 1600 | ||||
-rw-r--r-- | themes/default/js/plugins/jquery.Jcrop.min.js | 246 |
15 files changed, 2204 insertions, 28 deletions
diff --git a/admin/picture_coi.php b/admin/picture_coi.php new file mode 100644 index 000000000..2a3a60023 --- /dev/null +++ b/admin/picture_coi.php @@ -0,0 +1,97 @@ +<?php +// +-----------------------------------------------------------------------+ +// | Piwigo - a PHP based photo gallery | +// +-----------------------------------------------------------------------+ +// | Copyright(C) 2008-2012 Piwigo Team http://piwigo.org | +// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | +// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +if(!defined("PHPWG_ROOT_PATH")) +{ + die('Hacking attempt!'); +} + +// +-----------------------------------------------------------------------+ +// | Check Access and exit when user status is not ok | +// +-----------------------------------------------------------------------+ +check_status(ACCESS_ADMINISTRATOR); + +check_input_parameter('image_id', $_GET, false, PATTERN_ID); + +if (isset($_POST['submit'])) +{ + $query = 'UPDATE '.IMAGES_TABLE; + if (strlen($_POST['l'])==0) + { + $query .= ' SET coi=NULL'; + } + else + { + $coi = fraction_to_char($_POST['l']) + .fraction_to_char($_POST['t']) + .fraction_to_char($_POST['r']) + .fraction_to_char($_POST['b']); + $query .= ' SET coi=\''.$coi.'\''; + } + $query .= ' WHERE id='.$_GET['image_id']; + pwg_query($query); +} + +$query = 'SELECT * FROM '.IMAGES_TABLE.' WHERE id='.$_GET['image_id']; +$row = pwg_db_fetch_assoc( pwg_query($query) ); + +if (isset($_POST['submit'])) +{ + delete_element_derivatives($row); +} + +$tpl_var = array( + 'ALT' => $row['file'], + 'U_IMG' => DerivativeImage::url(IMG_LARGE, $row), + 'U_EDIT' => get_root_url().'admin.php?page=picture_modify&image_id='.$_GET['image_id'], + ); + +if (!empty($row['coi'])) +{ + $tpl_var['coi'] = array( + 'l'=> char_to_fraction($row['coi'][0]), + 't'=> char_to_fraction($row['coi'][1]), + 'r'=> char_to_fraction($row['coi'][2]), + 'b'=> char_to_fraction($row['coi'][3]), + ); +} + +if (isset($_POST['submit'])) +{ + $uid = '&b='.time(); + $conf['question_mark_in_urls'] = $conf['php_extension_in_urls'] = true; + $conf['derivative_url_style']=2; //script + $tpl_var['U_SQUARE'] = DerivativeImage::url(IMG_SQUARE, $row).$uid; + $tpl_var['U_THUMB'] = DerivativeImage::url(IMG_THUMB, $row).$uid; +} +else +{ + $tpl_var['U_SQUARE'] = DerivativeImage::url(IMG_SQUARE, $row); + $tpl_var['U_THUMB'] = DerivativeImage::url(IMG_THUMB, $row); +} + +$template->assign($tpl_var); +$template->set_filename('picture_coi', 'picture_coi.tpl'); + +$template->assign_var_from_handle('ADMIN_CONTENT', 'picture_coi'); +?> diff --git a/admin/picture_modify.php b/admin/picture_modify.php index 66a3240d3..38b607cc7 100644 --- a/admin/picture_modify.php +++ b/admin/picture_modify.php @@ -303,6 +303,11 @@ $template->assign( ) ); +if (in_array(get_extension($row['path']),$conf['picture_ext'])) +{ + $template->assign('U_COI', get_root_url().'admin.php?page=picture_coi&image_id='.$_GET['image_id']); +} + // image level options $selected_level = isset($_POST['level']) ? $_POST['level'] : $row['level']; $template->assign( diff --git a/admin/themes/default/template/picture_coi.tpl b/admin/themes/default/template/picture_coi.tpl new file mode 100644 index 000000000..8287d3701 --- /dev/null +++ b/admin/themes/default/template/picture_coi.tpl @@ -0,0 +1,66 @@ +{html_head} +<link rel="stylesheet" type="text/css" href="themes/default/js/plugins/jquery.Jcrop.css" /> +{/html_head} +{combine_script id='jquery.jcrop' load='footer' require='jquery' path='themes/default/js/plugins/jquery.Jcrop.min.js'} + +<h2>{'Center of interest'|@translate}</h2> +<div> +<a href="{$U_EDIT}">{'Edit photo information'|@translate}</a> +</div> + +<div> +<img src="{$U_SQUARE}" alt="{$ALT}"> +<img src="{$U_THUMB}" alt="{$ALT}"> +</div> + +<div> +<form method="post"> +<input type="hidden" id="l" name="l" value="{if isset($coi)}{$coi.l}{/if}"> +<input type="hidden" id="t" name="t" value="{if isset($coi)}{$coi.t}{/if}"> +<input type="hidden" id="r" name="r" value="{if isset($coi)}{$coi.r}{/if}"> +<input type="hidden" id="b" name="b" value="{if isset($coi)}{$coi.b}{/if}"> + +<img id="jcrop" src="{$U_IMG}" alt="{$ALT}"> + +<p> +<input type="submit" name="submit" value="{'Submit'|@translate}"> +</p> +</form> +</div> + +{footer_script} +{literal} +function from_coi(f, total) { + return f*total; +} + +function to_coi(v, total) { + return v/total; +} + +function jOnChange(sel) { + var $img = jQuery("#jcrop"); + jQuery("#l").val( to_coi(sel.x, $img.width()) ); + jQuery("#t").val( to_coi(sel.y, $img.height()) ); + jQuery("#r").val( to_coi(sel.x2, $img.width()) ); + jQuery("#b").val( to_coi(sel.y2, $img.height()) ); +} +function jOnRelease() { + jQuery("#l,#t,#r,#b").val(""); +} + +{/literal} +jQuery("#jcrop").Jcrop( {ldelim} + boxWidth: 400, boxHeight: 400, + onChange: jOnChange, + onRelease: jOnRelease + } +{if isset($coi)} + ,function() {ldelim} + var $img = jQuery("#jcrop"); + this.animateTo( [from_coi({$coi.l}, $img.width()), from_coi({$coi.t}, $img.height()), from_coi({$coi.r}, $img.width()), from_coi({$coi.b}, $img.height()) ] ); + } +{/if} +); +{/footer_script} + diff --git a/admin/themes/default/template/picture_modify.tpl b/admin/themes/default/template/picture_modify.tpl index cddd1ba78..28e6bfc76 100644 --- a/admin/themes/default/template/picture_modify.tpl +++ b/admin/themes/default/template/picture_modify.tpl @@ -83,7 +83,12 @@ pwg_initialization_datepicker("#date_creation_day", "#date_creation_month", "#da </td> </tr> {/if} - +{if isset($U_COI)} + <tr> + <td></td> + <td><a href="{$U_COI}">{'Not cropped correctly?'|@translate}</a></td> + </tr> +{/if} </table> </fieldset> @@ -232,12 +232,6 @@ function parse_request() } } array_shift($deriv); - $page['coi'] = ''; - if (count($deriv) && $deriv[0][0]=='c' && $deriv[0][1]=='i') - { - $page['coi'] = substr(array_shift($deriv), 2); - preg_match('#^[a-zA-Z]{4}$#', $page['coi']) or ierror('Invalid center of interest', 400); - } if ($page['derivative_type'] == IMG_CUSTOM) { @@ -256,7 +250,7 @@ function parse_request() { ierror('Too big', 403); } - + $key = array(); $params->add_url_tokens($key); $key = implode('_', $key); @@ -266,15 +260,65 @@ function parse_request() } } - if (!is_file(PHPWG_ROOT_PATH.$req.$ext) and - is_file(PHPWG_ROOT_PATH.'../'.$req.$ext) ) + if (is_file(PHPWG_ROOT_PATH.$req.$ext)) + { + $req = './'.$req; // will be used to match #iamges.path + } + elseif (is_file(PHPWG_ROOT_PATH.'../'.$req.$ext)) + { $req = '../'.$req; + } $page['src_location'] = $req.$ext; $page['src_path'] = PHPWG_ROOT_PATH.$page['src_location']; $page['src_url'] = $page['root_path'].$page['src_location']; } +function try_switch_source(DerivativeParams $params, $original_mtime) +{ + global $page; + $candidates = array(); + foreach(ImageStdParams::get_defined_type_map() as $candidate) + { + if ($candidate->type == $params->type) + continue; + if ($candidate->use_watermark != $params->use_watermark) + continue; + if ($candidate->max_width() < $params->max_width() || $candidate->max_height() < $params->max_height()) + continue; + if ($params->sizing->max_crop==0) + { + if ($candidate->sizing->max_crop!=0) + continue; + } + else + { + if ($candidate->sizing->max_crop!=0) + continue; // this could be optimized + if (!isset($page['original_size'])) + continue; + $candidate_size = $candidate->compute_final_size($page['original_size']); + if ($candidate_size[0] < $params->sizing->min_size[0] || $candidate_size[1] < $params->sizing->min_size[1] ) + continue; + } + $candidates[] = $candidate; + } + + foreach( array_reverse($candidates) as $candidate) + { + $candidate_path = $page['derivative_path']; + $candidate_path = str_replace( '-'.derivative_to_url($params->type), '-'.derivative_to_url($candidate->type), $candidate_path); + $candidate_mtime = @filemtime($candidate_path); + if ($candidate_mtime === false + || $candidate_mtime < $original_mtime + || $candidate_mtime < $candidate->last_mod_time) + continue; + $params->use_watermark = false; + $params->sharpen = min(1, $params->sharpen); + $page['src_path'] = $candidate_path; + $page['src_url'] = $page['root_path'] . substr($candidate_path, strlen(PHPWG_ROOT_PATH)); + } +} function send_derivative($expires) { @@ -362,6 +406,40 @@ if (!$need_generate) send_derivative($expires); } +$page['coi'] = null; +if (strpos($page['src_location'], '/pwg_representative/')===false + && strpos($page['src_location'], 'themes/')===false + && strpos($page['src_location'], 'plugins/')===false) +{ + @include(PHPWG_ROOT_PATH.PWG_LOCAL_DIR .'config/database.inc.php'); + include(PHPWG_ROOT_PATH .'include/dblayer/functions_'.$conf['dblayer'].'.inc.php'); + try + { + $pwg_db_link = pwg_db_connect($conf['db_host'], $conf['db_user'], + $conf['db_password'], $conf['db_base']); + $query = 'SELECT coi, width, height FROM '.$prefixeTable.'images WHERE path=\''.$page['src_location'].'\''; + if ( ($row=pwg_db_fetch_assoc(pwg_query($query))) ) + { + if (isset($row['width'])) + { + $page['original_size'] = array($row['width'],$row['height']); + } + $page['coi'] = $row['coi']; + } + mysql_close($pwg_db_link); + if (!$row) + { + ierror('Db file path not found', 404); + } + } + catch (Exception $e) + { + ilog("db error", $e->getMessage()); + } +} + +try_switch_source($params, $src_mtime); + if (!mkgetdir(dirname($page['derivative_path']))) { ierror("dir create error", 500); diff --git a/include/dblayer/functions_mysql.inc.php b/include/dblayer/functions_mysql.inc.php index 2c0aab1dc..65cb9fbd2 100644 --- a/include/dblayer/functions_mysql.inc.php +++ b/include/dblayer/functions_mysql.inc.php @@ -84,10 +84,10 @@ function pwg_query($query) { global $conf,$page,$debug,$t2; - $start = get_moment(); + $start = microtime(true); ($result = mysql_query($query)) or my_error($query, $conf['die_on_sql_error']); - $time = get_moment() - $start; + $time = microtime(true) - $start; if (!isset($page['count_queries'])) { @@ -199,7 +199,7 @@ function array_from_query($query, $fieldname) $result = pwg_query($query); while ($row = mysql_fetch_assoc($result)) { - array_push($array, $row[$fieldname]); + $array[] = $row[$fieldname]; } return $array; diff --git a/include/derivative.inc.php b/include/derivative.inc.php index 0ba906461..6d0055def 100644 --- a/include/derivative.inc.php +++ b/include/derivative.inc.php @@ -27,14 +27,13 @@ final class SrcImage public $id; public $rel_path; - public $coi=null; private $size=null; private $flags=0; function __construct($infos) { global $conf; - + $this->id = $infos['id']; $ext = get_extension($infos['path']); if (in_array($ext, $conf['picture_ext'])) @@ -54,7 +53,6 @@ final class SrcImage $this->size = @getimagesize(PHPWG_ROOT_PATH.$this->rel_path); } - $this->coi = @$infos['coi']; if (!$this->size && isset($infos['width']) && isset($infos['height'])) { $this->size = array($infos['width'], $infos['height']); @@ -168,11 +166,6 @@ final class DerivativeImage $tokens=array(); $tokens[] = substr($params->type,0,2); - if ($params->sizing->max_crop != 0 and !empty($src->coi)) - { - $tokens[] = 'ci'.$src->coi; - } - if ($params->type==IMG_CUSTOM) { $params->add_url_tokens($tokens); @@ -257,7 +250,7 @@ final class DerivativeImage { return $this->src_image->get_size(); } - return $this->params->compute_final_size($this->src_image->get_size(), $this->src_image->coi); + return $this->params->compute_final_size($this->src_image->get_size()); } function get_size_htm() diff --git a/include/derivative_params.inc.php b/include/derivative_params.inc.php index 15c78c9aa..dc19d1df7 100644 --- a/include/derivative_params.inc.php +++ b/include/derivative_params.inc.php @@ -45,7 +45,7 @@ function char_to_fraction($c) function fraction_to_char($f) { - return ord('a') + round($f*25); + return chr(ord('a') + round($f*25)); } /** small utility to manipulate a 'rectangle'*/ @@ -257,9 +257,9 @@ final class DerivativeParams $this->sizing->add_url_tokens($tokens); } - function compute_final_size($in_size, $coi) + function compute_final_size($in_size) { - $this->sizing->compute( $in_size, $coi, $crop_rect, $scale_size ); + $this->sizing->compute( $in_size, null, $crop_rect, $scale_size ); return $scale_size != null ? $scale_size : $in_size; } diff --git a/include/derivative_std_params.inc.php b/include/derivative_std_params.inc.php index 773866dec..07093e0fc 100644 --- a/include/derivative_std_params.inc.php +++ b/include/derivative_std_params.inc.php @@ -72,7 +72,7 @@ final class ImageStdParams { return self::$all_type_map[$type]; } - + static function get_custom($w, $h, $crop=0, $minw=null, $minh=null) { $params = new DerivativeParams( new SizingParams( array($w,$h), $crop, array($minw,$minh)) ); @@ -103,6 +103,8 @@ final class ImageStdParams self::$type_map = $arr['d']; self::$watermark = @$arr['w']; if (!self::$watermark) self::$watermark = new WatermarkParams(); + self::$custom = @$arr['c']; + if (!self::$custom) self::$custom = array(); } else { @@ -134,7 +136,7 @@ final class ImageStdParams { self::$watermark = $watermark; } - + static function set_and_save($map) { self::$type_map = $map; @@ -176,7 +178,7 @@ final class ImageStdParams $params->use_watermark = true; } } - + private static function build_maps() { foreach (self::$type_map as $type=>$params) diff --git a/install/db/116-database.php b/install/db/116-database.php new file mode 100644 index 000000000..81fa3167b --- /dev/null +++ b/install/db/116-database.php @@ -0,0 +1,48 @@ +<?php +// +-----------------------------------------------------------------------+ +// | Piwigo - a PHP based photo gallery | +// +-----------------------------------------------------------------------+ +// | Copyright(C) 2008-2012 Piwigo Team http://piwigo.org | +// | Copyright(C) 2003-2008 PhpWebGallery Team http://phpwebgallery.net | +// | Copyright(C) 2002-2003 Pierrick LE GALL http://le-gall.net/pierrick | +// +-----------------------------------------------------------------------+ +// | This program is free software; you can redistribute it and/or modify | +// | it under the terms of the GNU General Public License as published by | +// | the Free Software Foundation | +// | | +// | This program is distributed in the hope that it will be useful, but | +// | WITHOUT ANY WARRANTY; without even the implied warranty of | +// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | +// | General Public License for more details. | +// | | +// | You should have received a copy of the GNU General Public License | +// | along with this program; if not, write to the Free Software | +// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | +// | USA. | +// +-----------------------------------------------------------------------+ + +if (!defined('PHPWG_ROOT_PATH')) +{ + die('Hacking attempt!'); +} + +$upgrade_description = 'Add #images.coi'; + +include_once(PHPWG_ROOT_PATH.'include/constants.php'); + +// +-----------------------------------------------------------------------+ +// | Upgrade content | +// +-----------------------------------------------------------------------+ + +$query = ' +ALTER TABLE '.IMAGES_TABLE.' ADD COLUMN coi CHAR(4) DEFAULT NULL COMMENT \'center of interest\' AFTER height +'; +pwg_query($query); + +echo +"\n" +.'"'.$upgrade_description.'"'.' ended' +."\n" +; + +?> diff --git a/install/piwigo_structure-mysql.sql b/install/piwigo_structure-mysql.sql index 6ce563042..59d3e6f74 100644 --- a/install/piwigo_structure-mysql.sql +++ b/install/piwigo_structure-mysql.sql @@ -185,6 +185,7 @@ CREATE TABLE `piwigo_images` ( `filesize` mediumint(9) unsigned default NULL, `width` smallint(9) unsigned default NULL, `height` smallint(9) unsigned default NULL, + `coi` char(4) default NULL COMMENT 'center of interest', `representative_ext` varchar(4) default NULL, `date_metadata_update` date default NULL, `rating_score` float(5,2) unsigned default NULL, diff --git a/themes/default/js/plugins/Jcrop.gif b/themes/default/js/plugins/Jcrop.gif Binary files differnew file mode 100644 index 000000000..72ea7ccb5 --- /dev/null +++ b/themes/default/js/plugins/Jcrop.gif diff --git a/themes/default/js/plugins/jquery.Jcrop.css b/themes/default/js/plugins/jquery.Jcrop.css new file mode 100644 index 000000000..073e22746 --- /dev/null +++ b/themes/default/js/plugins/jquery.Jcrop.css @@ -0,0 +1,35 @@ +/* Fixes issue here http://code.google.com/p/jcrop/issues/detail?id=1 */ +.jcrop-holder { text-align: left; } + +.jcrop-vline, .jcrop-hline +{ + font-size: 0px; + position: absolute; + background: white url('Jcrop.gif') top left repeat; +} +.jcrop-vline { height: 100%; width: 1px !important; } +.jcrop-hline { width: 100%; height: 1px !important; } +.jcrop-vline.right { right: 0px; } +.jcrop-hline.bottom { bottom: 0px; } +.jcrop-handle { + font-size: 1px; + width: 7px !important; + height: 7px !important; + border: 1px #eee solid; + background-color: #333; +} + +.jcrop-tracker { width: 100%; height: 100%; } + +.custom .jcrop-vline, +.custom .jcrop-hline +{ + background: yellow; +} +.custom .jcrop-handle +{ + border-color: black; + background-color: #C7BB00; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; +} diff --git a/themes/default/js/plugins/jquery.Jcrop.js b/themes/default/js/plugins/jquery.Jcrop.js new file mode 100644 index 000000000..22731d606 --- /dev/null +++ b/themes/default/js/plugins/jquery.Jcrop.js @@ -0,0 +1,1600 @@ +/** + * jquery.Jcrop.js v0.9.9 + * jQuery Image Cropping Plugin + * @author Kelly Hallman <khallman@gmail.com> + * Copyright (c) 2008-2011 Kelly Hallman - released under MIT License {{{ + * + * 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 ($) { + + $.Jcrop = function (obj, opt) { + var options = $.extend({}, $.Jcrop.defaults), + docOffset, lastcurs, ie6mode = false; + + // Internal Methods {{{ + function px(n) { + return parseInt(n, 10) + 'px'; + } + function pct(n) { + return parseInt(n, 10) + '%'; + } + function cssClass(cl) { + return options.baseClass + '-' + cl; + } + function supportsColorFade() { + return $.fx.step.hasOwnProperty('backgroundColor'); + } + function getPos(obj) //{{{ + { + // Updated in v0.9.4 to use built-in dimensions plugin + var pos = $(obj).offset(); + return [pos.left, pos.top]; + } + //}}} + function mouseAbs(e) //{{{ + { + return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])]; + } + //}}} + function setOptions(opt) //{{{ + { + if (typeof(opt) !== 'object') { + opt = {}; + } + options = $.extend(options, opt); + + if (typeof(options.onChange) !== 'function') { + options.onChange = function () {}; + } + if (typeof(options.onSelect) !== 'function') { + options.onSelect = function () {}; + } + if (typeof(options.onRelease) !== 'function') { + options.onRelease = function () {}; + } + } + //}}} + function myCursor(type) //{{{ + { + if (type !== lastcurs) { + Tracker.setCursor(type); + lastcurs = type; + } + } + //}}} + function startDragMode(mode, pos) //{{{ + { + docOffset = getPos($img); + Tracker.setCursor(mode === 'move' ? mode : mode + '-resize'); + + if (mode === 'move') { + return Tracker.activateHandlers(createMover(pos), doneSelect); + } + + var fc = Coords.getFixed(); + var opp = oppLockCorner(mode); + var opc = Coords.getCorner(oppLockCorner(opp)); + + Coords.setPressed(Coords.getCorner(opp)); + Coords.setCurrent(opc); + + Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect); + } + //}}} + function dragmodeHandler(mode, f) //{{{ + { + return function (pos) { + if (!options.aspectRatio) { + switch (mode) { + case 'e': + pos[1] = f.y2; + break; + case 'w': + pos[1] = f.y2; + break; + case 'n': + pos[0] = f.x2; + break; + case 's': + pos[0] = f.x2; + break; + } + } else { + switch (mode) { + case 'e': + pos[1] = f.y + 1; + break; + case 'w': + pos[1] = f.y + 1; + break; + case 'n': + pos[0] = f.x + 1; + break; + case 's': + pos[0] = f.x + 1; + break; + } + } + Coords.setCurrent(pos); + Selection.update(); + }; + } + //}}} + function createMover(pos) //{{{ + { + var lloc = pos; + KeyManager.watchKeys(); + + return function (pos) { + Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]); + lloc = pos; + + Selection.update(); + }; + } + //}}} + function oppLockCorner(ord) //{{{ + { + switch (ord) { + case 'n': + return 'sw'; + case 's': + return 'nw'; + case 'e': + return 'nw'; + case 'w': + return 'ne'; + case 'ne': + return 'sw'; + case 'nw': + return 'se'; + case 'se': + return 'nw'; + case 'sw': + return 'ne'; + } + } + //}}} + function createDragger(ord) //{{{ + { + return function (e) { + if (options.disabled) { + return false; + } + if ((ord === 'move') && !options.allowMove) { + return false; + } + btndown = true; + startDragMode(ord, mouseAbs(e)); + e.stopPropagation(); + e.preventDefault(); + return false; + }; + } + //}}} + function presize($obj, w, h) //{{{ + { + var nw = $obj.width(), + nh = $obj.height(); + if ((nw > w) && w > 0) { + nw = w; + nh = (w / $obj.width()) * $obj.height(); + } + if ((nh > h) && h > 0) { + nh = h; + nw = (h / $obj.height()) * $obj.width(); + } + xscale = $obj.width() / nw; + yscale = $obj.height() / nh; + $obj.width(nw).height(nh); + } + //}}} + function unscale(c) //{{{ + { + return { + x: parseInt(c.x * xscale, 10), + y: parseInt(c.y * yscale, 10), + x2: parseInt(c.x2 * xscale, 10), + y2: parseInt(c.y2 * yscale, 10), + w: parseInt(c.w * xscale, 10), + h: parseInt(c.h * yscale, 10) + }; + } + //}}} + function doneSelect(pos) //{{{ + { + var c = Coords.getFixed(); + if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) { + Selection.enableHandles(); + Selection.done(); + } else { + Selection.release(); + } + Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); + } + //}}} + function newSelection(e) //{{{ + { + if (options.disabled) { + return false; + } + if (!options.allowSelect) { + return false; + } + btndown = true; + docOffset = getPos($img); + Selection.disableHandles(); + myCursor('crosshair'); + var pos = mouseAbs(e); + Coords.setPressed(pos); + Selection.update(); + Tracker.activateHandlers(selectDrag, doneSelect); + KeyManager.watchKeys(); + + e.stopPropagation(); + e.preventDefault(); + return false; + } + //}}} + function selectDrag(pos) //{{{ + { + Coords.setCurrent(pos); + Selection.update(); + } + //}}} + function newTracker() //{{{ + { + var trk = $('<div></div>').addClass(cssClass('tracker')); + if ($.browser.msie) { + trk.css({ + opacity: 0, + backgroundColor: 'white' + }); + } + return trk; + } + //}}} + + // }}} + // Initialization {{{ + // Sanitize some options {{{ + if ($.browser.msie && ($.browser.version.split('.')[0] === '6')) { + ie6mode = true; + } + if (typeof(obj) !== 'object') { + obj = $(obj)[0]; + } + if (typeof(opt) !== 'object') { + opt = {}; + } + // }}} + setOptions(opt); + // Initialize some jQuery objects {{{ + // The values are SET on the image(s) for the interface + // If the original image has any of these set, they will be reset + // However, if you destroy() the Jcrop instance the original image's + // character in the DOM will be as you left it. + var img_css = { + border: 'none', + margin: 0, + padding: 0, + position: 'absolute' + }; + + var $origimg = $(obj); + var $img = $origimg.clone().removeAttr('id').css(img_css); + + $img.width($origimg.width()); + $img.height($origimg.height()); + $origimg.after($img).hide(); + + presize($img, options.boxWidth, options.boxHeight); + + var boundx = $img.width(), + boundy = $img.height(), + + + $div = $('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({ + position: 'relative', + backgroundColor: options.bgColor + }).insertAfter($origimg).append($img); + + delete(options.bgColor); + if (options.addClass) { + $div.addClass(options.addClass); + } + + var $img2 = $('<img />') + .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy), + + $img_holder = $('<div />') + .width(pct(100)).height(pct(100)).css({ + zIndex: 310, + position: 'absolute', + overflow: 'hidden' + }).append($img2), + + $hdl_holder = $('<div />') + .width(pct(100)).height(pct(100)).css('zIndex', 320), + + $sel = $('<div />') + .css({ + position: 'absolute', + zIndex: 300 + }).insertBefore($img).append($img_holder, $hdl_holder); + + if (ie6mode) { + $sel.css({ + overflowY: 'hidden' + }); + } + + var bound = options.boundary; + var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({ + position: 'absolute', + top: px(-bound), + left: px(-bound), + zIndex: 290 + }).mousedown(newSelection); + + /* }}} */ + // Set more variables {{{ + var bgopacity = options.bgOpacity, + xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true, + btndown, animating, shift_down; + + docOffset = getPos($img); + // }}} + // }}} + // Internal Modules {{{ + // Touch Module {{{ + var Touch = (function () { + // Touch support detection function adapted (under MIT License) + // from code by Jeffrey Sambells - http://github.com/iamamused/ + function hasTouchSupport() { + var support = {}, + events = ['touchstart', 'touchmove', 'touchend'], + el = document.createElement('div'), i; + + try { + for(i=0; i<events.length; i++) { + var eventName = events[i]; + eventName = 'on' + eventName; + var isSupported = (eventName in el); + if (!isSupported) { + el.setAttribute(eventName, 'return;'); + isSupported = typeof el[eventName] == 'function'; + } + support[events[i]] = isSupported; + } + return support.touchstart && support.touchend && support.touchmove; + } + catch(err) { + return false; + } + } + + function detectSupport() { + if ((options.touchSupport === true) || (options.touchSupport === false)) return options.touchSupport; + else return hasTouchSupport(); + } + return { + createDragger: function (ord) { + return function (e) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + if (options.disabled) { + return false; + } + if ((ord === 'move') && !options.allowMove) { + return false; + } + btndown = true; + startDragMode(ord, mouseAbs(e)); + e.stopPropagation(); + e.preventDefault(); + return false; + }; + }, + newSelection: function (e) { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + return newSelection(e); + }, + isSupported: hasTouchSupport, + support: detectSupport() + }; + }()); + // }}} + // Coords Module {{{ + var Coords = (function () { + var x1 = 0, + y1 = 0, + x2 = 0, + y2 = 0, + ox, oy; + + function setPressed(pos) //{{{ + { + pos = rebound(pos); + x2 = x1 = pos[0]; + y2 = y1 = pos[1]; + } + //}}} + function setCurrent(pos) //{{{ + { + pos = rebound(pos); + ox = pos[0] - x2; + oy = pos[1] - y2; + x2 = pos[0]; + y2 = pos[1]; + } + //}}} + function getOffset() //{{{ + { + return [ox, oy]; + } + //}}} + function moveOffset(offset) //{{{ + { + var ox = offset[0], + oy = offset[1]; + + if (0 > x1 + ox) { + ox -= ox + x1; + } + if (0 > y1 + oy) { + oy -= oy + y1; + } + + if (boundy < y2 + oy) { + oy += boundy - (y2 + oy); + } + if (boundx < x2 + ox) { + ox += boundx - (x2 + ox); + } + + x1 += ox; + x2 += ox; + y1 += oy; + y2 += oy; + } + //}}} + function getCorner(ord) //{{{ + { + var c = getFixed(); + switch (ord) { + case 'ne': + return [c.x2, c.y]; + case 'nw': + return [c.x, c.y]; + case 'se': + return [c.x2, c.y2]; + case 'sw': + return [c.x, c.y2]; + } + } + //}}} + function getFixed() //{{{ + { + if (!options.aspectRatio) { + return getRect(); + } + // This function could use some optimization I think... + var aspect = options.aspectRatio, + min_x = options.minSize[0] / xscale, + + + //min_y = options.minSize[1]/yscale, + max_x = options.maxSize[0] / xscale, + max_y = options.maxSize[1] / yscale, + rw = x2 - x1, + rh = y2 - y1, + rwa = Math.abs(rw), + rha = Math.abs(rh), + real_ratio = rwa / rha, + xx, yy; + + if (max_x === 0) { + max_x = boundx * 10; + } + if (max_y === 0) { + max_y = boundy * 10; + } + if (real_ratio < aspect) { + yy = y2; + w = rha * aspect; + xx = rw < 0 ? x1 - w : w + x1; + + if (xx < 0) { + xx = 0; + h = Math.abs((xx - x1) / aspect); + yy = rh < 0 ? y1 - h : h + y1; + } else if (xx > boundx) { + xx = boundx; + h = Math.abs((xx - x1) / aspect); + yy = rh < 0 ? y1 - h : h + y1; + } + } else { + xx = x2; + h = rwa / aspect; + yy = rh < 0 ? y1 - h : y1 + h; + if (yy < 0) { + yy = 0; + w = Math.abs((yy - y1) * aspect); + xx = rw < 0 ? x1 - w : w + x1; + } else if (yy > boundy) { + yy = boundy; + w = Math.abs(yy - y1) * aspect; + xx = rw < 0 ? x1 - w : w + x1; + } + } + + // Magic %-) + if (xx > x1) { // right side + if (xx - x1 < min_x) { + xx = x1 + min_x; + } else if (xx - x1 > max_x) { + xx = x1 + max_x; + } + if (yy > y1) { + yy = y1 + (xx - x1) / aspect; + } else { + yy = y1 - (xx - x1) / aspect; + } + } else if (xx < x1) { // left side + if (x1 - xx < min_x) { + xx = x1 - min_x; + } else if (x1 - xx > max_x) { + xx = x1 - max_x; + } + if (yy > y1) { + yy = y1 + (x1 - xx) / aspect; + } else { + yy = y1 - (x1 - xx) / aspect; + } + } + + if (xx < 0) { + x1 -= xx; + xx = 0; + } else if (xx > boundx) { + x1 -= xx - boundx; + xx = boundx; + } + + if (yy < 0) { + y1 -= yy; + yy = 0; + } else if (yy > boundy) { + y1 -= yy - boundy; + yy = boundy; + } + + return makeObj(flipCoords(x1, y1, xx, yy)); + } + //}}} + function rebound(p) //{{{ + { + if (p[0] < 0) { + p[0] = 0; + } + if (p[1] < 0) { + p[1] = 0; + } + + if (p[0] > boundx) { + p[0] = boundx; + } + if (p[1] > boundy) { + p[1] = boundy; + } + + return [p[0], p[1]]; + } + //}}} + function flipCoords(x1, y1, x2, y2) //{{{ + { + var xa = x1, + xb = x2, + ya = y1, + yb = y2; + if (x2 < x1) { + xa = x2; + xb = x1; + } + if (y2 < y1) { + ya = y2; + yb = y1; + } + return [Math.round(xa), Math.round(ya), Math.round(xb), Math.round(yb)]; + } + //}}} + function getRect() //{{{ + { + var xsize = x2 - x1, + ysize = y2 - y1, + delta; + + if (xlimit && (Math.abs(xsize) > xlimit)) { + x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit); + } + if (ylimit && (Math.abs(ysize) > ylimit)) { + y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit); + } + + if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) { + y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale); + } + if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) { + x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale); + } + + if (x1 < 0) { + x2 -= x1; + x1 -= x1; + } + if (y1 < 0) { + y2 -= y1; + y1 -= y1; + } + if (x2 < 0) { + x1 -= x2; + x2 -= x2; + } + if (y2 < 0) { + y1 -= y2; + y2 -= y2; + } + if (x2 > boundx) { + delta = x2 - boundx; + x1 -= delta; + x2 -= delta; + } + if (y2 > boundy) { + delta = y2 - boundy; + y1 -= delta; + y2 -= delta; + } + if (x1 > boundx) { + delta = x1 - boundy; + y2 -= delta; + y1 -= delta; + } + if (y1 > boundy) { + delta = y1 - boundy; + y2 -= delta; + y1 -= delta; + } + + return makeObj(flipCoords(x1, y1, x2, y2)); + } + //}}} + function makeObj(a) //{{{ + { + return { + x: a[0], + y: a[1], + x2: a[2], + y2: a[3], + w: a[2] - a[0], + h: a[3] - a[1] + }; + } + //}}} + + return { + flipCoords: flipCoords, + setPressed: setPressed, + setCurrent: setCurrent, + getOffset: getOffset, + moveOffset: moveOffset, + getCorner: getCorner, + getFixed: getFixed + }; + }()); + + //}}} + // Selection Module {{{ + var Selection = (function () { + var awake, hdep = 370; + var borders = {}; + var handle = {}; + var seehandles = false; + var hhs = options.handleOffset; + + // Private Methods + function insertBorder(type) //{{{ + { + var jq = $('<div />').css({ + position: 'absolute', + opacity: options.borderOpacity + }).addClass(cssClass(type)); + $img_holder.append(jq); + return jq; + } + //}}} + function dragDiv(ord, zi) //{{{ + { + var jq = $('<div />').mousedown(createDragger(ord)).css({ + cursor: ord + '-resize', + position: 'absolute', + zIndex: zi + }); + + if (Touch.support) { + jq.bind('touchstart', Touch.createDragger(ord)); + } + + $hdl_holder.append(jq); + return jq; + } + //}}} + function insertHandle(ord) //{{{ + { + return dragDiv(ord, hdep++).css({ + top: px(-hhs + 1), + left: px(-hhs + 1), + opacity: options.handleOpacity + }).addClass(cssClass('handle')); + } + //}}} + function insertDragbar(ord) //{{{ + { + var s = options.handleSize, + h = s, + w = s, + t = hhs, + l = hhs; + + switch (ord) { + case 'n': + case 's': + w = pct(100); + break; + case 'e': + case 'w': + h = pct(100); + break; + } + + return dragDiv(ord, hdep++).width(w).height(h).css({ + top: px(-t + 1), + left: px(-l + 1) + }); + } + //}}} + function createHandles(li) //{{{ + { + var i; + for (i = 0; i < li.length; i++) { + handle[li[i]] = insertHandle(li[i]); + } + } + //}}} + function moveHandles(c) //{{{ + { + var midvert = Math.round((c.h / 2) - hhs), + midhoriz = Math.round((c.w / 2) - hhs), + north = -hhs + 1, + west = -hhs + 1, + east = c.w - hhs, + south = c.h - hhs, + x, y; + + if (handle.e) { + handle.e.css({ + top: px(midvert), + left: px(east) + }); + handle.w.css({ + top: px(midvert) + }); + handle.s.css({ + top: px(south), + left: px(midhoriz) + }); + handle.n.css({ + left: px(midhoriz) + }); + } + if (handle.ne) { + handle.ne.css({ + left: px(east) + }); + handle.se.css({ + top: px(south), + left: px(east) + }); + handle.sw.css({ + top: px(south) + }); + } + if (handle.b) { + handle.b.css({ + top: px(south) + }); + handle.r.css({ + left: px(east) + }); + } + } + //}}} + function moveto(x, y) //{{{ + { + $img2.css({ + top: px(-y), + left: px(-x) + }); + $sel.css({ + top: px(y), + left: px(x) + }); + } + //}}} + function resize(w, h) //{{{ + { + $sel.width(w).height(h); + } + //}}} + function refresh() //{{{ + { + var c = Coords.getFixed(); + + Coords.setPressed([c.x, c.y]); + Coords.setCurrent([c.x2, c.y2]); + + updateVisible(); + } + //}}} + + // Internal Methods + function updateVisible() //{{{ + { + if (awake) { + return update(); + } + } + //}}} + function update() //{{{ + { + var c = Coords.getFixed(); + + resize(c.w, c.h); + moveto(c.x, c.y); + +/* + options.drawBorders && + borders.right.css({ left: px(c.w-1) }) && + borders.bottom.css({ top: px(c.h-1) }); + */ + + if (seehandles) { + moveHandles(c); + } + if (!awake) { + show(); + } + + options.onChange.call(api, unscale(c)); + } + //}}} + function show() //{{{ + { + $sel.show(); + + if (options.bgFade) { + $img.fadeTo(options.fadeTime, bgopacity); + } else { + $img.css('opacity', bgopacity); + } + + awake = true; + } + //}}} + function release() //{{{ + { + disableHandles(); + $sel.hide(); + + if (options.bgFade) { + $img.fadeTo(options.fadeTime, 1); + } else { + $img.css('opacity', 1); + } + + awake = false; + options.onRelease.call(api); + } + //}}} + function showHandles() //{{{ + { + if (seehandles) { + moveHandles(Coords.getFixed()); + $hdl_holder.show(); + } + } + //}}} + function enableHandles() //{{{ + { + seehandles = true; + if (options.allowResize) { + moveHandles(Coords.getFixed()); + $hdl_holder.show(); + return true; + } + } + //}}} + function disableHandles() //{{{ + { + seehandles = false; + $hdl_holder.hide(); + } + //}}} + function animMode(v) //{{{ + { + if (animating === v) { + disableHandles(); + } else { + enableHandles(); + } + } + //}}} + function done() //{{{ + { + animMode(false); + refresh(); + } + //}}} + /* Insert draggable elements {{{*/ + + // Insert border divs for outline + if (options.drawBorders) { + borders = { + top: insertBorder('hline'), + bottom: insertBorder('hline bottom'), + left: insertBorder('vline'), + right: insertBorder('vline right') + }; + } + + // Insert handles on edges + if (options.dragEdges) { + handle.t = insertDragbar('n'); + handle.b = insertDragbar('s'); + handle.r = insertDragbar('e'); + handle.l = insertDragbar('w'); + } + + // Insert side and corner handles + if (options.sideHandles) { + createHandles(['n', 's', 'e', 'w']); + } + if (options.cornerHandles) { + createHandles(['sw', 'nw', 'ne', 'se']); + } + + + //}}} + + var $track = newTracker().mousedown(createDragger('move')).css({ + cursor: 'move', + position: 'absolute', + zIndex: 360 + }); + + if (Touch.support) { + $track.bind('touchstart.jcrop', Touch.createDragger('move')); + } + + $img_holder.append($track); + disableHandles(); + + return { + updateVisible: updateVisible, + update: update, + release: release, + refresh: refresh, + isAwake: function () { + return awake; + }, + setCursor: function (cursor) { + $track.css('cursor', cursor); + }, + enableHandles: enableHandles, + enableOnly: function () { + seehandles = true; + }, + showHandles: showHandles, + disableHandles: disableHandles, + animMode: animMode, + done: done + }; + }()); + + //}}} + // Tracker Module {{{ + var Tracker = (function () { + var onMove = function () {}, + onDone = function () {}, + trackDoc = options.trackDocument; + + function toFront() //{{{ + { + $trk.css({ + zIndex: 450 + }); + if (trackDoc) { + $(document) + .bind('mousemove',trackMove) + .bind('mouseup',trackUp); + } + } + //}}} + function toBack() //{{{ + { + $trk.css({ + zIndex: 290 + }); + if (trackDoc) { + $(document) + .unbind('mousemove', trackMove) + .unbind('mouseup', trackUp); + } + } + //}}} + function trackMove(e) //{{{ + { + onMove(mouseAbs(e)); + return false; + } + //}}} + function trackUp(e) //{{{ + { + e.preventDefault(); + e.stopPropagation(); + + if (btndown) { + btndown = false; + + onDone(mouseAbs(e)); + + if (Selection.isAwake()) { + options.onSelect.call(api, unscale(Coords.getFixed())); + } + + toBack(); + onMove = function () {}; + onDone = function () {}; + } + + return false; + } + //}}} + function activateHandlers(move, done) //{{{ + { + btndown = true; + onMove = move; + onDone = done; + toFront(); + return false; + } + //}}} + function trackTouchMove(e) //{{{ + { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + return trackMove(e); + } + //}}} + function trackTouchEnd(e) //{{{ + { + e.pageX = e.originalEvent.changedTouches[0].pageX; + e.pageY = e.originalEvent.changedTouches[0].pageY; + return trackUp(e); + } + //}}} + function setCursor(t) //{{{ + { + $trk.css('cursor', t); + } + //}}} + + if (Touch.support) { + $(document) + .bind('touchmove', trackTouchMove) + .bind('touchend', trackTouchEnd); + } + + if (!trackDoc) { + $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp); + } + + $img.before($trk); + return { + activateHandlers: activateHandlers, + setCursor: setCursor + }; + }()); + //}}} + // KeyManager Module {{{ + var KeyManager = (function () { + var $keymgr = $('<input type="radio" />').css({ + position: 'fixed', + left: '-120px', + width: '12px' + }), + $keywrap = $('<div />').css({ + position: 'absolute', + overflow: 'hidden' + }).append($keymgr); + + function watchKeys() //{{{ + { + if (options.keySupport) { + $keymgr.show(); + $keymgr.focus(); + } + } + //}}} + function onBlur(e) //{{{ + { + $keymgr.hide(); + } + //}}} + function doNudge(e, x, y) //{{{ + { + if (options.allowMove) { + Coords.moveOffset([x, y]); + Selection.updateVisible(); + } + e.preventDefault(); + e.stopPropagation(); + } + //}}} + function parseKey(e) //{{{ + { + if (e.ctrlKey) { + return true; + } + shift_down = e.shiftKey ? true : false; + var nudge = shift_down ? 10 : 1; + + switch (e.keyCode) { + case 37: + doNudge(e, -nudge, 0); + break; + case 39: + doNudge(e, nudge, 0); + break; + case 38: + doNudge(e, 0, -nudge); + break; + case 40: + doNudge(e, 0, nudge); + break; + case 27: + Selection.release(); + break; + case 9: + return true; + } + + return false; + } + //}}} + + if (options.keySupport) { + $keymgr.keydown(parseKey).blur(onBlur); + if (ie6mode || !options.fixedSupport) { + $keymgr.css({ + position: 'absolute', + left: '-20px' + }); + $keywrap.append($keymgr).insertBefore($img); + } else { + $keymgr.insertBefore($img); + } + } + + + return { + watchKeys: watchKeys + }; + }()); + //}}} + // }}} + // API methods {{{ + function setClass(cname) //{{{ + { + $div.removeClass().addClass(cssClass('holder')).addClass(cname); + } + //}}} + function animateTo(a, callback) //{{{ + { + var x1 = parseInt(a[0], 10) / xscale, + y1 = parseInt(a[1], 10) / yscale, + x2 = parseInt(a[2], 10) / xscale, + y2 = parseInt(a[3], 10) / yscale; + + if (animating) { + return; + } + + var animto = Coords.flipCoords(x1, y1, x2, y2), + c = Coords.getFixed(), + initcr = [c.x, c.y, c.x2, c.y2], + animat = initcr, + interv = options.animationDelay, + ix1 = animto[0] - initcr[0], + iy1 = animto[1] - initcr[1], + ix2 = animto[2] - initcr[2], + iy2 = animto[3] - initcr[3], + pcent = 0, + velocity = options.swingSpeed; + + x = animat[0]; + y = animat[1]; + x2 = animat[2]; + y2 = animat[3]; + + Selection.animMode(true); + var anim_timer; + + function queueAnimator() { + window.setTimeout(animator, interv); + } + var animator = (function () { + return function () { + pcent += (100 - pcent) / velocity; + + animat[0] = x + ((pcent / 100) * ix1); + animat[1] = y + ((pcent / 100) * iy1); + animat[2] = x2 + ((pcent / 100) * ix2); + animat[3] = y2 + ((pcent / 100) * iy2); + + if (pcent >= 99.8) { + pcent = 100; + } + if (pcent < 100) { + setSelectRaw(animat); + queueAnimator(); + } else { + Selection.done(); + if (typeof(callback) === 'function') { + callback.call(api); + } + } + }; + }()); + queueAnimator(); + } + //}}} + function setSelect(rect) //{{{ + { + setSelectRaw([ + parseInt(rect[0], 10) / xscale, parseInt(rect[1], 10) / yscale, parseInt(rect[2], 10) / xscale, parseInt(rect[3], 10) / yscale]); + } + //}}} + function setSelectRaw(l) //{{{ + { + Coords.setPressed([l[0], l[1]]); + Coords.setCurrent([l[2], l[3]]); + Selection.update(); + } + //}}} + function tellSelect() //{{{ + { + return unscale(Coords.getFixed()); + } + //}}} + function tellScaled() //{{{ + { + return Coords.getFixed(); + } + //}}} + function setOptionsNew(opt) //{{{ + { + setOptions(opt); + interfaceUpdate(); + } + //}}} + function disableCrop() //{{{ + { + options.disabled = true; + Selection.disableHandles(); + Selection.setCursor('default'); + Tracker.setCursor('default'); + } + //}}} + function enableCrop() //{{{ + { + options.disabled = false; + interfaceUpdate(); + } + //}}} + function cancelCrop() //{{{ + { + Selection.done(); + Tracker.activateHandlers(null, null); + } + //}}} + function destroy() //{{{ + { + $div.remove(); + $origimg.show(); + $(obj).removeData('Jcrop'); + } + //}}} + function setImage(src, callback) //{{{ + { + Selection.release(); + disableCrop(); + var img = new Image(); + img.onload = function () { + var iw = img.width; + var ih = img.height; + var bw = options.boxWidth; + var bh = options.boxHeight; + $img.width(iw).height(ih); + $img.attr('src', src); + $img2.attr('src', src); + presize($img, bw, bh); + boundx = $img.width(); + boundy = $img.height(); + $img2.width(boundx).height(boundy); + $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2)); + $div.width(boundx).height(boundy); + enableCrop(); + + if (typeof(callback) === 'function') { + callback.call(api); + } + }; + img.src = src; + } + //}}} + function interfaceUpdate(alt) //{{{ + // This method tweaks the interface based on options object. + // Called when options are changed and at end of initialization. + { + if (options.allowResize) { + if (alt) { + Selection.enableOnly(); + } else { + Selection.enableHandles(); + } + } else { + Selection.disableHandles(); + } + + Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); + Selection.setCursor(options.allowMove ? 'move' : 'default'); + + + if (options.hasOwnProperty('setSelect')) { + setSelect(options.setSelect); + Selection.done(); + delete(options.setSelect); + } + + if (options.hasOwnProperty('trueSize')) { + xscale = options.trueSize[0] / boundx; + yscale = options.trueSize[1] / boundy; + } + if (options.hasOwnProperty('bgColor')) { + + if (supportsColorFade() && options.fadeTime) { + $div.animate({ + backgroundColor: options.bgColor + }, { + queue: false, + duration: options.fadeTime + }); + } else { + $div.css('backgroundColor', options.bgColor); + } + + delete(options.bgColor); + } + if (options.hasOwnProperty('bgOpacity')) { + bgopacity = options.bgOpacity; + + if (Selection.isAwake()) { + if (options.fadeTime) { + $img.fadeTo(options.fadeTime, bgopacity); + } else { + $div.css('opacity', options.opacity); + } + } + delete(options.bgOpacity); + } + + xlimit = options.maxSize[0] || 0; + ylimit = options.maxSize[1] || 0; + xmin = options.minSize[0] || 0; + ymin = options.minSize[1] || 0; + + if (options.hasOwnProperty('outerImage')) { + $img.attr('src', options.outerImage); + delete(options.outerImage); + } + + Selection.refresh(); + } + //}}} + //}}} + + if (Touch.support) { + $trk.bind('touchstart', Touch.newSelection); + } + + $hdl_holder.hide(); + interfaceUpdate(true); + + var api = { + setImage: setImage, + animateTo: animateTo, + setSelect: setSelect, + setOptions: setOptionsNew, + tellSelect: tellSelect, + tellScaled: tellScaled, + setClass: setClass, + + disable: disableCrop, + enable: enableCrop, + cancel: cancelCrop, + release: Selection.release, + destroy: destroy, + + focus: KeyManager.watchKeys, + + getBounds: function () { + return [boundx * xscale, boundy * yscale]; + }, + getWidgetSize: function () { + return [boundx, boundy]; + }, + getScaleFactor: function () { + return [xscale, yscale]; + }, + + ui: { + holder: $div, + selection: $sel + } + }; + + if ($.browser.msie) { + $div.bind('selectstart', function () { + return false; + }); + } + + $origimg.data('Jcrop', api); + return api; + }; + $.fn.Jcrop = function (options, callback) //{{{ + { + + function attachWhenDone(from) //{{{ + { + var opt = (typeof(options) === 'object') ? options : {}; + var loadsrc = opt.useImg || from.src; + var img = new Image(); + img.onload = function () { + function attachJcrop() { + var api = $.Jcrop(from, opt); + if (typeof(callback) === 'function') { + callback.call(api); + } + } + + function attachAttempt() { + if (!img.width || !img.height) { + window.setTimeout(attachAttempt, 50); + } else { + attachJcrop(); + } + } + window.setTimeout(attachAttempt, 50); + }; + img.src = loadsrc; + } + //}}} + + // Iterate over each object, attach Jcrop + this.each(function () { + // If we've already attached to this object + if ($(this).data('Jcrop')) { + // The API can be requested this way (undocumented) + if (options === 'api') { + return $(this).data('Jcrop'); + } + // Otherwise, we just reset the options... + else { + $(this).data('Jcrop').setOptions(options); + } + } + // If we haven't been attached, preload and attach + else { + attachWhenDone(this); + } + }); + + // Return "this" so the object is chainable (jQuery-style) + return this; + }; + //}}} + // Global Defaults {{{ + $.Jcrop.defaults = { + + // Basic Settings + allowSelect: true, + allowMove: true, + allowResize: true, + + trackDocument: true, + + // Styling Options + baseClass: 'jcrop', + addClass: null, + bgColor: 'black', + bgOpacity: 0.6, + bgFade: false, + borderOpacity: 0.4, + handleOpacity: 0.5, + handleSize: 9, + handleOffset: 5, + + aspectRatio: 0, + keySupport: true, + cornerHandles: true, + sideHandles: true, + drawBorders: true, + dragEdges: true, + fixedSupport: true, + touchSupport: null, + + boxWidth: 0, + boxHeight: 0, + boundary: 2, + fadeTime: 400, + animationDelay: 20, + swingSpeed: 3, + + minSelect: [0, 0], + maxSize: [0, 0], + minSize: [0, 0], + + // Callbacks / Event Handlers + onChange: function () {}, + onSelect: function () {}, + onRelease: function () {} + }; + + // }}} +}(jQuery)); diff --git a/themes/default/js/plugins/jquery.Jcrop.min.js b/themes/default/js/plugins/jquery.Jcrop.min.js new file mode 100644 index 000000000..a8a9f5035 --- /dev/null +++ b/themes/default/js/plugins/jquery.Jcrop.min.js @@ -0,0 +1,246 @@ +/** + * jquery.Jcrop.min.js v0.9.9 (build:20110607) + * jQuery Image Cropping Plugin + * @author Kelly Hallman <khallman@gmail.com> + * Copyright (c) 2008-2011 Kelly Hallman - released under MIT License + * https://github.com/tapmodo/Jcrop + */ + +(function($){$.Jcrop=function(obj,opt){var options=$.extend({},$.Jcrop.defaults),docOffset,lastcurs,ie6mode=false;function px(n){return parseInt(n,10)+'px';} +function pct(n){return parseInt(n,10)+'%';} +function cssClass(cl){return options.baseClass+'-'+cl;} +function supportsColorFade(){return $.fx.step.hasOwnProperty('backgroundColor');} +function getPos(obj) +{var pos=$(obj).offset();return[pos.left,pos.top];} +function mouseAbs(e) +{return[(e.pageX-docOffset[0]),(e.pageY-docOffset[1])];} +function setOptions(opt) +{if(typeof(opt)!=='object'){opt={};} +options=$.extend(options,opt);if(typeof(options.onChange)!=='function'){options.onChange=function(){};} +if(typeof(options.onSelect)!=='function'){options.onSelect=function(){};} +if(typeof(options.onRelease)!=='function'){options.onRelease=function(){};}} +function myCursor(type) +{if(type!==lastcurs){Tracker.setCursor(type);lastcurs=type;}} +function startDragMode(mode,pos) +{docOffset=getPos($img);Tracker.setCursor(mode==='move'?mode:mode+'-resize');if(mode==='move'){return Tracker.activateHandlers(createMover(pos),doneSelect);} +var fc=Coords.getFixed();var opp=oppLockCorner(mode);var opc=Coords.getCorner(oppLockCorner(opp));Coords.setPressed(Coords.getCorner(opp));Coords.setCurrent(opc);Tracker.activateHandlers(dragmodeHandler(mode,fc),doneSelect);} +function dragmodeHandler(mode,f) +{return function(pos){if(!options.aspectRatio){switch(mode){case'e':pos[1]=f.y2;break;case'w':pos[1]=f.y2;break;case'n':pos[0]=f.x2;break;case's':pos[0]=f.x2;break;}}else{switch(mode){case'e':pos[1]=f.y+1;break;case'w':pos[1]=f.y+1;break;case'n':pos[0]=f.x+1;break;case's':pos[0]=f.x+1;break;}} +Coords.setCurrent(pos);Selection.update();};} +function createMover(pos) +{var lloc=pos;KeyManager.watchKeys();return function(pos){Coords.moveOffset([pos[0]-lloc[0],pos[1]-lloc[1]]);lloc=pos;Selection.update();};} +function oppLockCorner(ord) +{switch(ord){case'n':return'sw';case's':return'nw';case'e':return'nw';case'w':return'ne';case'ne':return'sw';case'nw':return'se';case'se':return'nw';case'sw':return'ne';}} +function createDragger(ord) +{return function(e){if(options.disabled){return false;} +if((ord==='move')&&!options.allowMove){return false;} +btndown=true;startDragMode(ord,mouseAbs(e));e.stopPropagation();e.preventDefault();return false;};} +function presize($obj,w,h) +{var nw=$obj.width(),nh=$obj.height();if((nw>w)&&w>0){nw=w;nh=(w/$obj.width())*$obj.height();} +if((nh>h)&&h>0){nh=h;nw=(h/$obj.height())*$obj.width();} +xscale=$obj.width()/nw;yscale=$obj.height()/nh;$obj.width(nw).height(nh);} +function unscale(c) +{return{x:parseInt(c.x*xscale,10),y:parseInt(c.y*yscale,10),x2:parseInt(c.x2*xscale,10),y2:parseInt(c.y2*yscale,10),w:parseInt(c.w*xscale,10),h:parseInt(c.h*yscale,10)};} +function doneSelect(pos) +{var c=Coords.getFixed();if((c.w>options.minSelect[0])&&(c.h>options.minSelect[1])){Selection.enableHandles();Selection.done();}else{Selection.release();} +Tracker.setCursor(options.allowSelect?'crosshair':'default');} +function newSelection(e) +{if(options.disabled){return false;} +if(!options.allowSelect){return false;} +btndown=true;docOffset=getPos($img);Selection.disableHandles();myCursor('crosshair');var pos=mouseAbs(e);Coords.setPressed(pos);Selection.update();Tracker.activateHandlers(selectDrag,doneSelect);KeyManager.watchKeys();e.stopPropagation();e.preventDefault();return false;} +function selectDrag(pos) +{Coords.setCurrent(pos);Selection.update();} +function newTracker() +{var trk=$('<div></div>').addClass(cssClass('tracker'));if($.browser.msie){trk.css({opacity:0,backgroundColor:'white'});} +return trk;} +if($.browser.msie&&($.browser.version.split('.')[0]==='6')){ie6mode=true;} +if(typeof(obj)!=='object'){obj=$(obj)[0];} +if(typeof(opt)!=='object'){opt={};} +setOptions(opt);var img_css={border:'none',margin:0,padding:0,position:'absolute'};var $origimg=$(obj);var $img=$origimg.clone().removeAttr('id').css(img_css);$img.width($origimg.width());$img.height($origimg.height());$origimg.after($img).hide();presize($img,options.boxWidth,options.boxHeight);var boundx=$img.width(),boundy=$img.height(),$div=$('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({position:'relative',backgroundColor:options.bgColor}).insertAfter($origimg).append($img);delete(options.bgColor);if(options.addClass){$div.addClass(options.addClass);} +var $img2=$('<img />').attr('src',$img.attr('src')).css(img_css).width(boundx).height(boundy),$img_holder=$('<div />').width(pct(100)).height(pct(100)).css({zIndex:310,position:'absolute',overflow:'hidden'}).append($img2),$hdl_holder=$('<div />').width(pct(100)).height(pct(100)).css('zIndex',320),$sel=$('<div />').css({position:'absolute',zIndex:300}).insertBefore($img).append($img_holder,$hdl_holder);if(ie6mode){$sel.css({overflowY:'hidden'});} +var bound=options.boundary;var $trk=newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)).css({position:'absolute',top:px(-bound),left:px(-bound),zIndex:290}).mousedown(newSelection);var bgopacity=options.bgOpacity,xlimit,ylimit,xmin,ymin,xscale,yscale,enabled=true,btndown,animating,shift_down;docOffset=getPos($img);var Touch=(function(){function hasTouchSupport(){var support={},events=['touchstart','touchmove','touchend'],el=document.createElement('div'),i;try{for(i=0;i<events.length;i++){var eventName=events[i];eventName='on'+eventName;var isSupported=(eventName in el);if(!isSupported){el.setAttribute(eventName,'return;');isSupported=typeof el[eventName]=='function';} +support[events[i]]=isSupported;} +return support.touchstart&&support.touchend&&support.touchmove;} +catch(err){return false;}} +function detectSupport(){if((options.touchSupport===true)||(options.touchSupport===false))return options.touchSupport;else return hasTouchSupport();} +return{createDragger:function(ord){return function(e){e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;if(options.disabled){return false;} +if((ord==='move')&&!options.allowMove){return false;} +btndown=true;startDragMode(ord,mouseAbs(e));e.stopPropagation();e.preventDefault();return false;};},newSelection:function(e){e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;return newSelection(e);},isSupported:hasTouchSupport,support:detectSupport()};}());var Coords=(function(){var x1=0,y1=0,x2=0,y2=0,ox,oy;function setPressed(pos) +{pos=rebound(pos);x2=x1=pos[0];y2=y1=pos[1];} +function setCurrent(pos) +{pos=rebound(pos);ox=pos[0]-x2;oy=pos[1]-y2;x2=pos[0];y2=pos[1];} +function getOffset() +{return[ox,oy];} +function moveOffset(offset) +{var ox=offset[0],oy=offset[1];if(0>x1+ox){ox-=ox+x1;} +if(0>y1+oy){oy-=oy+y1;} +if(boundy<y2+oy){oy+=boundy-(y2+oy);} +if(boundx<x2+ox){ox+=boundx-(x2+ox);} +x1+=ox;x2+=ox;y1+=oy;y2+=oy;} +function getCorner(ord) +{var c=getFixed();switch(ord){case'ne':return[c.x2,c.y];case'nw':return[c.x,c.y];case'se':return[c.x2,c.y2];case'sw':return[c.x,c.y2];}} +function getFixed() +{if(!options.aspectRatio){return getRect();} +var aspect=options.aspectRatio,min_x=options.minSize[0]/xscale,max_x=options.maxSize[0]/xscale,max_y=options.maxSize[1]/yscale,rw=x2-x1,rh=y2-y1,rwa=Math.abs(rw),rha=Math.abs(rh),real_ratio=rwa/rha,xx,yy;if(max_x===0){max_x=boundx*10;} +if(max_y===0){max_y=boundy*10;} +if(real_ratio<aspect){yy=y2;w=rha*aspect;xx=rw<0?x1-w:w+x1;if(xx<0){xx=0;h=Math.abs((xx-x1)/aspect);yy=rh<0?y1-h:h+y1;}else if(xx>boundx){xx=boundx;h=Math.abs((xx-x1)/aspect);yy=rh<0?y1-h:h+y1;}}else{xx=x2;h=rwa/aspect;yy=rh<0?y1-h:y1+h;if(yy<0){yy=0;w=Math.abs((yy-y1)*aspect);xx=rw<0?x1-w:w+x1;}else if(yy>boundy){yy=boundy;w=Math.abs(yy-y1)*aspect;xx=rw<0?x1-w:w+x1;}} +if(xx>x1){if(xx-x1<min_x){xx=x1+min_x;}else if(xx-x1>max_x){xx=x1+max_x;} +if(yy>y1){yy=y1+(xx-x1)/aspect;}else{yy=y1-(xx-x1)/aspect;}}else if(xx<x1){if(x1-xx<min_x){xx=x1-min_x;}else if(x1-xx>max_x){xx=x1-max_x;} +if(yy>y1){yy=y1+(x1-xx)/aspect;}else{yy=y1-(x1-xx)/aspect;}} +if(xx<0){x1-=xx;xx=0;}else if(xx>boundx){x1-=xx-boundx;xx=boundx;} +if(yy<0){y1-=yy;yy=0;}else if(yy>boundy){y1-=yy-boundy;yy=boundy;} +return makeObj(flipCoords(x1,y1,xx,yy));} +function rebound(p) +{if(p[0]<0){p[0]=0;} +if(p[1]<0){p[1]=0;} +if(p[0]>boundx){p[0]=boundx;} +if(p[1]>boundy){p[1]=boundy;} +return[p[0],p[1]];} +function flipCoords(x1,y1,x2,y2) +{var xa=x1,xb=x2,ya=y1,yb=y2;if(x2<x1){xa=x2;xb=x1;} +if(y2<y1){ya=y2;yb=y1;} +return[Math.round(xa),Math.round(ya),Math.round(xb),Math.round(yb)];} +function getRect() +{var xsize=x2-x1,ysize=y2-y1,delta;if(xlimit&&(Math.abs(xsize)>xlimit)){x2=(xsize>0)?(x1+xlimit):(x1-xlimit);} +if(ylimit&&(Math.abs(ysize)>ylimit)){y2=(ysize>0)?(y1+ylimit):(y1-ylimit);} +if(ymin/yscale&&(Math.abs(ysize)<ymin/yscale)){y2=(ysize>0)?(y1+ymin/yscale):(y1-ymin/yscale);} +if(xmin/xscale&&(Math.abs(xsize)<xmin/xscale)){x2=(xsize>0)?(x1+xmin/xscale):(x1-xmin/xscale);} +if(x1<0){x2-=x1;x1-=x1;} +if(y1<0){y2-=y1;y1-=y1;} +if(x2<0){x1-=x2;x2-=x2;} +if(y2<0){y1-=y2;y2-=y2;} +if(x2>boundx){delta=x2-boundx;x1-=delta;x2-=delta;} +if(y2>boundy){delta=y2-boundy;y1-=delta;y2-=delta;} +if(x1>boundx){delta=x1-boundy;y2-=delta;y1-=delta;} +if(y1>boundy){delta=y1-boundy;y2-=delta;y1-=delta;} +return makeObj(flipCoords(x1,y1,x2,y2));} +function makeObj(a) +{return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]};} +return{flipCoords:flipCoords,setPressed:setPressed,setCurrent:setCurrent,getOffset:getOffset,moveOffset:moveOffset,getCorner:getCorner,getFixed:getFixed};}());var Selection=(function(){var awake,hdep=370;var borders={};var handle={};var seehandles=false;var hhs=options.handleOffset;function insertBorder(type) +{var jq=$('<div />').css({position:'absolute',opacity:options.borderOpacity}).addClass(cssClass(type));$img_holder.append(jq);return jq;} +function dragDiv(ord,zi) +{var jq=$('<div />').mousedown(createDragger(ord)).css({cursor:ord+'-resize',position:'absolute',zIndex:zi});if(Touch.support){jq.bind('touchstart',Touch.createDragger(ord));} +$hdl_holder.append(jq);return jq;} +function insertHandle(ord) +{return dragDiv(ord,hdep++).css({top:px(-hhs+1),left:px(-hhs+1),opacity:options.handleOpacity}).addClass(cssClass('handle'));} +function insertDragbar(ord) +{var s=options.handleSize,h=s,w=s,t=hhs,l=hhs;switch(ord){case'n':case's':w=pct(100);break;case'e':case'w':h=pct(100);break;} +return dragDiv(ord,hdep++).width(w).height(h).css({top:px(-t+1),left:px(-l+1)});} +function createHandles(li) +{var i;for(i=0;i<li.length;i++){handle[li[i]]=insertHandle(li[i]);}} +function moveHandles(c) +{var midvert=Math.round((c.h/2)-hhs),midhoriz=Math.round((c.w/2)-hhs),north=-hhs+1,west=-hhs+1,east=c.w-hhs,south=c.h-hhs,x,y;if(handle.e){handle.e.css({top:px(midvert),left:px(east)});handle.w.css({top:px(midvert)});handle.s.css({top:px(south),left:px(midhoriz)});handle.n.css({left:px(midhoriz)});} +if(handle.ne){handle.ne.css({left:px(east)});handle.se.css({top:px(south),left:px(east)});handle.sw.css({top:px(south)});} +if(handle.b){handle.b.css({top:px(south)});handle.r.css({left:px(east)});}} +function moveto(x,y) +{$img2.css({top:px(-y),left:px(-x)});$sel.css({top:px(y),left:px(x)});} +function resize(w,h) +{$sel.width(w).height(h);} +function refresh() +{var c=Coords.getFixed();Coords.setPressed([c.x,c.y]);Coords.setCurrent([c.x2,c.y2]);updateVisible();} +function updateVisible() +{if(awake){return update();}} +function update() +{var c=Coords.getFixed();resize(c.w,c.h);moveto(c.x,c.y);if(seehandles){moveHandles(c);} +if(!awake){show();} +options.onChange.call(api,unscale(c));} +function show() +{$sel.show();if(options.bgFade){$img.fadeTo(options.fadeTime,bgopacity);}else{$img.css('opacity',bgopacity);} +awake=true;} +function release() +{disableHandles();$sel.hide();if(options.bgFade){$img.fadeTo(options.fadeTime,1);}else{$img.css('opacity',1);} +awake=false;options.onRelease.call(api);} +function showHandles() +{if(seehandles){moveHandles(Coords.getFixed());$hdl_holder.show();}} +function enableHandles() +{seehandles=true;if(options.allowResize){moveHandles(Coords.getFixed());$hdl_holder.show();return true;}} +function disableHandles() +{seehandles=false;$hdl_holder.hide();} +function animMode(v) +{if(animating===v){disableHandles();}else{enableHandles();}} +function done() +{animMode(false);refresh();} +if(options.drawBorders){borders={top:insertBorder('hline'),bottom:insertBorder('hline bottom'),left:insertBorder('vline'),right:insertBorder('vline right')};} +if(options.dragEdges){handle.t=insertDragbar('n');handle.b=insertDragbar('s');handle.r=insertDragbar('e');handle.l=insertDragbar('w');} +if(options.sideHandles){createHandles(['n','s','e','w']);} +if(options.cornerHandles){createHandles(['sw','nw','ne','se']);} +var $track=newTracker().mousedown(createDragger('move')).css({cursor:'move',position:'absolute',zIndex:360});if(Touch.support){$track.bind('touchstart.jcrop',Touch.createDragger('move'));} +$img_holder.append($track);disableHandles();return{updateVisible:updateVisible,update:update,release:release,refresh:refresh,isAwake:function(){return awake;},setCursor:function(cursor){$track.css('cursor',cursor);},enableHandles:enableHandles,enableOnly:function(){seehandles=true;},showHandles:showHandles,disableHandles:disableHandles,animMode:animMode,done:done};}());var Tracker=(function(){var onMove=function(){},onDone=function(){},trackDoc=options.trackDocument;function toFront() +{$trk.css({zIndex:450});if(trackDoc){$(document).bind('mousemove',trackMove).bind('mouseup',trackUp);}} +function toBack() +{$trk.css({zIndex:290});if(trackDoc){$(document).unbind('mousemove',trackMove).unbind('mouseup',trackUp);}} +function trackMove(e) +{onMove(mouseAbs(e));return false;} +function trackUp(e) +{e.preventDefault();e.stopPropagation();if(btndown){btndown=false;onDone(mouseAbs(e));if(Selection.isAwake()){options.onSelect.call(api,unscale(Coords.getFixed()));} +toBack();onMove=function(){};onDone=function(){};} +return false;} +function activateHandlers(move,done) +{btndown=true;onMove=move;onDone=done;toFront();return false;} +function trackTouchMove(e) +{e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;return trackMove(e);} +function trackTouchEnd(e) +{e.pageX=e.originalEvent.changedTouches[0].pageX;e.pageY=e.originalEvent.changedTouches[0].pageY;return trackUp(e);} +function setCursor(t) +{$trk.css('cursor',t);} +if(Touch.support){$(document).bind('touchmove',trackTouchMove).bind('touchend',trackTouchEnd);} +if(!trackDoc){$trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);} +$img.before($trk);return{activateHandlers:activateHandlers,setCursor:setCursor};}());var KeyManager=(function(){var $keymgr=$('<input type="radio" />').css({position:'fixed',left:'-120px',width:'12px'}),$keywrap=$('<div />').css({position:'absolute',overflow:'hidden'}).append($keymgr);function watchKeys() +{if(options.keySupport){$keymgr.show();$keymgr.focus();}} +function onBlur(e) +{$keymgr.hide();} +function doNudge(e,x,y) +{if(options.allowMove){Coords.moveOffset([x,y]);Selection.updateVisible();} +e.preventDefault();e.stopPropagation();} +function parseKey(e) +{if(e.ctrlKey){return true;} +shift_down=e.shiftKey?true:false;var nudge=shift_down?10:1;switch(e.keyCode){case 37:doNudge(e,-nudge,0);break;case 39:doNudge(e,nudge,0);break;case 38:doNudge(e,0,-nudge);break;case 40:doNudge(e,0,nudge);break;case 27:Selection.release();break;case 9:return true;} +return false;} +if(options.keySupport){$keymgr.keydown(parseKey).blur(onBlur);if(ie6mode||!options.fixedSupport){$keymgr.css({position:'absolute',left:'-20px'});$keywrap.append($keymgr).insertBefore($img);}else{$keymgr.insertBefore($img);}} +return{watchKeys:watchKeys};}());function setClass(cname) +{$div.removeClass().addClass(cssClass('holder')).addClass(cname);} +function animateTo(a,callback) +{var x1=parseInt(a[0],10)/xscale,y1=parseInt(a[1],10)/yscale,x2=parseInt(a[2],10)/xscale,y2=parseInt(a[3],10)/yscale;if(animating){return;} +var animto=Coords.flipCoords(x1,y1,x2,y2),c=Coords.getFixed(),initcr=[c.x,c.y,c.x2,c.y2],animat=initcr,interv=options.animationDelay,ix1=animto[0]-initcr[0],iy1=animto[1]-initcr[1],ix2=animto[2]-initcr[2],iy2=animto[3]-initcr[3],pcent=0,velocity=options.swingSpeed;x=animat[0];y=animat[1];x2=animat[2];y2=animat[3];Selection.animMode(true);var anim_timer;function queueAnimator(){window.setTimeout(animator,interv);} +var animator=(function(){return function(){pcent+=(100-pcent)/velocity;animat[0]=x+((pcent/100)*ix1);animat[1]=y+((pcent/100)*iy1);animat[2]=x2+((pcent/100)*ix2);animat[3]=y2+((pcent/100)*iy2);if(pcent>=99.8){pcent=100;} +if(pcent<100){setSelectRaw(animat);queueAnimator();}else{Selection.done();if(typeof(callback)==='function'){callback.call(api);}}};}());queueAnimator();} +function setSelect(rect) +{setSelectRaw([parseInt(rect[0],10)/xscale,parseInt(rect[1],10)/yscale,parseInt(rect[2],10)/xscale,parseInt(rect[3],10)/yscale]);} +function setSelectRaw(l) +{Coords.setPressed([l[0],l[1]]);Coords.setCurrent([l[2],l[3]]);Selection.update();} +function tellSelect() +{return unscale(Coords.getFixed());} +function tellScaled() +{return Coords.getFixed();} +function setOptionsNew(opt) +{setOptions(opt);interfaceUpdate();} +function disableCrop() +{options.disabled=true;Selection.disableHandles();Selection.setCursor('default');Tracker.setCursor('default');} +function enableCrop() +{options.disabled=false;interfaceUpdate();} +function cancelCrop() +{Selection.done();Tracker.activateHandlers(null,null);} +function destroy() +{$div.remove();$origimg.show();$(obj).removeData('Jcrop');} +function setImage(src,callback) +{Selection.release();disableCrop();var img=new Image();img.onload=function(){var iw=img.width;var ih=img.height;var bw=options.boxWidth;var bh=options.boxHeight;$img.width(iw).height(ih);$img.attr('src',src);$img2.attr('src',src);presize($img,bw,bh);boundx=$img.width();boundy=$img.height();$img2.width(boundx).height(boundy);$trk.width(boundx+(bound*2)).height(boundy+(bound*2));$div.width(boundx).height(boundy);enableCrop();if(typeof(callback)==='function'){callback.call(api);}};img.src=src;} +function interfaceUpdate(alt) +{if(options.allowResize){if(alt){Selection.enableOnly();}else{Selection.enableHandles();}}else{Selection.disableHandles();} +Tracker.setCursor(options.allowSelect?'crosshair':'default');Selection.setCursor(options.allowMove?'move':'default');if(options.hasOwnProperty('setSelect')){setSelect(options.setSelect);Selection.done();delete(options.setSelect);} +if(options.hasOwnProperty('trueSize')){xscale=options.trueSize[0]/boundx;yscale=options.trueSize[1]/boundy;} +if(options.hasOwnProperty('bgColor')){if(supportsColorFade()&&options.fadeTime){$div.animate({backgroundColor:options.bgColor},{queue:false,duration:options.fadeTime});}else{$div.css('backgroundColor',options.bgColor);} +delete(options.bgColor);} +if(options.hasOwnProperty('bgOpacity')){bgopacity=options.bgOpacity;if(Selection.isAwake()){if(options.fadeTime){$img.fadeTo(options.fadeTime,bgopacity);}else{$div.css('opacity',options.opacity);}} +delete(options.bgOpacity);} +xlimit=options.maxSize[0]||0;ylimit=options.maxSize[1]||0;xmin=options.minSize[0]||0;ymin=options.minSize[1]||0;if(options.hasOwnProperty('outerImage')){$img.attr('src',options.outerImage);delete(options.outerImage);} +Selection.refresh();} +if(Touch.support){$trk.bind('touchstart',Touch.newSelection);} +$hdl_holder.hide();interfaceUpdate(true);var api={setImage:setImage,animateTo:animateTo,setSelect:setSelect,setOptions:setOptionsNew,tellSelect:tellSelect,tellScaled:tellScaled,setClass:setClass,disable:disableCrop,enable:enableCrop,cancel:cancelCrop,release:Selection.release,destroy:destroy,focus:KeyManager.watchKeys,getBounds:function(){return[boundx*xscale,boundy*yscale];},getWidgetSize:function(){return[boundx,boundy];},getScaleFactor:function(){return[xscale,yscale];},ui:{holder:$div,selection:$sel}};if($.browser.msie){$div.bind('selectstart',function(){return false;});} +$origimg.data('Jcrop',api);return api;};$.fn.Jcrop=function(options,callback) +{function attachWhenDone(from) +{var opt=(typeof(options)==='object')?options:{};var loadsrc=opt.useImg||from.src;var img=new Image();img.onload=function(){function attachJcrop(){var api=$.Jcrop(from,opt);if(typeof(callback)==='function'){callback.call(api);}} +function attachAttempt(){if(!img.width||!img.height){window.setTimeout(attachAttempt,50);}else{attachJcrop();}} +window.setTimeout(attachAttempt,50);};img.src=loadsrc;} +this.each(function(){if($(this).data('Jcrop')){if(options==='api'){return $(this).data('Jcrop');} +else{$(this).data('Jcrop').setOptions(options);}} +else{attachWhenDone(this);}});return this;};$.Jcrop.defaults={allowSelect:true,allowMove:true,allowResize:true,trackDocument:true,baseClass:'jcrop',addClass:null,bgColor:'black',bgOpacity:0.6,bgFade:false,borderOpacity:0.4,handleOpacity:0.5,handleSize:9,handleOffset:5,aspectRatio:0,keySupport:true,cornerHandles:true,sideHandles:true,drawBorders:true,dragEdges:true,fixedSupport:true,touchSupport:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onRelease:function(){}};}(jQuery));
\ No newline at end of file |