更新前端文件

This commit is contained in:
2019-07-06 16:59:35 +08:00
parent 777b452685
commit 79615defdb
1758 changed files with 315372 additions and 12014 deletions
+39
View File
@@ -0,0 +1,39 @@
{
"name": "Jcrop",
"version": "2.0.4",
"homepage": "http://jcrop.org/",
"authors": [
"Tapmodo <khallman@tapmodo.com>"
],
"description": "jQuery image cropping plugin",
"main": [
"js/Jcrop.js",
"css/Jcrop.css"
],
"keywords": [
"images",
"forms",
"cropping",
"crop",
"select",
"image",
"form"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"_release": "2.0.4",
"_resolution": {
"type": "version",
"tag": "v2.0.4",
"commit": "80f645b69fc938b3823d92d74e5019036d04a9ca"
},
"_source": "https://github.com/tapmodo/Jcrop.git",
"_target": "~2.0.4",
"_originalSource": "jcrop"
}
+129
View File
@@ -0,0 +1,129 @@
module.exports = function(grunt) {
// These are the files used in order to build the Jcrop.js source
// variable is used in initConfig concat rule below
// also used for the watch task
var jcrop_sources = [
'src/intro.js',
'src/constructor.js',
'src/static.js',
'src/stage/Abstract.js',
'src/stage/Image.js',
//'src/stage/CssTransform.js',
'src/stage/Canvas.js',
'src/filter/BackoffFilter.js',
'src/filter/ConstrainFilter.js',
'src/filter/ExtentFilter.js',
'src/filter/GridFilter.js',
'src/filter/RatioFilter.js',
'src/filter/RoundFilter.js',
'src/filter/ShadeFilter.js',
'src/component/CanvasAnimator.js',
'src/component/CropAnimator.js',
'src/component/DragState.js',
'src/component/EventManager.js',
'src/component/ImageLoader.js',
'src/component/JcropTouch.js',
'src/component/KeyWatcher.js',
'src/component/Selection.js',
'src/component/StageDrag.js',
'src/component/StageManager.js',
'src/component/Thumbnailer.js',
'src/component/DialDrag.js',
'src/defaults.js',
'src/api.js',
'src/plugin.js',
'src/modernizr.js',
'src/outro.js'
];
var json = grunt.file.readJSON('package.json');
// Project configuration
grunt.initConfig({
pkg: json,
watch: {
css: {
files: [ 'src/**/*.less' ],
tasks: [ 'css' ]
},
js: {
files: [ 'src/**/*.js' ],
tasks: [ 'js' ]
}
},
concat: {
options: {
banner: '/*! <%= pkg.name %>.js v<%= pkg.version %> - build: <%= grunt.template.today("yyyymmdd") %>\n'+
' * @copyright 2008-2015 Tapmodo Interactive LLC\n' +
' * @license Free software under MIT License\n'+
' * @website http://jcrop.org/\n'+
' **/\n'
},
dist: {
src: jcrop_sources,
dest: 'js/<%= pkg.name %>.js'
}
},
less: {
dist: {
files: {
"css/Jcrop.css": "src/css/Jcrop.less"
}
}
},
cssmin: {
dist: {
options: {
keepSpecialComments: 0,
banner: '/*! <%= pkg.name %>.min.css v<%= pkg.version %> - build: <%= grunt.template.today("yyyymmdd") %>\n'+
' * Copyright 2008-2015 Tapmodo Interactive LLC\n' +
' * Free software under MIT License\n'+
' **/\n'
},
files: {
"css/Jcrop.min.css": "css/Jcrop.css"
}
}
},
usebanner: {
dist: {
options: {
banner: '/*! <%= pkg.name %>.css v<%= pkg.version %> - build: <%= grunt.template.today("yyyymmdd") %>\n'+
' * Copyright 2008-2015 Tapmodo Interactive LLC\n' +
' * Free software under MIT License\n'+
' **/\n'
},
files: {
src: [ 'css/Jcrop.css' ]
}
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %>.min.js v<%= pkg.version %> - build: <%= grunt.template.today("yyyymmdd") %>\n' +
' * Copyright 2008-2015 Tapmodo Interactive LLC\n' +
' * Free software under MIT License\n'+
' **/\n'
},
dist: {
src: 'js/<%= pkg.name %>.js',
dest: 'js/<%= pkg.name %>.min.js'
}
}
});
// Load grunt plugins
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-banner');
// Default tasks
grunt.registerTask('default', ['js','css']);
grunt.registerTask('js', ['concat','uglify']);
grunt.registerTask('css', ['less','cssmin','usebanner']);
};
+22
View File
@@ -0,0 +1,22 @@
Copyright (c) 2011 Tapmodo Interactive LLC,
http://github.com/tapmodo/Jcrop
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.
+67
View File
@@ -0,0 +1,67 @@
Jcrop Image Cropping Plugin
===========================
Jcrop is the quick and easy way to add image cropping functionality to
your web application. It combines the ease-of-use of a typical jQuery
plugin with a powerful cross-platform DHTML cropping engine that is
faithful to familiar desktop graphics applications.
### Feature Overview
* Attaches unobtrusively to any image or block element
* Completely based on true prototypical Javascript objects for extreme flexibility
* Supports multiple active selections, per-selection customization
* Supports aspect ratio locking, minimum/maximum size, and other features
* Acts as in-line form element, can receive focus, tab through
* Keyboard support for nuding selections and trapping other keys
* Inherently API-driven and stylable with CSS
* Mobile touch support for iOS and Android
### Cross-platform Compatibility
The current version of Jcrop has been cross-platform tested and core functionality
works in all the following browsers:
* Firefox 3+
* Safari 4+
* Opera 9.5+
* Google Chrome 14+
* Internet Explorer 7+
Older versions of some browsers may also work.
Always thoroughly test any desired functionality on all target platforms and devices.
##### Legacy IE Compatibility
Internet Explorer 6 suffers some visual problems with the new CSS structure
and will not be explicitly supported from v2.x and up. Currently Jcrop can still
be used in IE6, it just looks ugly. IE7 and newer versions deliver a nearly flawless
Jcrop experience.
-------------
## MIT License
**Jcrop is free software under MIT License.**
#### Copyright (c) 2008-2015 Tapmodo Interactive LLC,<br />http://github.com/tapmodo/Jcrop
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.
+27
View File
@@ -0,0 +1,27 @@
{
"name": "Jcrop",
"version": "2.0.4",
"homepage": "http://jcrop.org/",
"authors": [
"Tapmodo <khallman@tapmodo.com>"
],
"description": "jQuery image cropping plugin",
"main": ["js/Jcrop.js", "css/Jcrop.css"],
"keywords": [
"images",
"forms",
"cropping",
"crop",
"select",
"image",
"form"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
+372
View File
@@ -0,0 +1,372 @@
/*! Jcrop.css v2.0.4 - build: 20151117
* Copyright 2008-2015 Tapmodo Interactive LLC
* Free software under MIT License
**/
/*
The outer-most container in a typical Jcrop instance
If you are having difficulty with formatting related to styles
on a parent element, place any fixes here or in a like selector
You can also style this element if you want to add a border, etc
A better method for styling can be seen below with .jcrop-light
(Add a class to the holder and style elements for that extended class)
*/
.jcrop-active {
direction: ltr;
text-align: left;
box-sizing: border-box;
/* IE10 touch compatibility */
-ms-touch-action: none;
}
.jcrop-dragging {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.jcrop-selection {
z-index: 2;
}
.jcrop-selection.jcrop-current {
z-index: 4;
}
/* Selection Borders */
.jcrop-border {
background: #ffffff url("Jcrop.gif");
line-height: 1px !important;
font-size: 0 !important;
overflow: hidden;
position: absolute;
filter: alpha(opacity=50) !important;
opacity: 0.5 !important;
}
.jcrop-border.ord-w,
.jcrop-border.ord-e,
.jcrop-border.ord-n {
top: 0px;
}
.jcrop-border.ord-n,
.jcrop-border.ord-s {
width: 100%;
height: 1px !important;
}
.jcrop-border.ord-w,
.jcrop-border.ord-e {
height: 100%;
width: 1px !important;
}
.jcrop-border.ord-e {
right: -1px;
}
.jcrop-border.ord-n {
top: -1px;
}
.jcrop-border.ord-w {
left: -1px;
}
.jcrop-border.ord-s {
bottom: -1px;
}
.jcrop-selection {
position: absolute;
}
.jcrop-box {
z-index: 2;
display: block;
background: none;
border: none;
padding: 0;
margin: 0;
font-size: 0;
}
.jcrop-box:hover {
background: none;
}
.jcrop-box:active {
background: none;
}
.jcrop-box:focus {
outline: 1px rgba(128, 128, 128, 0.65) dotted;
}
.jcrop-active,
.jcrop-box {
position: relative;
}
.jcrop-box {
width: 100%;
height: 100%;
cursor: move;
}
/* Selection Handles */
.jcrop-handle {
z-index: 4;
background-color: rgba(49, 28, 28, 0.58);
border: 1px #eeeeee solid;
width: 9px;
height: 9px;
font-size: 0;
position: absolute;
filter: alpha(opacity=80) !important;
opacity: 0.8 !important;
}
.jcrop-handle.ord-n {
left: 50%;
margin-left: -5px;
margin-top: -5px;
top: 0;
cursor: n-resize;
}
.jcrop-handle.ord-s {
bottom: 0;
left: 50%;
margin-bottom: -5px;
margin-left: -5px;
cursor: s-resize;
}
.jcrop-handle.ord-e {
margin-right: -5px;
margin-top: -5px;
right: 0;
top: 50%;
cursor: e-resize;
}
.jcrop-handle.ord-w {
left: 0;
margin-left: -5px;
margin-top: -5px;
top: 50%;
cursor: w-resize;
}
.jcrop-handle.ord-nw {
left: 0;
margin-left: -5px;
margin-top: -5px;
top: 0;
cursor: nw-resize;
}
.jcrop-handle.ord-ne {
margin-right: -5px;
margin-top: -5px;
right: 0;
top: 0;
cursor: ne-resize;
}
.jcrop-handle.ord-se {
bottom: 0;
margin-bottom: -5px;
margin-right: -5px;
right: 0;
cursor: se-resize;
}
.jcrop-handle.ord-sw {
bottom: 0;
left: 0;
margin-bottom: -5px;
margin-left: -5px;
cursor: sw-resize;
}
/* Larger Selection Handles for Touch */
.jcrop-touch .jcrop-handle {
z-index: 4;
background-color: rgba(49, 28, 28, 0.58);
border: 1px #eeeeee solid;
width: 18px;
height: 18px;
font-size: 0;
position: absolute;
filter: alpha(opacity=80) !important;
opacity: 0.8 !important;
}
.jcrop-touch .jcrop-handle.ord-n {
left: 50%;
margin-left: -10px;
margin-top: -10px;
top: 0;
cursor: n-resize;
}
.jcrop-touch .jcrop-handle.ord-s {
bottom: 0;
left: 50%;
margin-bottom: -10px;
margin-left: -10px;
cursor: s-resize;
}
.jcrop-touch .jcrop-handle.ord-e {
margin-right: -10px;
margin-top: -10px;
right: 0;
top: 50%;
cursor: e-resize;
}
.jcrop-touch .jcrop-handle.ord-w {
left: 0;
margin-left: -10px;
margin-top: -10px;
top: 50%;
cursor: w-resize;
}
.jcrop-touch .jcrop-handle.ord-nw {
left: 0;
margin-left: -10px;
margin-top: -10px;
top: 0;
cursor: nw-resize;
}
.jcrop-touch .jcrop-handle.ord-ne {
margin-right: -10px;
margin-top: -10px;
right: 0;
top: 0;
cursor: ne-resize;
}
.jcrop-touch .jcrop-handle.ord-se {
bottom: 0;
margin-bottom: -10px;
margin-right: -10px;
right: 0;
cursor: se-resize;
}
.jcrop-touch .jcrop-handle.ord-sw {
bottom: 0;
left: 0;
margin-bottom: -10px;
margin-left: -10px;
cursor: sw-resize;
}
/* Selection Dragbars */
.jcrop-dragbar {
font-size: 0;
position: absolute;
}
.jcrop-dragbar.ord-n,
.jcrop-dragbar.ord-s {
height: 9px !important;
width: 100%;
}
.jcrop-dragbar.ord-e,
.jcrop-dragbar.ord-w {
top: 0px;
height: 100%;
width: 9px !important;
}
.jcrop-dragbar.ord-n {
margin-top: -5px;
cursor: n-resize;
top: 0px;
}
.jcrop-dragbar.ord-s {
bottom: 0;
margin-bottom: -5px;
cursor: s-resize;
}
.jcrop-dragbar.ord-e {
margin-right: -5px;
right: 0;
cursor: e-resize;
}
.jcrop-dragbar.ord-w {
margin-left: -5px;
cursor: w-resize;
}
/* Shading panels */
.jcrop-shades {
position: relative;
top: 0;
left: 0;
}
.jcrop-shades div {
cursor: crosshair;
}
/* Various special states */
.jcrop-noresize .jcrop-dragbar,
.jcrop-noresize .jcrop-handle {
display: none;
}
.jcrop-selection.jcrop-nodrag .jcrop-box,
.jcrop-nodrag .jcrop-shades div {
cursor: default;
}
/* The "jcrop-light" class/extension */
.jcrop-light .jcrop-border {
background: #ffffff;
filter: alpha(opacity=70) !important;
opacity: .70!important;
}
.jcrop-light .jcrop-handle {
background-color: #000000;
border-color: #ffffff;
}
/* The "jcrop-dark" class/extension */
.jcrop-dark .jcrop-border {
background: #000000;
filter: alpha(opacity=70) !important;
opacity: 0.7 !important;
}
.jcrop-dark .jcrop-handle {
background-color: #ffffff;
border-color: #000000;
}
/* Simple macro to turn off the antlines */
.solid-line .jcrop-border {
background: #ffffff;
}
.jcrop-thumb {
position: absolute;
overflow: hidden;
z-index: 5;
}
/* Fix for twitter bootstrap et al. */
.jcrop-active img,
.jcrop-thumb img,
.jcrop-thumb canvas {
min-width: none;
min-height: none;
max-width: none;
max-height: none;
}
/* Improved multiple selection styles - in progress */
.jcrop-hl-active .jcrop-border {
filter: alpha(opacity=20) !important;
opacity: .20!important;
}
.jcrop-hl-active .jcrop-handle {
filter: alpha(opacity=10) !important;
opacity: .10!important;
}
.jcrop-hl-active .jcrop-selection:hover {
/*
.jcrop-handle {
filter:Alpha(opacity=35)!important;
opacity:.35!important;
}
*/
}
.jcrop-hl-active .jcrop-selection:hover .jcrop-border {
background-color: #ccc;
filter: alpha(opacity=50) !important;
opacity: .50!important;
}
.jcrop-hl-active .jcrop-selection.jcrop-current .jcrop-border {
background: #808080 url('Jcrop.gif');
opacity: .35!important;
filter: alpha(opacity=35) !important;
}
.jcrop-hl-active .jcrop-selection.jcrop-current .jcrop-handle {
filter: alpha(opacity=30) !important;
opacity: .30!important;
}
.jcrop-hl-active .jcrop-selection.jcrop-focus .jcrop-border {
background: url('Jcrop.gif');
opacity: .65!important;
filter: alpha(opacity=65) !important;
}
.jcrop-hl-active .jcrop-selection.jcrop-focus .jcrop-handle {
filter: alpha(opacity=60) !important;
opacity: .60!important;
}
/* Prevent background on button element */
button.jcrop-box {
background: none;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

File diff suppressed because one or more lines are too long
+100
View File
@@ -0,0 +1,100 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World | Jcrop Demos</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../js/Jcrop.js"></script>
<script type="text/javascript">
jQuery(function($){
var d = document, ge = 'getElementById';
$('#interface').on('cropmove cropend',function(e,s,c){
d[ge]('crop-x').value = c.x;
d[ge]('crop-y').value = c.y;
d[ge]('crop-w').value = c.w;
d[ge]('crop-h').value = c.h;
});
// Most basic attachment example
$('#target').Jcrop({
setSelect: [ 175, 100, 400, 300 ]
});
$('#text-inputs').on('change','input',function(e){
$('#target').Jcrop('api').animateTo([
parseInt(d[ge]('crop-x').value),
parseInt(d[ge]('crop-y').value),
parseInt(d[ge]('crop-w').value),
parseInt(d[ge]('crop-h').value)
]);
});
});
</script>
<link rel="stylesheet" href="demo_files/main.css">
<link rel="stylesheet" href="demo_files/demos.css">
<link rel="stylesheet" href="../css/Jcrop.css">
<style>
#text-inputs { margin: 10px 8px 0; }
.input-group { margin-right: 1.5em; }
.nav-box { width: 748px; padding: 0 !important; margin: 4px 0; background-color: #f8f8f7; }
</style>
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="../" class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="./basic.html">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<h1>Hello World</h1>
</div>
<div class="demo-nav menu-box">
<h3>Jcrop Demos</h3>
<ul class="links">
<li><b>Hello World</b></li>
<li><a href="thumbnail.html">Thumbnail Preview</a></li>
<li><a href="panel.html">Feature Panel</a></li>
<li><a href="coords.html">Dimensions</a></li>
<li><a href="circle.html">Circles</a></li>
</ul>
</div>
<div id="interface" class="page-interface"><img src="http://jcrop-cdn.tapmodo.com/assets/images/sierra2-750.jpg" id="target"></div>
<div class="nav-box">
<form onsubmit="return false;" id="text-inputs"><span class="input-group"><b>X</b>
<input type="text" name="cx" id="crop-x" class="span1"></span><span class="input-group"><b>Y</b>
<input type="text" name="cy" id="crop-y" class="span1"></span><span class="input-group"><b>W</b>
<input type="text" name="cw" id="crop-w" class="span1"></span><span class="input-group"><b>H</b>
<input type="text" name="ch" id="crop-h" class="span1"></span>
</form>
</div>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2013 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World | Jcrop Demos</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../js/Jcrop.js"></script>
<script type="text/javascript">
jQuery(function($){
var d = document, ge = 'getElementById';
$('#interface').on('cropmove cropend',function(e,s,c){
d[ge]('crop-x').value = c.x;
d[ge]('crop-y').value = c.y;
d[ge]('crop-w').value = c.w;
d[ge]('crop-h').value = c.h;
});
// Most basic attachment example
$('#target').Jcrop({
boxWidth: 750,
setSelect: [ 175, 100, 400, 300 ]
});
$('#text-inputs').on('change','input',function(e){
$('#target').Jcrop('api').animateTo([
parseInt(d[ge]('crop-x').value),
parseInt(d[ge]('crop-y').value),
parseInt(d[ge]('crop-w').value),
parseInt(d[ge]('crop-h').value)
]);
});
});
</script>
<link rel="stylesheet" href="demo_files/main.css">
<link rel="stylesheet" href="demo_files/demos.css">
<link rel="stylesheet" href="../css/Jcrop.css">
<style>
#text-inputs { margin: 10px 8px 0; }
.input-group { margin-right: 1.5em; }
.nav-box { width: 748px; padding: 0 !important; margin: 4px 0; background-color: #f8f8f7; }
</style>
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="../" class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="./basic.html">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<h1>Hello World</h1>
</div>
<div class="demo-nav menu-box">
<h3>Jcrop Demos</h3>
<ul class="links">
<li><b>Hello World</b></li>
<li><a href="thumbnail.html">Thumbnail Preview</a></li>
<li><a href="panel.html">Feature Panel</a></li>
<li><a href="coords.html">Dimensions</a></li>
<li><a href="circle.html">Circles</a></li>
</ul>
</div>
<div id="interface" class="page-interface"><img src="http://jcrop-cdn.tapmodo.com/assets/images/lake4-1500.jpg" id="target"></div>
<div class="nav-box">
<form onsubmit="return false;" id="text-inputs"><span class="input-group"><b>X</b>
<input type="text" name="cx" id="crop-x" class="span1"></span><span class="input-group"><b>Y</b>
<input type="text" name="cy" id="crop-y" class="span1"></span><span class="input-group"><b>W</b>
<input type="text" name="cw" id="crop-w" class="span1"></span><span class="input-group"><b>H</b>
<input type="text" name="ch" id="crop-h" class="span1"></span>
</form>
</div>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2013 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
+232
View File
@@ -0,0 +1,232 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Circles | Jcrop Demos</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../js/Jcrop.js"></script>
<script type="text/javascript">
var cb, filter;
jQuery(function($){
// Create a new Selection object extended from Selection
var CircleSel = function(){ };
// Set the custom selection's prototype object to be an instance
// of the built-in Selection object
CircleSel.prototype = new $.Jcrop.component.Selection();
// Then we can continue extending it
$.extend(CircleSel.prototype,{
zoomscale: 1,
attach: function(){
this.frame.css({
background: 'url(' + $('#target')[0].src.replace('750','750') + ')'
});
},
positionBg: function(b){
var midx = ( b.x + b.x2 ) / 2;
var midy = ( b.y + b.y2 ) / 2;
var ox = (-midx*this.zoomscale)+(b.w/2);
var oy = (-midy*this.zoomscale)+(b.h/2);
//this.frame.css({ backgroundPosition: ox+'px '+oy+'px' });
this.frame.css({ backgroundPosition: -(b.x+1)+'px '+(-b.y-1)+'px' });
},
redraw: function(b){
// Call original update() method first, with arguments
$.Jcrop.component.Selection.prototype.redraw.call(this,b);
this.positionBg(this.last);
return this;
},
prototype: $.Jcrop.component.Selection.prototype
});
// Jcrop Initialization
$('#target').Jcrop({
// Change default Selection component for new selections
selectionComponent: CircleSel,
// Use a default filter chain that omits shader
applyFilters: [ 'constrain', 'extent', 'backoff', 'ratio', 'round' ],
// Start with circles only
aspectRatio: 1,
// Set an initial selection
setSelect: [ 147, 55, 456, 390 ],
// Only n/s/e/w handles
handles: [ 'n','s','e','w' ],
// No dragbars or borders
dragbars: [ ],
borders: [ ]
},function(){
this.container.addClass('jcrop-circle-demo');
interface_load(this);
});
function interface_load(obj){
cb = obj;
// Add in a custom shading element...
cb.container.prepend($('<div />').addClass('custom-shade'));
function random_coords() {
return [
Math.random()*300,
Math.random()*200,
(Math.random()*540)+50,
(Math.random()*340)+60
];
}
// Settings Buttons
$(document.body).on('click','[data-setting]',function(e){
var $targ = $(e.target),
setting = $targ.data('setting'),
value = $targ.data('value'),
opt = {};
opt[setting] = value;
cb.setOptions(opt);
$targ.closest('.btn-group').find('.active').removeClass('active');
$targ.addClass('active');
if ((setting == 'multi') && !value) {
var m = cb.ui.multi, s = cb.ui.selection;
for(var i=0;i<m.length;i++)
if (s !== m[i]) m[i].remove();
cb.ui.multi = [ s ];
s.focus();
}
e.preventDefault();
});
// Animate button event
$(document.body).on('click','[data-action]',function(e){
var $targ = $(e.target);
var action = $targ.data('action');
switch(action){
case 'random-move':
cb.ui.selection.animateTo(random_coords());
break;
}
cb.ui.selection.refresh();
}).on('selectstart',function(e){
e.preventDefault();
}).on('click','a[data-action]',function(e){
e.preventDefault();
});
}
});
</script>
<link rel="stylesheet" href="demo_files/main.css">
<link rel="stylesheet" href="demo_files/demos.css">
<link rel="stylesheet" href="../css/Jcrop.css"><style type="text/css">.jcrop-circle-demo .jcrop-box {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
border: 1px rgba(255, 255, 255, 0.4) solid;
border-radius: 50%;
-webkit-box-shadow: 1px 1px 26px #000000;
-moz-box-shadow: 1px 1px 26px #000000;
box-shadow: 1px 1px 26px #000000;
overflow: hidden;
}
.jcrop-circle-demo .jcrop-box:focus {
outline: none;
}
.custom-shade {
position: absolute;
top: 0px;
left: 0px;
background-color: black;
opacity: 0.4;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="../" class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="./basic.html">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<h1>Circles</h1>
</div>
<div class="demo-nav menu-box">
<h3>Jcrop Demos</h3>
<ul class="links">
<li><a href="basic.html">Hello World</a></li>
<li><a href="thumbnail.html">Thumbnail Preview</a></li>
<li><a href="panel.html">Feature Panel</a></li>
<li><a href="coords.html">Dimensions</a></li>
<li><b>Circles</b></li>
</ul>
</div>
<div class="page-interface"><img src="http://jcrop-cdn.tapmodo.com/assets/images/sierra2-750.jpg" id="target">
<div class="btn-toolbar"><a href="#" data-action="random-move" id="moveselection" class="btn btn-small">Move</a><span class="btn-group"><a href="#" data-setting="aspectRatio" data-value="1" class="btn active btn-small">Circle</a><a href="#" data-setting="aspectRatio" data-value="0" class="btn btn-small">Ellipse</a></span><span class="btn-group"><a href="#" data-setting="multi" data-value="0" class="btn active btn-small">Single </a><a href="#" data-setting="multi" data-value="1" class="btn btn-small">Multi</a></span></div>
<h3>About This Demo</h3><p><strong>And you thought Jcrop could only do rectangles!</strong> Well, that&#39;s still
mostly true. This demo implements a custom <code>Selection</code> object that
uses CSS properties to create the appearance of circles and ellipses.</p>
<h4>Custom CSS and Shading</h4>
<p>By setting the CSS property <code>border-radius: 50%</code>, we can give the
selection an appearance of a circle or an ellipse. The built-in
shader filter has been disabled, and a semi-opaque <code>&lt;div&gt;</code> has been
inserted over the image to give the appearance of shading.</p>
<h4>Cropping Irregular Selections</h4>
<p>If you actually want to <em>crop</em> a circle or an ellipse, you&#39;re on
your own. Jcrop will provide the rectangular coordinates for these
crops, and further processing can be done to extract the circle
or ellipse from the image.</p>
</div>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2013 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
+173
View File
@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dimensions | Jcrop Demos</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../js/Jcrop.js"></script>
<script src="/Jcrop/js/jquery.color.js"></script>
<script type="text/javascript">
var cb, filter;
jQuery(function($){
// Create a new Selection object extended from Selection
var CoordsSel = function(){ };
// Set the custom selection's prototype object to be an instance
// of the built-in Selection object
CoordsSel.prototype = new $.Jcrop.component.Selection;
// Then we can continue extending it
$.extend(CoordsSel.prototype,{
attach: function(){
// Prepend an element to Selection.element (selection container)
this.coords = $('<div> x </div>').addClass('jcrop-coords');
this.element.prepend(this.coords);
},
redraw: function(b){
// Call original redraw() method first, with arguments
$.Jcrop.component.Selection.prototype.redraw.call(this,b);
// Update coordinates
this.coords.html(this.last.w+' &times '+this.last.h);
return this;
}
});
// Now set it as the component that is used for new selections
$('#target').Jcrop({
selectionComponent: CoordsSel,
bgColor: 'rgb(145,176,241)',
bgOpacity: 0.5
},function(){
this.container.addClass('jcrop-hl-active');
interface_load(this);
});
function interface_load(obj){
cb = obj;
cb.newSelection().update($.Jcrop.wrapFromXywh([ 147, 55, 456, 390 ])).refresh();
//cb.ui.selection.removeFilter(cb.filter.shader);
cb.ui.selection.refresh();
function random_coords() {
return [
Math.random()*300,
Math.random()*200,
(Math.random()*540)+50,
(Math.random()*340)+60
];
}
// Animate button event
$(document.body).on('click','[data-action]',function(e){
var $targ = $(e.target);
var action = $targ.data('action');
switch(action){
case 'random-move':
cb.ui.selection.animateTo(random_coords());
break;
}
cb.ui.selection.refresh();
}).on('selectstart',function(e){
e.preventDefault();
}).on('click','a[data-action]',function(e){
e.preventDefault();
});
}
$.Jcrop.component.CoordsSel = CoordsSel;
});
</script>
<link rel="stylesheet" href="demo_files/main.css">
<link rel="stylesheet" href="demo_files/demos.css">
<link rel="stylesheet" href="../css/Jcrop.css">
<style type="text/css">
.jcrop-border {
background: rgba(0,0,0,0.8);
}
.jcrop-handle {
border-color: rgba(0,0,0,0.8);
}
.jcrop-coords {
display: none;
position: absolute;
bottom: -24px;
right: 7px;
color: rgba(255, 255, 255, 0.8);
padding: 1px 4px 0;
font-size: 10px;
white-space: nowrap;
font-family: "Lucida Console", Monaco, monospace;
background: rgba(0, 0, 0, 0.8);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.jcrop-current .jcrop-coords {
display: block;
}
</style>
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="../" class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="./basic.html">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<h1>Dimensions</h1>
</div>
<div class="demo-nav menu-box">
<h3>Jcrop Demos</h3>
<ul class="links">
<li><a href="basic.html">Hello World</a></li>
<li><a href="thumbnail.html">Thumbnail Preview</a></li>
<li><a href="panel.html">Feature Panel</a></li>
<li><b>Dimensions</b></li>
<li><a href="circle.html">Circles</a></li>
</ul>
</div>
<div class="page-interface"><img src="http://jcrop-cdn.tapmodo.com/assets/images/sierra-750.jpg" id="target">
<div class="btn-toolbar"><a href="#" data-action="random-move" id="moveselection" class="btn btn-small">Move</a></div>
</div>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2013 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
+123
View File
@@ -0,0 +1,123 @@
<?php
/**
* Jcrop image cropping plugin for jQuery
* Example cropping script
* @copyright 2008-2009 Kelly Hallman
* More info: http://deepliquid.com/content/Jcrop_Implementation_Theory.html
*/
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$targ_w = $targ_h = 150;
$jpeg_quality = 90;
$src = 'demo_files/pool.jpg';
$img_r = imagecreatefromjpeg($src);
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );
imagecopyresampled($dst_r,$img_r,0,0,$_POST['x'],$_POST['y'],
$targ_w,$targ_h,$_POST['w'],$_POST['h']);
header('Content-type: image/jpeg');
imagejpeg($dst_r,null,$jpeg_quality);
exit;
}
// If not a POST request, display page below:
?><!DOCTYPE html>
<html lang="en">
<head>
<title>Live Cropping Demo</title>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<script src="../js/jquery.min.js"></script>
<script src="../js/jquery.Jcrop.js"></script>
<link rel="stylesheet" href="demo_files/main.css" type="text/css" />
<link rel="stylesheet" href="demo_files/demos.css" type="text/css" />
<link rel="stylesheet" href="../css/jquery.Jcrop.css" type="text/css" />
<script type="text/javascript">
$(function(){
$('#cropbox').Jcrop({
aspectRatio: 1,
onSelect: updateCoords
});
});
function updateCoords(c)
{
$('#x').val(c.x);
$('#y').val(c.y);
$('#w').val(c.w);
$('#h').val(c.h);
};
function checkCoords()
{
if (parseInt($('#w').val())) return true;
alert('Please select a crop region then press submit.');
return false;
};
</script>
<style type="text/css">
#target {
background-color: #ccc;
width: 500px;
height: 330px;
font-size: 24px;
display: block;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<ul class="breadcrumb first">
<li><a href="../index.html">Jcrop</a> <span class="divider">/</span></li>
<li><a href="../index.html">Demos</a> <span class="divider">/</span></li>
<li class="active">Live Demo (Requires PHP)</li>
</ul>
<h1>Server-based Cropping Behavior</h1>
</div>
<!-- This is the image we're attaching Jcrop to -->
<img src="demo_files/pool.jpg" id="cropbox" />
<!-- This is the form that our event handler fills -->
<form action="crop.php" method="post" onsubmit="return checkCoords();">
<input type="hidden" id="x" name="x" />
<input type="hidden" id="y" name="y" />
<input type="hidden" id="w" name="w" />
<input type="hidden" id="h" name="h" />
<input type="submit" value="Crop Image" class="btn btn-large btn-inverse" />
</form>
<p>
<b>An example server-side crop script.</b> Hidden form values
are set when a selection is made. If you press the <i>Crop Image</i>
button, the form will be submitted and a 150x150 thumbnail will be
dumped to the browser. Try it!
</p>
</div>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,263 @@
/* Jcrop Demo Site CSS - 2013 Tapmodo Interactive LLC - MIT License
Not required to run Jcrop - contains twitter bootstrap code */
/* To build these CSS files you must have LESS and run
* $ git submodule init
* $ git submodule update
* ...to pull in the Twitter bootstrap files
*/
.clearfix {
*zoom: 1;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
line-height: 0;
}
.clearfix:after {
clear: both;
}
.hide-text {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
.input-block-level {
display: block;
width: 100%;
min-height: 30px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* JCROP DEMOS CSS */
li small {
color: #f07878;
}
.inline-labels label {
display: inline;
}
div#interface.span3 fieldset {
margin-bottom: 1.5em;
}
div#interface.span3 fieldset legend {
margin-bottom: 2px;
padding-bottom: 2px;
line-height: 1.2;
}
.article h1 {
color: #333;
margin-top: .2em;
}
.jc-demo {
text-align: center;
}
.jcropper-holder {
border: 1px #bbb solid;
}
.jc-demo-box {
text-align: left;
margin: 3.4em auto 2em;
background: white;
border: 1px #bbb solid;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.25);
-moz-box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.25);
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.25);
padding: 1em 2em 2em;
}
form {
margin: 1.5em 0;
}
form.coords label {
margin-right: 1em;
font-weight: bold;
color: #900;
}
form.coords input {
width: 3em;
}
.ui-widget-overlay {
opacity: 0.80;
filter: alpha(opacity=70);
}
.jc-dialog {
padding-top: 1em;
}
.ui-dialog p tt {
color: yellow;
}
.jcrop-light .jcrop-selection {
-moz-box-shadow: 0px 0px 15px #999;
/* Firefox */
-webkit-box-shadow: 0px 0px 15px #999;
/* Safari, Chrome */
box-shadow: 0px 0px 15px #999;
/* CSS3 */
}
.jcrop-dark .jcrop-selection {
-moz-box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.35);
/* Firefox */
-webkit-box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.35);
/* Safari, Chrome */
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.35);
/* CSS3 */
}
.jcrop-dark .jcrop-selection:hover {
-moz-box-shadow: 0px 0px 6px #000000;
/* Firefox */
-webkit-box-shadow: 0px 0px 6px #000000;
/* Safari, Chrome */
box-shadow: 0px 0px 6px #000000;
/* CSS3 */
}
.jcrop-dark .jcrop-selection.jcrop-current {
-moz-box-shadow: 0px 0px 15px #000;
/* Firefox */
-webkit-box-shadow: 0px 0px 15px #000;
/* Safari, Chrome */
box-shadow: 0px 0px 15px #000;
/* CSS3 */
}
.jcrop-fancy .jcrop-handle.ord-e {
-webkit-border-top-left-radius: 0px;
-webkit-border-bottom-left-radius: 0px;
}
.jcrop-fancy .jcrop-handle.ord-w {
-webkit-border-top-right-radius: 0px;
-webkit-border-bottom-right-radius: 0px;
}
.jcrop-fancy .jcrop-handle.ord-nw {
-webkit-border-bottom-right-radius: 0px;
}
.jcrop-fancy .jcrop-handle.ord-ne {
-webkit-border-bottom-left-radius: 0px;
}
.jcrop-fancy .jcrop-handle.ord-sw {
-webkit-border-top-right-radius: 0px;
}
.jcrop-fancy .jcrop-handle.ord-se {
-webkit-border-top-left-radius: 0px;
}
.jcrop-fancy .jcrop-handle.ord-s {
-webkit-border-top-left-radius: 0px;
-webkit-border-top-right-radius: 0px;
}
.jcrop-fancy .jcrop-handle.ord-n {
-webkit-border-bottom-left-radius: 0px;
-webkit-border-bottom-right-radius: 0px;
}
.description {
margin: 16px 0;
}
.jcrop-droptarget canvas {
background-color: #f0f0f0;
}
div.nav-box {
border: 1px #ccc solid;
-webkit-box-shadow: inset 0px 0px 12px #cccccc;
-moz-box-shadow: inset 0px 0px 12px #cccccc;
box-shadow: inset 0px 0px 12px #cccccc;
margin-bottom: 0.5em;
padding: 0 0 1em 1em;
}
div.nav-box h3 {
line-height: 1;
color: #777;
}
ul.icons-only {
list-style: none outside;
margin: 0 0 0 0.5em;
}
ul.icons-only li i {
margin-right: 0.5em;
line-height: 22px;
}
.bolder {
font-weight: bolder;
}
.menu-box {
border: 1px #c4c4c4 solid;
border-radius: 3px;
background: white;
margin-right: -40px;
margin-left: 15px;
font-size: 11.2px;
line-height: 1.3;
padding: 4px 8px;
}
.menu-box h3 {
background: #307b93;
color: white;
padding: 4px 4px 4px 12px;
line-height: 1;
margin-left: -14px;
font-size: 16px;
position: relative;
}
.menu-box h3::after {
content: '';
border-right: #15485c 5px solid;
border-bottom: transparent 5px solid;
position: absolute;
bottom: -5px;
left: 0px;
}
.menu-box ul.links {
padding: 0;
margin: 0 3px 1em;
border-bottom: 1px #ebebeb solid;
list-style: none outside;
}
.menu-box ul.links li {
border-top: 1px #ebebeb solid;
padding: 0;
}
.menu-box.demo-nav {
float: right;
width: 135px;
}
.menu-box.main-menu {
float: right;
width: 180px;
margin-top: -95px;
}
pre {
margin: 0 0 1.2em;
}
.alert p {
margin-bottom: 0;
}
table.option-list tbody td.col1 {
color: #777;
font-weight: bolder;
}
table.option-list td.col1 {
width: 19%;
}
table.option-list td.col2 {
width: 31%;
}
table.option-list td.col3 {
width: 50%;
}
code {
border: none;
color: #555;
}
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

+62
View File
@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>All Jcrop Demos | Jcrop Demos</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../js/Jcrop.js"></script>
<script type="text/javascript">
jQuery(function($){
// Most basic attachment example
$('#target').Jcrop({});
});
</script>
<link rel="stylesheet" href="demo_files/main.css">
<link rel="stylesheet" href="demo_files/demos.css">
<link rel="stylesheet" href="../css/Jcrop.css">
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="../" class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="./basic.html">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<h1>All Jcrop Demos</h1>
</div>
<ul></ul>
<li><a href="basic.html">Hello World</a></li>
<li><a href="thumbnail.html">Thumbnail Preview</a></li>
<li><a href="panel.html">Feature Panel</a></li>
<li><a href="coords.html">Dimensions</a></li>
<li><a href="circle.html">Circles</a></li>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2013 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Non-image Cropping | Jcrop Demos</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../js/Jcrop.js"></script>
<script type="text/javascript">
jQuery(function($){
// I did JSON.stringify(jcrop_api.ui.selection.get()) on a crop I liked:
var c = {"x":186,"y":218,"x2":564,"y2":281,"w":378,"h":63};
$('#target').Jcrop({
setSelect: [c.x,c.y,c.w,c.h]
},function(){
this.animateTo([ 18, 11, 713, 170 ]);
});
});
</script>
<link rel="stylesheet" href="demo_files/main.css">
<link rel="stylesheet" href="demo_files/demos.css">
<link rel="stylesheet" href="../css/Jcrop.css">
<style>
#target {
background-color: #ccc;
width: 750px;
height: 500px;
display: block;
}
#target p {
padding: .5em 1em;
line-height: 1;
font-size: 36px;
display: block;
}
</style>
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="../" class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="./basic.html">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<h1>Non-image Cropping</h1>
</div>
<div class="demo-nav menu-box">
<h3>Jcrop Demos</h3>
<ul class="links">
<li><a href="basic.html">Hello World</a></li>
<li><a href="thumbnail.html">Thumbnail Preview</a></li>
<li><a href="panel.html">Feature Panel</a></li>
<li><a href="coords.html">Dimensions</a></li>
<li><a href="circle.html">Circles</a></li>
</ul>
</div>
<div id="target" class="jcrop-dark jcrop-hl-active"><p><strong>This is an example of attaching Jcrop to a target that is not an image.</strong>
You are now cropping over &lt;div&gt; content.</p>
</div>
<div class="description"><p><strong>Attaching Jcrop to a non-image element.</strong><br/>This is mostly useful to implement other interfaces, such as
<code>canvas</code> or over an arbitrary <code>div</code>.</p>
</div>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2013 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
+373
View File
@@ -0,0 +1,373 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Feature Panel | Jcrop Demos</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../js/Jcrop.js"></script>
<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="http://jcrop-dev.tapmodo.com/Jcrop/js/jquery.color.js"></script>
<script type="text/javascript">
var cb, filter;
jQuery(function($){
var $targ = $('#target');
var $easing = $('#easing');
$('#target').Jcrop({
animEasing: 'easeOutQuart',
bgOpacity: .35,
linked: false,
multi: true
},function(){
this.container.addClass('jcrop-dark jcrop-hl-active');
interface_load(this);
});
function interface_load(obj){
cb = obj;
cb.newSelection();
cb.setSelect([ 147, 55, 456, 390 ]);
cb.refresh();
// Hack a "special" selection...
var logosel = cb.newSelection().update($.Jcrop.wrapFromXywh([73,268,400,100]));
$.extend(logosel,{
special: true, // custom value used in our local script here
bgColor: '#999',
bgOpacity: 0.8,
canResize: false,
canDelete: false
});
logosel.element.prepend('<img src="http://tapmodo.com/img/tapmodo-official.png" style="position:absolute;background-color:white;width:100%;height:100%;" />');
logosel.aspectRatio = 400/100;
logosel.refresh();
cb.ui.multi[1].focus();
// Select an interesting easing function
$easing[0].selectedIndex = 24;
// Set up the easing function select element event
cb.opt.animEasing = $easing.change(function(e){
var $targ = $(e.target);
cb.opt.animEasing = $targ.val();
e.preventDefault();
cb.ui.selection.animateTo([Math.random()*300,Math.random()*200,(Math.random()*540)+50,(Math.random()*340)+60]);
}).val();
$('#filter-selections input').attr('checked',false);
$('#page-interface').on('startselect',function(e){
e.preventDefault();
});
/**
*
*/
cb.container.on('cropfocus cropblur cropstart cropend',function(e){
var sel = $(e.target).data('selection');
switch(e.type){
case 'cropfocus':
$('#can_size')[0].checked = sel.canResize?true:false;
$('#can_delete')[0].checked = sel.canDelete?true:false;
$('#can_drag')[0].checked = sel.canDrag?true:false;
$('#set_minsize')[0].checked = (sel.minSize[0]>8)?true:false;
$('#set_maxsize')[0].checked = (sel.maxSize[0])?true:false;
$('#set_bounds')[0].checked = (sel.edge.n)?true:false;
$('#is_linked')[0].disabled = sel.special?true:false;
$('#is_linked')[0].checked = sel.linked?true:false;
$('#shading-tools a')[0].disabled = sel.special?true:false;
$('#shading-tools a')[sel.special?'addClass':'removeClass']('disabled');
$('#ar-links').find('.active').removeClass('active');
if (sel.aspectRatio) {
if (!$('#ar-links').find('[data-value="'+sel.aspectRatio+'"]').addClass('active').length)
$('#ar-lock').addClass('active');
} else $('#ar-free').addClass('active');
}
});
$('#aspect_ratio').on('change',function(e){
var s = cb.ui.selection;
var b = s.get();
s.aspectRatio = e.target.checked? b.w/b.h : 0;
s.refresh();
});
$('#is_linked').on('change',function(e){
cb.ui.selection.linked = e.target.checked;
});
$('#selection-options').on('change','[data-filter-toggle]',function(e){
var tog = $(e.target).data('filter-toggle');
var o = { };
o[tog] = e.target.checked? true: false;
cb.setOptions(o);
});
var cycle_colors = [
'red',
'blue',
'gray',
'yellow',
'orange',
'green',
'white'
];
function random_coords() {
return [
Math.random()*300,
Math.random()*200,
(Math.random()*540)+50,
(Math.random()*340)+60
];
}
$('#can_drag,#can_size,#can_delete,#enablesel,#multisel,#anim_mode').attr('checked','checked');
$('#is_linked,#aspect_ratio').attr('checked',false);
function anim_mode(){
return document.getElementById('anim_mode').checked;
}
// A simple function to cleanup multiple spawned selections
function run_cleanup(){
var m = cb.ui.multi, s = cb.ui.selection;
for(var i=0;i<m.length;i++)
if (s !== m[i]) m[i].remove();
cb.ui.multi = [ s ];
s.center();
s.focus();
}
// Animate button event
$(document.body).on('click','[data-action]',function(e){
var $targ = $(e.target);
var action = $targ.data('action');
switch(action){
case 'set-maxsize':
cb.setOptions({ maxSize: e.target.checked? [400,350]: [0,0] });
break;
case 'set-minsize':
cb.setOptions({ minSize: e.target.checked? [60,60]: [8,8] });
break;
case 'set-bounds':
if (e.target.checked){
cb.setOptions({ edge: {
n: 15,
e: -20,
s: -40,
w: 28
}});
}
else {
cb.setOptions({ edge: {
n: 0,
e: 0,
s: 0,
w: 0
}});
}
break;
case 'set-image':
$targ.parent().find('.active').removeClass('active');
$targ.addClass('active');
$('#target').attr('src','//jcrop-cdn.tapmodo.com/assets/images/'+$targ.data('image')+'-750.jpg');
break;
case 'set-ar':
var value = $targ.data('value');
$targ.parent().find('.active').removeClass('active');
if (value == 'lock'){
var b = cb.ui.selection.get();
value = b.w / b.h;
}
$targ.addClass('active');
cb.setOptions({ aspectRatio: value });
break;
case 'set-selmode':
$targ.parent().find('.active').removeClass('active');
$targ.addClass('active');
switch($targ.data('mode')){
case 'none':
cb.container.addClass('jcrop-nodrag');
cb.setOptions({ allowSelect: false });
break;
case 'single':
cb.container.removeClass('jcrop-nodrag');
cb.setOptions({ allowSelect: true, multi: false });
break;
case 'multi':
cb.container.removeClass('jcrop-nodrag');
cb.setOptions({ allowSelect: true, multi: true });
break;
}
break;
case 'enable-selections':
cb.ui.stage.dragger.active = e.target.checked;
break;
case 'enable-multi':
cb.ui.stage.dragger.multi = e.target.checked;
break;
case 'color-cycle':
var cc = cycle_colors.shift();
cb.setOptions({ bgColor: cc });
cycle_colors.push(cc);
break;
case 'set-opacity':
$targ.parent().find('.active').removeClass('active');
$targ.addClass('active');
cb.setOptions({ bgOpacity: $targ.data('opacity'), bgColor: 'black' });
break;
case 'cleanup-all':
run_cleanup();
break;
case 'random-move':
cb[anim_mode()?'animateTo':'setSelect'](random_coords());
break;
}
}).on('keydown',function(e){
if (e.keyCode == 8) e.preventDefault();
}).on('selectstart',function(e){
e.preventDefault();
}).on('click','a[data-action]',function(e){
e.preventDefault();
});
}
});
</script>
<link rel="stylesheet" href="demo_files/main.css">
<link rel="stylesheet" href="demo_files/demos.css">
<link rel="stylesheet" href="../css/Jcrop.css">
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="../" class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="./basic.html">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<h1>Feature Panel</h1>
</div>
<div class="demo-nav menu-box">
<h3>Jcrop Demos</h3>
<ul class="links">
<li><a href="basic.html">Hello World</a></li>
<li><a href="thumbnail.html">Thumbnail Preview</a></li>
<li><b>Feature Panel</b></li>
<li><a href="coords.html">Dimensions</a></li>
<li><a href="circle.html">Circles</a></li>
</ul>
</div>
<div class="page-interface"><img src="http://jcrop-cdn.tapmodo.com/assets/images/sierra2-750.jpg" id="target">
<div class="row-fluid">
<div class="span4">
<h5>Selection Properties</h5>
<div id="selection-options">
<label class="checkbox">
<input type="checkbox" data-filter-toggle="canDrag" id="can_drag">Draggable
</label>
<label class="checkbox">
<input type="checkbox" data-filter-toggle="canResize" id="can_size">Resizable
</label>
<label class="checkbox">
<input type="checkbox" data-filter-toggle="canDelete" id="can_delete">Deletable
</label>
</div>
<label class="checkbox">
<input type="checkbox" data-action="set-bounds" id="set_bounds">Enable boundary
</label>
<label class="checkbox">
<input type="checkbox" data-action="set-minsize" id="set_minsize">Minimum Size
</label>
<label class="checkbox">
<input type="checkbox" data-action="set-maxsize" id="set_maxsize">Maximum Size
</label>
</div>
<div class="span4">
<h5>Aspect Ratio</h5>
<div class="btn-toolbar"><span id="ar-links" class="btn-group"><a href="#" data-action="set-ar" data-value="0" id="ar-free" class="btn active btn-small">Free</a><a href="#" data-action="set-ar" data-value="lock" id="ar-lock" class="btn btn-small">Lock</a><a href="#" data-action="set-ar" data-value="1.4" class="btn btn-small">Wide</a><a href="#" data-action="set-ar" data-value=".8" class="btn btn-small">Tall</a></span></div>
<h5>Shading</h5>
<div id="shading-tools" class="btn-toolbar"><a href="#" data-action="color-cycle" class="btn btn-small">Color</a><span class="btn-group"><a href="#" data-action="set-opacity" data-opacity=".35" class="btn active btn-small">Light</a><a href="#" data-action="set-opacity" data-opacity=".55" class="btn btn-small">Medium</a><a href="#" data-action="set-opacity" data-opacity=".75" class="btn btn-small">Dark</a></span></div>
<h5>Animation</h5>
<label class="checkbox">
<input type="checkbox" id="anim_mode">Enable Animation
</label>
<select data-action="update-easing" id="easing" class="select">
<option>linear</option>
<option>swing</option>
<option>easeInOutQuad</option>
<option>easeInQuad</option>
<option>easeOutQuad</option>
<option>easeInOutExpo</option>
<option>easeInExpo</option>
<option>easeOutExpo</option>
<option>easeInOutSine</option>
<option>easeInSine</option>
<option>easeOutSine</option>
<option>easeOutBounce</option>
<option>easeInOutCirc</option>
<option>easeInCirc</option>
<option>easeOutCirc</option>
<option>easeInOutCubic</option>
<option>easeInCubic</option>
<option>easeOutCubic</option>
<option>easeOutElastic</option>
<option>easeInOutBack</option>
<option>easeInBack</option>
<option>easeOutBack</option>
<option>easeInOutQuart</option>
<option>easeInQuart</option>
<option>easeOutQuart</option>
<option>easeInOutQuint</option>
<option>easeInQuint</option>
<option>easeOutQuint</option>
</select>
</div>
<div class="span4">
<h5>Current Selection</h5>
<label class="checkbox">
<input type="checkbox" data-filter-toggle="ratio" id="is_linked">Linked Selection
</label>
<div class="btn-toolbar"><a href="#" data-action="random-move" id="moveselection" class="btn btn-small">Move</a><a href="#" data-action="cleanup-all" class="btn btn-small">Cleanup</a></div>
<h5>New Selections</h5>
<div class="btn-toolbar"><span class="btn-group"><a href="#" data-action="set-selmode" data-mode="none" class="btn btn-small">None</a><a href="#" data-action="set-selmode" data-mode="single" class="btn btn-small">Single</a><a href="#" data-action="set-selmode" data-mode="multi" class="btn active btn-small">Multi</a></span></div>
<h5>Test Image</h5>
<div class="btn-toolbar"><span class="btn-group"><a href="#" data-action="set-image" data-image="sierra" class="btn btn-small">Sierra1</a><a href="#" data-action="set-image" data-image="sierra2" class="btn active btn-small">Sierra2</a><a href="#" data-action="set-image" data-image="market" class="btn btn-small">Market</a></span></div>
</div>
</div>
</div>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2013 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Thumbnail Preview | Jcrop Demos</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="../js/Jcrop.js"></script>
<script type="text/javascript">
jQuery(function($){
// Create a scope-wide variable to hold the Thumbnailer instance
var thumbnail;
// Instantiate Jcrop
$('#target').Jcrop({
aspectRatio: 1,
setSelect: [ 175, 100, 400, 300 ]
},function(){
var jcrop_api = this;
thumbnail = new $.Jcrop.component.Thumbnailer(jcrop_api,{ width: 130, height: 130 });
});
// Wire up the auto-hide checkbox/toggle
$('#autohide').attr('checked',false).on('change',function(e){
var chk = this.checked;
if (thumbnail) {
thumbnail.autoHide = chk? true: false;
thumbnail[chk?'hide':'show']();
}
});
});
</script>
<link rel="stylesheet" href="demo_files/main.css">
<link rel="stylesheet" href="demo_files/demos.css">
<link rel="stylesheet" href="../css/Jcrop.css">
<style>
.jcrop-thumb {
top: -25px;
right: 20px;
border: 1px black solid;
}
#text-inputs { margin: 10px 8px 0; }
.input-group { margin-right: 1.5em; }
.nav-box { width: 748px; padding: 0 !important; margin: 4px 0; background-color: #f8f8f7; }
</style>
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="../" class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a href="./basic.html">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<h1>Thumbnail Preview</h1>
</div>
<div class="demo-nav menu-box">
<h3>Jcrop Demos</h3>
<ul class="links">
<li><a href="basic.html">Hello World</a></li>
<li><b>Thumbnail Preview</b></li>
<li><a href="panel.html">Feature Panel</a></li>
<li><a href="coords.html">Dimensions</a></li>
<li><a href="circle.html">Circles</a></li>
</ul>
</div>
<div id="interface" class="page-interface"><img src="http://jcrop-dist.tapmodo.com/assets/images/sierra2-750.jpg" crossOrigin="anonymous" id="target">
<div style="margin-top:0.7em">
<label class="checkbox">
<input type="checkbox" id="autohide"><b>Auto-hide Thumbnail Preview</b>
</label>
</div>
</div>
<h3>Built-in Preview Support</h3><p><strong>Thumbnail previews just got much easier!</strong> Used to be, if you wanted to
include a dynamic preview with Jcrop, you had to write client code.
A number of people had difficulty adapting that code to their needs.
No more! Now just attach a Thumbnailer object. Pass in the Jcrop instance,
desired width, and height, and you&#39;re done.</p>
<h5>Invocation Code (for this demo)</h5>
<pre><code>$(&#39;#target&#39;).Jcrop({
aspectRatio: 1,
setSelect: [ 175, 100, 400, 300 ]
},function(){
var jcrop_api = this;
new $.Jcrop.component.Thumbnailer(jcrop_api,{ width: 130, height: 130 });
});</code></pre>
<p>The constructor takes a reference to the Jcrop instance, and allows
passage of various options such as initial width and height.</p>
<h5>Customize Position and Styling with CSS</h5>
<pre><code>.jcrop-thumb {
top: -25px;
right: 20px;
border: 1px black solid;
}</code></pre>
<p>The absolutely-positioned, sized thumbnail is appended to the Jcrop
instance container automatically. It can then be positioned relatively
to the container by using top/left/bottom/right CSS values. Styling
such as a border or a box shadow can be added if desired.</p>
<h3>Additional Features</h3>
<ul><li>Can be locked to an individual Selection object.</li><li>Can be resized using <code>resize(w,h)</code> method.</li></ul>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2013 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
+122
View File
@@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Jcrop v2.0.0-RC1 | Jcrop Jcrop</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<link rel="stylesheet" href="demos/demo_files/main.css">
<link rel="stylesheet" href="demos/demo_files/demos.css">
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<button type="button" data-toggle="collapse" data-target="nav-collapse" class="btn btn-navbar"><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="brand">Jcrop</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li><a href="demos/">Demos</a>
</li>
<li><a href="http://beta.jcrop.org/doc/">Docs</a>
</li>
<li><a href="http://beta.jcrop.org/contact/">Contact</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="span12">
<div class="jc-demo-box">
<div class="page-header">
<ul class="breadcrumb first">
<li><a href="http://jcrop.org/">Jcrop.org</a><span class="divider">/</span></li>
<li class="active">Jcrop v2.0.0-RC1</li>
</ul>
<h1>Jcrop v2.0.0-RC1</h1>
</div>
<div class="main-menu menu-box">
<h3>Jcrop Demos</h3>
<ul class="links">
<li><a href="demos/basic.html">Hello World</a></li>
<li><a href="demos/thumbnail.html">Thumbnail Preview</a></li>
<li><a href="demos/panel.html">Feature Panel</a></li>
<li><a href="demos/coords.html">Dimensions</a></li>
<li><a href="demos/circle.html">Circles</a></li>
</ul>
</div>
<p><b>Build Date:</b> Sun Sep 08 2013 02:56:09 GMT+0000 (UTC)</p><h3>What&#39;s Included</h3>
<p>The this archive contains the latest version of <strong>Jcrop</strong>,
comprised of the following:</p>
<ul><li>Latest version of <a href="js/Jcrop.js"><strong>Jcrop.js</strong></a> and <a href="css/Jcrop.css"><strong>Jcrop.css</strong></a>, the primary requisite files</li><li>Minimized versions of both of the above (<a href="js/Jcrop.min.js">Jcrop.min.js</a>, <a href="css/Jcrop.min.css">Jcrop.min.css</a>)</li><li>Several demos are also included, see links in menu at right</li></ul>
<hr><h1>Jcrop Image Cropping Plugin</h1>
<p>Jcrop is the quick and easy way to add image cropping functionality to
your web application. It combines the ease-of-use of a typical jQuery
plugin with a powerful cross-platform DHTML cropping engine that is
faithful to familiar desktop graphics applications.</p>
<h3>Feature Overview</h3>
<ul><li>Attaches unobtrusively to any image or block element</li><li>Completely based on true prototypical Javascript objects for extreme flexibility</li><li>Supports multiple active selections, per-selection customization</li><li>Supports aspect ratio locking, minimum/maximum size, and other features</li><li>Acts as in-line form element, can receive focus, tab through</li><li>Keyboard support for nuding selections and trapping other keys</li><li>Inherently API-driven and stylable with CSS</li><li>Mobile touch support for iOS and Android</li></ul>
<h3>Cross-platform Compatibility</h3>
<p>The current version of Jcrop has been cross-platform tested and core functionality
works in all the following browsers:</p>
<ul><li>Firefox 3+</li><li>Safari 4+</li><li>Opera 9.5+</li><li>Google Chrome 14+</li><li>Internet Explorer 7+</li></ul>
<p>Older versions of some browsers may also work.</p>
<p>Always thoroughly test any desired functionality on all target platforms and devices.</p>
<h5>Legacy IE Compatibility</h5>
<p>Internet Explorer 6 suffers some visual problems with the new CSS structure
and will not be explicitly supported from v2.x and up. Currently Jcrop can still
be used in IE6, it just looks ugly. IE7 and newer versions deliver a nearly flawless
Jcrop experience.</p>
<hr/>
<h2>MIT License</h2>
<p><strong>Jcrop is free software under MIT License.</strong></p>
<h4>Copyright (c) 2008-2015 Tapmodo Interactive LLC</h4>
<h5><a href="http://github.com/tapmodo/Jcrop">http://github.com/tapmodo/Jcrop</a></h5>
<p>Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
&quot;Software&quot;), 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:</p>
<p>The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.</p>
<p>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, 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.</p>
<div class="tapmodo-footer"><a href="http://tapmodo.com" class="tapmodo-logo segment">tapmodo.com</a>
<div class="segment"><b>&copy; 2008-2015 Tapmodo Interactive LLC</b>
<div>Jcrop is free software released under <a href="../MIT-LICENSE.txt">MIT License</a></div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+661
View File
@@ -0,0 +1,661 @@
/*!
* jQuery Color Animations v2.0pre
* http://jquery.org/
*
* Copyright 2011 John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
(function( jQuery, undefined ){
var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color outlineColor".split(" "),
// plusequals test for += 100 -= 100
rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
// a set of RE's that can match strings and generate color tuples.
stringParsers = [{
re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
parse: function( execResult ) {
return [
execResult[ 1 ],
execResult[ 2 ],
execResult[ 3 ],
execResult[ 4 ]
];
}
}, {
re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
parse: function( execResult ) {
return [
2.55 * execResult[1],
2.55 * execResult[2],
2.55 * execResult[3],
execResult[ 4 ]
];
}
}, {
re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
parse: function( execResult ) {
return [
parseInt( execResult[ 1 ], 16 ),
parseInt( execResult[ 2 ], 16 ),
parseInt( execResult[ 3 ], 16 )
];
}
}, {
re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
parse: function( execResult ) {
return [
parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
];
}
}, {
re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
space: "hsla",
parse: function( execResult ) {
return [
execResult[1],
execResult[2] / 100,
execResult[3] / 100,
execResult[4]
];
}
}],
// jQuery.Color( )
color = jQuery.Color = function( color, green, blue, alpha ) {
return new jQuery.Color.fn.parse( color, green, blue, alpha );
},
spaces = {
rgba: {
cache: "_rgba",
props: {
red: {
idx: 0,
type: "byte",
empty: true
},
green: {
idx: 1,
type: "byte",
empty: true
},
blue: {
idx: 2,
type: "byte",
empty: true
},
alpha: {
idx: 3,
type: "percent",
def: 1
}
}
},
hsla: {
cache: "_hsla",
props: {
hue: {
idx: 0,
type: "degrees",
empty: true
},
saturation: {
idx: 1,
type: "percent",
empty: true
},
lightness: {
idx: 2,
type: "percent",
empty: true
}
}
}
},
propTypes = {
"byte": {
floor: true,
min: 0,
max: 255
},
"percent": {
min: 0,
max: 1
},
"degrees": {
mod: 360,
floor: true
}
},
rgbaspace = spaces.rgba.props,
support = color.support = {},
// colors = jQuery.Color.names
colors,
// local aliases of functions called often
each = jQuery.each;
spaces.hsla.props.alpha = rgbaspace.alpha;
function clamp( value, prop, alwaysAllowEmpty ) {
var type = propTypes[ prop.type ] || {},
allowEmpty = prop.empty || alwaysAllowEmpty;
if ( allowEmpty && value == null ) {
return null;
}
if ( prop.def && value == null ) {
return prop.def;
}
if ( type.floor ) {
value = ~~value;
} else {
value = parseFloat( value );
}
if ( value == null || isNaN( value ) ) {
return prop.def;
}
if ( type.mod ) {
value = value % type.mod;
// -10 -> 350
return value < 0 ? type.mod + value : value;
}
// for now all property types without mod have min and max
return type.min > value ? type.min : type.max < value ? type.max : value;
}
function stringParse( string ) {
var inst = color(),
rgba = inst._rgba = [];
string = string.toLowerCase();
each( stringParsers, function( i, parser ) {
var match = parser.re.exec( string ),
values = match && parser.parse( match ),
parsed,
spaceName = parser.space || "rgba",
cache = spaces[ spaceName ].cache;
if ( values ) {
parsed = inst[ spaceName ]( values );
// if this was an rgba parse the assignment might happen twice
// oh well....
inst[ cache ] = parsed[ cache ];
rgba = inst._rgba = parsed._rgba;
// exit each( stringParsers ) here because we matched
return false;
}
});
// Found a stringParser that handled it
if ( rgba.length !== 0 ) {
// if this came from a parsed string, force "transparent" when alpha is 0
// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
if ( Math.max.apply( Math, rgba ) === 0 ) {
jQuery.extend( rgba, colors.transparent );
}
return inst;
}
// named colors / default - filter back through parse function
if ( string = colors[ string ] ) {
return string;
}
}
color.fn = color.prototype = {
constructor: color,
parse: function( red, green, blue, alpha ) {
if ( red === undefined ) {
this._rgba = [ null, null, null, null ];
return this;
}
if ( red instanceof jQuery || red.nodeType ) {
red = red instanceof jQuery ? red.css( green ) : jQuery( red ).css( green );
green = undefined;
}
var inst = this,
type = jQuery.type( red ),
rgba = this._rgba = [],
source;
// more than 1 argument specified - assume ( red, green, blue, alpha )
if ( green !== undefined ) {
red = [ red, green, blue, alpha ];
type = "array";
}
if ( type === "string" ) {
return this.parse( stringParse( red ) || colors._default );
}
if ( type === "array" ) {
each( rgbaspace, function( key, prop ) {
rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
});
return this;
}
if ( type === "object" ) {
if ( red instanceof color ) {
each( spaces, function( spaceName, space ) {
if ( red[ space.cache ] ) {
inst[ space.cache ] = red[ space.cache ].slice();
}
});
} else {
each( spaces, function( spaceName, space ) {
each( space.props, function( key, prop ) {
var cache = space.cache;
// if the cache doesn't exist, and we know how to convert
if ( !inst[ cache ] && space.to ) {
// if the value was null, we don't need to copy it
// if the key was alpha, we don't need to copy it either
if ( red[ key ] == null || key === "alpha") {
return;
}
inst[ cache ] = space.to( inst._rgba );
}
// this is the only case where we allow nulls for ALL properties.
// call clamp with alwaysAllowEmpty
inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
});
});
}
return this;
}
},
is: function( compare ) {
var is = color( compare ),
same = true,
myself = this;
each( spaces, function( _, space ) {
var isCache = is[ space.cache ],
localCache;
if (isCache) {
localCache = myself[ space.cache ] || space.to && space.to( myself._rgba ) || [];
each( space.props, function( _, prop ) {
if ( isCache[ prop.idx ] != null ) {
same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
return same;
}
});
}
return same;
});
return same;
},
_space: function() {
var used = [],
inst = this;
each( spaces, function( spaceName, space ) {
if ( inst[ space.cache ] ) {
used.push( spaceName );
}
});
return used.pop();
},
transition: function( other, distance ) {
var end = color( other ),
spaceName = end._space(),
space = spaces[ spaceName ],
start = this[ space.cache ] || space.to( this._rgba ),
result = start.slice();
end = end[ space.cache ];
each( space.props, function( key, prop ) {
var index = prop.idx,
startValue = start[ index ],
endValue = end[ index ],
type = propTypes[ prop.type ] || {};
// if null, don't override start value
if ( endValue === null ) {
return;
}
// if null - use end
if ( startValue === null ) {
result[ index ] = endValue;
} else {
if ( type.mod ) {
if ( endValue - startValue > type.mod / 2 ) {
startValue += type.mod;
} else if ( startValue - endValue > type.mod / 2 ) {
startValue -= type.mod;
}
}
result[ prop.idx ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
}
});
return this[ spaceName ]( result );
},
blend: function( opaque ) {
// if we are already opaque - return ourself
if ( this._rgba[ 3 ] === 1 ) {
return this;
}
var rgb = this._rgba.slice(),
a = rgb.pop(),
blend = color( opaque )._rgba;
return color( jQuery.map( rgb, function( v, i ) {
return ( 1 - a ) * blend[ i ] + a * v;
}));
},
toRgbaString: function() {
var prefix = "rgba(",
rgba = jQuery.map( this._rgba, function( v, i ) {
return v == null ? ( i > 2 ? 1 : 0 ) : v;
});
if ( rgba[ 3 ] === 1 ) {
rgba.pop();
prefix = "rgb(";
}
return prefix + rgba.join(",") + ")";
},
toHslaString: function() {
var prefix = "hsla(",
hsla = jQuery.map( this.hsla(), function( v, i ) {
if ( v == null ) {
v = i > 2 ? 1 : 0;
}
// catch 1 and 2
if ( i && i < 3 ) {
v = Math.round( v * 100 ) + "%";
}
return v;
});
if ( hsla[ 3 ] === 1 ) {
hsla.pop();
prefix = "hsl(";
}
return prefix + hsla.join(",") + ")";
},
toHexString: function( includeAlpha ) {
var rgba = this._rgba.slice(),
alpha = rgba.pop();
if ( includeAlpha ) {
rgba.push( ~~( alpha * 255 ) );
}
return "#" + jQuery.map( rgba, function( v, i ) {
// default to 0 when nulls exist
v = ( v || 0 ).toString( 16 );
return v.length === 1 ? "0" + v : v;
}).join("");
},
toString: function() {
return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
}
};
color.fn.parse.prototype = color.fn;
// hsla conversions adapted from:
// http://www.google.com/codesearch/p#OAMlx_jo-ck/src/third_party/WebKit/Source/WebCore/inspector/front-end/Color.js&d=7&l=193
function hue2rgb( p, q, h ) {
h = ( h + 1 ) % 1;
if ( h * 6 < 1 ) {
return p + (q - p) * 6 * h;
}
if ( h * 2 < 1) {
return q;
}
if ( h * 3 < 2 ) {
return p + (q - p) * ((2/3) - h) * 6;
}
return p;
}
spaces.hsla.to = function ( rgba ) {
if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
return [ null, null, null, rgba[ 3 ] ];
}
var r = rgba[ 0 ] / 255,
g = rgba[ 1 ] / 255,
b = rgba[ 2 ] / 255,
a = rgba[ 3 ],
max = Math.max( r, g, b ),
min = Math.min( r, g, b ),
diff = max - min,
add = max + min,
l = add * 0.5,
h, s;
if ( min === max ) {
h = 0;
} else if ( r === max ) {
h = ( 60 * ( g - b ) / diff ) + 360;
} else if ( g === max ) {
h = ( 60 * ( b - r ) / diff ) + 120;
} else {
h = ( 60 * ( r - g ) / diff ) + 240;
}
if ( l === 0 || l === 1 ) {
s = l;
} else if ( l <= 0.5 ) {
s = diff / add;
} else {
s = diff / ( 2 - add );
}
return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
};
spaces.hsla.from = function ( hsla ) {
if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
return [ null, null, null, hsla[ 3 ] ];
}
var h = hsla[ 0 ] / 360,
s = hsla[ 1 ],
l = hsla[ 2 ],
a = hsla[ 3 ],
q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
p = 2 * l - q,
r, g, b;
return [
Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
Math.round( hue2rgb( p, q, h ) * 255 ),
Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
a
];
};
each( spaces, function( spaceName, space ) {
var props = space.props,
cache = space.cache,
to = space.to,
from = space.from;
// makes rgba() and hsla()
color.fn[ spaceName ] = function( value ) {
// generate a cache for this space if it doesn't exist
if ( to && !this[ cache ] ) {
this[ cache ] = to( this._rgba );
}
if ( value === undefined ) {
return this[ cache ].slice();
}
var type = jQuery.type( value ),
arr = ( type === "array" || type === "object" ) ? value : arguments,
local = this[ cache ].slice(),
ret;
each( props, function( key, prop ) {
var val = arr[ type === "object" ? key : prop.idx ];
if ( val == null ) {
val = local[ prop.idx ];
}
local[ prop.idx ] = clamp( val, prop );
});
if ( from ) {
ret = color( from( local ) );
ret[ cache ] = local;
return ret;
} else {
return color( local );
}
};
// makes red() green() blue() alpha() hue() saturation() lightness()
each( props, function( key, prop ) {
// alpha is included in more than one space
if ( color.fn[ key ] ) {
return;
}
color.fn[ key ] = function( value ) {
var vtype = jQuery.type( value ),
fn = ( key === 'alpha' ? ( this._hsla ? 'hsla' : 'rgba' ) : spaceName ),
local = this[ fn ](),
cur = local[ prop.idx ],
match;
if ( vtype === "undefined" ) {
return cur;
}
if ( vtype === "function" ) {
value = value.call( this, cur );
vtype = jQuery.type( value );
}
if ( value == null && prop.empty ) {
return this;
}
if ( vtype === "string" ) {
match = rplusequals.exec( value );
if ( match ) {
value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
}
}
local[ prop.idx ] = value;
return this[ fn ]( local );
};
});
});
// add .fx.step functions
each( stepHooks, function( i, hook ) {
jQuery.cssHooks[ hook ] = {
set: function( elem, value ) {
var parsed, backgroundColor, curElem;
if ( jQuery.type( value ) !== 'string' || ( parsed = stringParse( value ) ) )
{
value = color( parsed || value );
if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
curElem = hook === "backgroundColor" ? elem.parentNode : elem;
do {
backgroundColor = jQuery.curCSS( curElem, "backgroundColor" );
} while (
( backgroundColor === "" || backgroundColor === "transparent" ) &&
( curElem = curElem.parentNode ) &&
curElem.style
);
value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
backgroundColor :
"_default" );
}
value = value.toRgbaString();
}
elem.style[ hook ] = value;
}
};
jQuery.fx.step[ hook ] = function( fx ) {
if ( !fx.colorInit ) {
fx.start = color( fx.elem, hook );
fx.end = color( fx.end );
fx.colorInit = true;
}
jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
};
});
// detect rgba support
jQuery(function() {
var div = document.createElement( "div" ),
div_style = div.style;
div_style.cssText = "background-color:rgba(1,1,1,.5)";
support.rgba = div_style.backgroundColor.indexOf( "rgba" ) > -1;
});
// Some named colors to work with
// From Interface by Stefan Petre
// http://interface.eyecon.ro/
colors = jQuery.Color.names = {
aqua: "#00ffff",
azure: "#f0ffff",
beige: "#f5f5dc",
black: "#000000",
blue: "#0000ff",
brown: "#a52a2a",
cyan: "#00ffff",
darkblue: "#00008b",
darkcyan: "#008b8b",
darkgrey: "#a9a9a9",
darkgreen: "#006400",
darkkhaki: "#bdb76b",
darkmagenta: "#8b008b",
darkolivegreen: "#556b2f",
darkorange: "#ff8c00",
darkorchid: "#9932cc",
darkred: "#8b0000",
darksalmon: "#e9967a",
darkviolet: "#9400d3",
fuchsia: "#ff00ff",
gold: "#ffd700",
green: "#008000",
indigo: "#4b0082",
khaki: "#f0e68c",
lightblue: "#add8e6",
lightcyan: "#e0ffff",
lightgreen: "#90ee90",
lightgrey: "#d3d3d3",
lightpink: "#ffb6c1",
lightyellow: "#ffffe0",
lime: "#00ff00",
magenta: "#ff00ff",
maroon: "#800000",
navy: "#000080",
olive: "#808000",
orange: "#ffa500",
pink: "#ffc0cb",
purple: "#800080",
violet: "#800080",
red: "#ff0000",
silver: "#c0c0c0",
white: "#ffffff",
yellow: "#ffff00",
transparent: [ null, null, null, 0 ],
_default: "#ffffff"
};
})( jQuery );
File diff suppressed because one or more lines are too long
+13
View File
@@ -0,0 +1,13 @@
{
"name": "Jcrop",
"version": "2.0.4",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-banner": "^0.1.4",
"grunt-contrib-concat": "^0.3.0",
"grunt-contrib-cssmin": "^0.6.2",
"grunt-contrib-less": "^0.7.0",
"grunt-contrib-uglify": "^0.2.7",
"grunt-contrib-watch": "^0.5.3"
}
}
+19
View File
@@ -0,0 +1,19 @@
## Javascript source files
The files in this path are Javascript fragments that are compiled together
to create the Jcrop.js source file. Also includes LESS CSS source files.
##### Building with Grunt
$ npm install
$ grunt
##### Grunt watch
The Grunt configuration also includes a watch task using grunt-watch.
Using `watch` (in a different terminal) will allow you to modify files
and have them automatically recompile when changes are detected.
$ grunt watch
Read the [grunt documentation](http://gruntjs.com) for more info.
+352
View File
@@ -0,0 +1,352 @@
// Jcrop API methods
$.extend(Jcrop.prototype,{
//init: function(){{{
init: function(){
this.event = new this.opt.eventManagerComponent(this);
this.ui.keyboard = new this.opt.keyboardComponent(this);
this.ui.manager = new this.opt.stagemanagerComponent(this);
this.applyFilters();
if ($.Jcrop.supportsTouch)
new $.Jcrop.component.Touch(this);
this.initEvents();
},
//}}}
// applySizeConstraints: function(){{{
applySizeConstraints: function(){
var o = this.opt,
img = this.opt.imgsrc;
if (img){
var iw = img.naturalWidth || img.width,
ih = img.naturalHeight || img.height,
bw = o.boxWidth || iw,
bh = o.boxHeight || ih;
if (img && ((iw > bw) || (ih > bh))){
var bx = Jcrop.getLargestBox(iw/ih,bw,bh);
$(img).width(bx[0]).height(bx[1]);
this.resizeContainer(bx[0],bx[1]);
this.opt.xscale = iw / bx[0];
this.opt.yscale = ih / bx[1];
}
}
if (this.opt.trueSize){
var dw = this.opt.trueSize[0];
var dh = this.opt.trueSize[1];
var cs = this.getContainerSize();
this.opt.xscale = dw / cs[0];
this.opt.yscale = dh / cs[1];
}
},
// }}}
initComponent: function(name){
if (Jcrop.component[name]) {
var args = Array.prototype.slice.call(arguments);
var obj = new Jcrop.component[name];
args.shift();
args.unshift(this);
obj.init.apply(obj,args);
return obj;
}
},
// setOptions: function(opt){{{
setOptions: function(opt,proptype){
if (!$.isPlainObject(opt)) opt = {};
$.extend(this.opt,opt);
// Handle a setSelect value
if (this.opt.setSelect) {
// If there is no current selection
// passing setSelect will create one
if (!this.ui.multi.length)
this.newSelection();
// Use these values to update the current selection
this.setSelect(this.opt.setSelect);
// Set to null so it doesn't get called again
this.opt.setSelect = null;
}
this.event.trigger('configupdate');
return this;
},
// }}}
//destroy: function(){{{
destroy: function(){
if (this.opt.imgsrc) {
this.container.before(this.opt.imgsrc);
this.container.remove();
$(this.opt.imgsrc).removeData('Jcrop').show();
} else {
// @todo: more elegant destroy() process for non-image containers
this.container.remove();
}
},
// }}}
// applyFilters: function(){{{
applyFilters: function(){
var obj;
for(var i=0,f=this.opt.applyFilters,l=f.length; i<l; i++){
if ($.Jcrop.filter[f[i]])
obj = new $.Jcrop.filter[f[i]];
obj.core = this;
if (obj.init) obj.init();
this.filter[f[i]] = obj;
}
},
// }}}
// getDefaultFilters: function(){{{
getDefaultFilters: function(){
var rv = [];
for(var i=0,f=this.opt.applyFilters,l=f.length; i<l; i++)
if(this.filter.hasOwnProperty(f[i]))
rv.push(this.filter[f[i]]);
rv.sort(function(x,y){ return x.priority - y.priority; });
return rv;
},
// }}}
// setSelection: function(sel){{{
setSelection: function(sel){
var m = this.ui.multi;
var n = [];
for(var i=0;i<m.length;i++) {
if (m[i] !== sel) n.push(m[i]);
m[i].toBack();
}
n.unshift(sel);
this.ui.multi = n;
this.ui.selection = sel;
sel.toFront();
return sel;
},
// }}}
// getSelection: function(raw){{{
getSelection: function(raw){
var b = this.ui.selection.get();
return b;
},
// }}}
// newSelection: function(){{{
newSelection: function(sel){
if (!sel)
sel = new this.opt.selectionComponent();
sel.init(this);
this.setSelection(sel);
return sel;
},
// }}}
// hasSelection: function(sel){{{
hasSelection: function(sel){
for(var i=0;i<this.ui.multi;i++)
if (sel === this.ui.multi[i]) return true;
},
// }}}
// removeSelection: function(sel){{{
removeSelection: function(sel){
var i, n = [], m = this.ui.multi;
for(var i=0;i<m.length;i++){
if (sel !== m[i])
n.push(m[i]);
else m[i].remove();
}
return this.ui.multi = n;
},
// }}}
//addFilter: function(filter){{{
addFilter: function(filter){
for(var i=0,m=this.ui.multi,l=m.length; i<l; i++)
m[i].addFilter(filter);
return this;
},
//}}}
// removeFiltersByTag: function(tag){{{
removeFilter: function(filter){
for(var i=0,m=this.ui.multi,l=m.length; i<l; i++)
m[i].removeFilter(filter);
return this;
},
// }}}
// blur: function(){{{
blur: function(){
this.ui.selection.blur();
return this;
},
// }}}
// focus: function(){{{
focus: function(){
this.ui.selection.focus();
return this;
},
// }}}
//initEvents: function(){{{
initEvents: function(){
var t = this;
t.container.on('selectstart',function(e){ return false; })
.on('mousedown','.'+t.opt.css_drag,t.startDrag());
},
//}}}
// maxSelect: function(){{{
maxSelect: function(){
this.setSelect([0,0,this.elw,this.elh]);
},
// }}}
// nudge: function(x,y){{{
nudge: function(x,y){
var s = this.ui.selection, b = s.get();
b.x += x;
b.x2 += x;
b.y += y;
b.y2 += y;
if (b.x < 0) { b.x2 = b.w; b.x = 0; }
else if (b.x2 > this.elw) { b.x2 = this.elw; b.x = b.x2 - b.w; }
if (b.y < 0) { b.y2 = b.h; b.y = 0; }
else if (b.y2 > this.elh) { b.y2 = this.elh; b.y = b.y2 - b.h; }
s.element.trigger('cropstart',[s,this.unscale(b)]);
s.updateRaw(b,'move');
s.element.trigger('cropend',[s,this.unscale(b)]);
},
// }}}
// refresh: function(){{{
refresh: function(){
for(var i=0,s=this.ui.multi,l=s.length;i<l;i++)
s[i].refresh();
},
// }}}
// blurAll: function(){{{
blurAll: function(){
var m = this.ui.multi;
for(var i=0;i<m.length;i++) {
if (m[i] !== sel) n.push(m[i]);
m[i].toBack();
}
},
// }}}
// scale: function(b){{{
scale: function(b){
var xs = this.opt.xscale,
ys = this.opt.yscale;
return {
x: b.x / xs,
y: b.y / ys,
x2: b.x2 / xs,
y2: b.y2 / ys,
w: b.w / xs,
h: b.h / ys
};
},
// }}}
// unscale: function(b){{{
unscale: function(b){
var xs = this.opt.xscale,
ys = this.opt.yscale;
return {
x: b.x * xs,
y: b.y * ys,
x2: b.x2 * xs,
y2: b.y2 * ys,
w: b.w * xs,
h: b.h * ys
};
},
// }}}
// requestDelete: function(){{{
requestDelete: function(){
if ((this.ui.multi.length > 1) && (this.ui.selection.canDelete))
return this.deleteSelection();
},
// }}}
// deleteSelection: function(){{{
deleteSelection: function(){
if (this.ui.selection) {
this.removeSelection(this.ui.selection);
if (this.ui.multi.length) this.ui.multi[0].focus();
this.ui.selection.refresh();
}
},
// }}}
// animateTo: function(box){{{
animateTo: function(box){
if (this.ui.selection)
this.ui.selection.animateTo(box);
return this;
},
// }}}
// setselect: function(box){{{
setSelect: function(box){
if (this.ui.selection)
this.ui.selection.update(Jcrop.wrapFromXywh(box));
return this;
},
// }}}
//startDrag: function(){{{
startDrag: function(){
var t = this;
return function(e){
var $targ = $(e.target);
var selection = $targ.closest('.'+t.opt.css_selection).data('selection');
var ord = $targ.data('ord');
t.container.trigger('cropstart',[selection,t.unscale(selection.get())]);
selection.startDrag(e,ord);
return false;
};
},
//}}}
// getContainerSize: function(){{{
getContainerSize: function(){
return [ this.container.width(), this.container.height() ];
},
// }}}
// resizeContainer: function(w,h){{{
resizeContainer: function(w,h){
this.container.width(w).height(h);
this.refresh();
},
// }}}
// setImage: function(src,cb){{{
setImage: function(src,cb){
var t = this, targ = t.opt.imgsrc;
if (!targ) return false;
new $.Jcrop.component.ImageLoader(src,null,function(w,h){
t.resizeContainer(w,h);
targ.src = src;
$(targ).width(w).height(h);
t.applySizeConstraints();
t.refresh();
t.container.trigger('cropimage',[t,targ]);
if (typeof cb == 'function')
cb.call(t,w,h);
});
},
// }}}
// update: function(b){{{
update: function(b){
if (this.ui.selection)
this.ui.selection.update(b);
}
// }}}
});
@@ -0,0 +1,75 @@
/**
* CanvasAnimator
* manages smooth cropping animation
*
* This object is called internally to manage animation.
* An in-memory div is animated and a progress callback
* is used to update the selection coordinates of the
* visible selection in realtime.
*/
var CanvasAnimator = function(stage){
this.stage = stage;
this.core = stage.core;
this.cloneStagePosition();
};
CanvasAnimator.prototype = {
cloneStagePosition: function(){
var s = this.stage;
this.angle = s.angle;
this.scale = s.scale;
this.offset = s.offset;
},
getElement: function(){
var s = this.stage;
return $('<div />')
.css({
position: 'absolute',
top: s.offset[0]+'px',
left: s.offset[1]+'px',
width: s.angle+'px',
height: s.scale+'px'
});
},
animate: function(cb){
var t = this;
this.scale = this.stage.boundScale(this.scale);
t.stage.triggerEvent('croprotstart');
t.getElement().animate({
top: t.offset[0]+'px',
left: t.offset[1]+'px',
width: t.angle+'px',
height: t.scale+'px'
},{
easing: t.core.opt.animEasing,
duration: t.core.opt.animDuration,
complete: function(){
t.stage.triggerEvent('croprotend');
(typeof cb == 'function') && cb.call(this);
},
progress: function(anim){
var props = {}, i, tw = anim.tweens;
for(i=0;i<tw.length;i++){
props[tw[i].prop] = tw[i].now; }
t.stage.setAngle(props.width)
.setScale(props.height)
.setOffset(props.top,props.left)
.redraw();
}
});
}
};
Jcrop.stage.Canvas.prototype.getAnimator = function(){
return new CanvasAnimator(this);
};
Jcrop.registerComponent('CanvasAnimator',CanvasAnimator);
@@ -0,0 +1,72 @@
/**
* CropAnimator
* manages smooth cropping animation
*
* This object is called internally to manage animation.
* An in-memory div is animated and a progress callback
* is used to update the selection coordinates of the
* visible selection in realtime.
*/
// var CropAnimator = function(selection){{{
var CropAnimator = function(selection){
this.selection = selection;
this.core = selection.core;
};
// }}}
CropAnimator.prototype = {
getElement: function(){
var b = this.selection.get();
return $('<div />')
.css({
position: 'absolute',
top: b.y+'px',
left: b.x+'px',
width: b.w+'px',
height: b.h+'px'
});
},
animate: function(x,y,w,h,cb){
var t = this;
t.selection.allowResize(false);
t.getElement().animate({
top: y+'px',
left: x+'px',
width: w+'px',
height: h+'px'
},{
easing: t.core.opt.animEasing,
duration: t.core.opt.animDuration,
complete: function(){
t.selection.allowResize(true);
cb && cb.call(this);
},
progress: function(anim){
var props = {}, i, tw = anim.tweens;
for(i=0;i<tw.length;i++){
props[tw[i].prop] = tw[i].now; }
var b = {
x: parseInt(props.left),
y: parseInt(props.top),
w: parseInt(props.width),
h: parseInt(props.height)
};
b.x2 = b.x + b.w;
b.y2 = b.y + b.h;
t.selection.updateRaw(b,'se');
}
});
}
};
Jcrop.registerComponent('Animator',CropAnimator);
@@ -0,0 +1,90 @@
/**
* DialDrag component
* This is a little hacky, it was adapted from some previous/old code
* Plan to update this API in the future
*/
var DialDrag = function() { };
DialDrag.prototype = {
init: function(core,actuator,callback){
var that = this;
if (!actuator) actuator = core.container;
this.$btn = $(actuator);
this.$targ = $(actuator);
this.core = core;
this.$btn
.addClass('dialdrag')
.on('mousedown.dialdrag',this.mousedown())
.data('dialdrag',this);
if (!$.isFunction(callback)) callback = function(){ };
this.callback = callback;
this.ondone = callback;
},
remove: function(){
this.$btn
.removeClass('dialdrag')
.off('.dialdrag')
.data('dialdrag',null);
return this;
},
setTarget: function(obj){
this.$targ = $(obj);
return this;
},
getOffset: function(){
var targ = this.$targ, pos = targ.offset();
return [
pos.left + (targ.width()/2),
pos.top + (targ.height()/2)
];
},
relMouse: function(e){
var x = e.pageX - this.offset[0],
y = e.pageY - this.offset[1],
ang = Math.atan2(y,x) * (180 / Math.PI),
vec = Math.sqrt(Math.pow(x,2)+Math.pow(y,2));
return [ x, y, ang, vec ];
},
mousedown: function(){
var that = this;
function mouseUp(e){
$(window).off('.dialdrag');
that.ondone.call(that,that.relMouse(e));
that.core.container.trigger('croprotend');
}
function mouseMove(e){
that.callback.call(that,that.relMouse(e));
}
return function(e) {
that.offset = that.getOffset();
var rel = that.relMouse(e);
that.angleOffset = -that.core.ui.stage.angle+rel[2];
that.distOffset = rel[3];
that.dragOffset = [rel[0],rel[1]];
that.core.container.trigger('croprotstart');
$(window)
.on('mousemove.dialdrag',mouseMove)
.on('mouseup.dialdrag',mouseUp);
that.callback.call(that,that.relMouse(e));
return false;
};
}
};
Jcrop.registerComponent('DialDrag',DialDrag);
@@ -0,0 +1,155 @@
/**
* DragState
* an object that handles dragging events
*
* This object is used by the built-in selection object to
* track a dragging operation on a selection
*/
// var DragState = function(e,selection,ord){{{
var DragState = function(e,selection,ord){
var t = this;
t.x = e.pageX;
t.y = e.pageY;
t.selection = selection;
t.eventTarget = selection.core.opt.dragEventTarget;
t.orig = selection.get();
selection.callFilterFunction('refresh');
var p = selection.core.container.position();
t.elx = p.left;
t.ely = p.top;
t.offsetx = 0;
t.offsety = 0;
t.ord = ord;
t.opposite = t.getOppositeCornerOffset();
t.initEvents(e);
};
// }}}
DragState.prototype = {
// getOppositeCornerOffset: function(){{{
// Calculate relative offset of locked corner
getOppositeCornerOffset: function(){
var o = this.orig;
var relx = this.x - this.elx - o.x;
var rely = this.y - this.ely - o.y;
switch(this.ord){
case 'nw':
case 'w':
return [ o.w - relx, o.h - rely ];
return [ o.x + o.w, o.y + o.h ];
case 'sw':
return [ o.w - relx, -rely ];
return [ o.x + o.w, o.y ];
case 'se':
case 's':
case 'e':
return [ -relx, -rely ];
return [ o.x, o.y ];
case 'ne':
case 'n':
return [ -relx, o.h - rely ];
return [ o.w, o.y + o.h ];
}
return [ null, null ];
},
// }}}
// initEvents: function(e){{{
initEvents: function(e){
$(this.eventTarget)
.on('mousemove.jcrop',this.createDragHandler())
.on('mouseup.jcrop',this.createStopHandler());
},
// }}}
// dragEvent: function(e){{{
dragEvent: function(e){
this.offsetx = e.pageX - this.x;
this.offsety = e.pageY - this.y;
this.selection.updateRaw(this.getBox(),this.ord);
},
// }}}
// endDragEvent: function(e){{{
endDragEvent: function(e){
var sel = this.selection;
sel.core.container.removeClass('jcrop-dragging');
sel.element.trigger('cropend',[sel,sel.core.unscale(sel.get())]);
sel.focus();
},
// }}}
// createStopHandler: function(){{{
createStopHandler: function(){
var t = this;
return function(e){
$(t.eventTarget).off('.jcrop');
t.endDragEvent(e);
return false;
};
},
// }}}
// createDragHandler: function(){{{
createDragHandler: function(){
var t = this;
return function(e){
t.dragEvent(e);
return false;
};
},
// }}}
//update: function(x,y){{{
update: function(x,y){
var t = this;
t.offsetx = x - t.x;
t.offsety = y - t.y;
},
//}}}
//resultWrap: function(d){{{
resultWrap: function(d){
var b = {
x: Math.min(d[0],d[2]),
y: Math.min(d[1],d[3]),
x2: Math.max(d[0],d[2]),
y2: Math.max(d[1],d[3])
};
b.w = b.x2 - b.x;
b.h = b.y2 - b.y;
return b;
},
//}}}
//getBox: function(){{{
getBox: function(){
var t = this;
var o = t.orig;
var _c = { x2: o.x + o.w, y2: o.y + o.h };
switch(t.ord){
case 'n': return t.resultWrap([ o.x, t.offsety + o.y, _c.x2, _c.y2 ]);
case 's': return t.resultWrap([ o.x, o.y, _c.x2, t.offsety + _c.y2 ]);
case 'e': return t.resultWrap([ o.x, o.y, t.offsetx + _c.x2, _c.y2 ]);
case 'w': return t.resultWrap([ o.x + t.offsetx, o.y, _c.x2, _c.y2 ]);
case 'sw': return t.resultWrap([ t.offsetx + o.x, o.y, _c.x2, t.offsety + _c.y2 ]);
case 'se': return t.resultWrap([ o.x, o.y, t.offsetx + _c.x2, t.offsety + _c.y2 ]);
case 'ne': return t.resultWrap([ o.x, t.offsety + o.y, t.offsetx + _c.x2, _c.y2 ]);
case 'nw': return t.resultWrap([ t.offsetx + o.x, t.offsety + o.y, _c.x2, _c.y2 ]);
case 'move':
_c.nx = o.x + t.offsetx;
_c.ny = o.y + t.offsety;
return t.resultWrap([ _c.nx, _c.ny, _c.nx + o.w, _c.ny + o.h ]);
}
}
//}}}
};
Jcrop.registerComponent('DragState',DragState);
@@ -0,0 +1,14 @@
/**
* EventManager
* provides internal event support
*/
var EventManager = function(core){
this.core = core;
};
EventManager.prototype = {
on: function(n,cb){ $(this).on(n,cb); },
off: function(n){ $(this).off(n); },
trigger: function(n){ $(this).trigger(n); }
};
Jcrop.registerComponent('EventManager',EventManager);
@@ -0,0 +1,57 @@
/**
* Image Loader
* Reliably pre-loads images
*/
// var ImageLoader = function(src,element,cb){{{
var ImageLoader = function(src,element,cb){
this.src = src;
if (!element) element = new Image;
this.element = element;
this.callback = cb;
this.load();
};
// }}}
$.extend(ImageLoader,{
// attach: function(el,cb){{{
attach: function(el,cb){
return new ImageLoader(el.src,el,cb);
},
// }}}
// prototype: {{{
prototype: {
getDimensions: function(){
var el = this.element;
if (el.naturalWidth)
return [ el.naturalWidth, el. naturalHeight ];
if (el.width)
return [ el.width, el.height ];
return null;
},
fireCallback: function(){
this.element.onload = null;
if (typeof this.callback == 'function')
this.callback.apply(this,this.getDimensions());
},
isLoaded: function(){
return this.element.complete;
},
load: function(){
var t = this;
var el = t.element;
el.src = t.src;
if (t.isLoaded()) t.fireCallback();
else t.element.onload = function(e){
t.fireCallback();
};
}
}
// }}}
});
Jcrop.registerComponent('ImageLoader',ImageLoader);
@@ -0,0 +1,99 @@
/**
* JcropTouch
* Detects and enables mobile touch support
*/
// var JcropTouch = function(core){{{
var JcropTouch = function(core){
this.core = core;
this.init();
};
// }}}
$.extend(JcropTouch,{
// support: function(){{{
support: function(){
if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch)
return true;
},
// }}}
prototype: {
// init: function(){{{
init: function(){
var t = this,
p = $.Jcrop.component.DragState.prototype;
// A bit of an ugly hack to make sure we modify prototype
// only once, store a key on the prototype
if (!p.touch) {
t.initEvents();
t.shimDragState();
t.shimStageDrag();
p.touch = true;
}
},
// }}}
// shimDragState: function(){{{
shimDragState: function(){
var t = this;
$.Jcrop.component.DragState.prototype.initEvents = function(e){
// Attach subsequent drag event handlers based on initial
// event type - avoids collecting "pseudo-mouse" events
// generated by some mobile browsers in some circumstances
if (e.type.substr(0,5) == 'touch') {
$(this.eventTarget)
.on('touchmove.jcrop.jcrop-touch',t.dragWrap(this.createDragHandler()))
.on('touchend.jcrop.jcrop-touch',this.createStopHandler());
}
// For other events, use the mouse handlers that
// the default DragState.initEvents() method sets...
else {
$(this.eventTarget)
.on('mousemove.jcrop',this.createDragHandler())
.on('mouseup.jcrop',this.createStopHandler());
}
};
},
// }}}
// shimStageDrag: function(){{{
shimStageDrag: function(){
this.core.container
.addClass('jcrop-touch')
.on('touchstart.jcrop.jcrop-stage',this.dragWrap(this.core.ui.manager.startDragHandler()));
},
// }}}
// dragWrap: function(cb){{{
dragWrap: function(cb){
return function(e){
e.preventDefault();
e.stopPropagation();
if (e.type.substr(0,5) == 'touch') {
e.pageX = e.originalEvent.changedTouches[0].pageX;
e.pageY = e.originalEvent.changedTouches[0].pageY;
return cb(e);
}
return false;
};
},
// }}}
// initEvents: function(){{{
initEvents: function(){
var t = this, c = t.core;
c.container.on(
'touchstart.jcrop.jcrop-touch',
'.'+c.opt.css_drag,
t.dragWrap(c.startDrag())
);
}
// }}}
}
});
Jcrop.registerComponent('Touch',JcropTouch);
@@ -0,0 +1,65 @@
/**
* KeyWatcher
* provides keyboard support
*/
// var KeyWatcher = function(core){{{
var KeyWatcher = function(core){
this.core = core;
this.init();
};
// }}}
$.extend(KeyWatcher,{
// defaults: {{{
defaults: {
eventName: 'keydown.jcrop',
passthru: [ 9 ],
debug: false
},
// }}}
prototype: {
// init: function(){{{
init: function(){
$.extend(this,KeyWatcher.defaults);
this.enable();
},
// }}}
// disable: function(){{{
disable: function(){
this.core.container.off(this.eventName);
},
// }}}
// enable: function(){{{
enable: function(){
var t = this, m = t.core;
m.container.on(t.eventName,function(e){
var nudge = e.shiftKey? 16: 2;
if ($.inArray(e.keyCode,t.passthru) >= 0)
return true;
switch(e.keyCode){
case 37: m.nudge(-nudge,0); break;
case 38: m.nudge(0,-nudge); break;
case 39: m.nudge(nudge,0); break;
case 40: m.nudge(0,nudge); break;
case 46:
case 8:
m.requestDelete();
return false;
break;
default:
if (t.debug) console.log('keycode: ' + e.keyCode);
break;
}
if (!e.metaKey && !e.ctrlKey)
e.preventDefault();
});
}
// }}}
}
});
Jcrop.registerComponent('Keyboard',KeyWatcher);
@@ -0,0 +1,336 @@
/**
* Selection
* Built-in selection object
*/
var Selection = function(){};
$.extend(Selection,{
// defaults: {{{
defaults: {
minSize: [ 8, 8 ],
maxSize: [ 0, 0 ],
aspectRatio: 0,
edge: { n: 0, s: 0, e: 0, w: 0 },
bgColor: null,
bgOpacity: null,
last: null,
state: null,
active: true,
linked: true,
canDelete: true,
canDrag: true,
canResize: true,
canSelect: true
},
// }}}
prototype: {
// init: function(core){{{
init: function(core){
this.core = core;
this.startup();
this.linked = this.core.opt.linked;
this.attach();
this.setOptions(this.core.opt);
core.container.trigger('cropcreate',[this]);
},
// }}}
// attach: function(){{{
attach: function(){
// For extending init() sequence
},
// }}}
// startup: function(){{{
startup: function(){
var t = this, o = t.core.opt;
$.extend(t,Selection.defaults);
t.filter = t.core.getDefaultFilters();
t.element = $('<div />').addClass(o.css_selection).data({ selection: t });
t.frame = $('<button />').addClass(o.css_button).data('ord','move').attr('type','button');
t.element.append(t.frame).appendTo(t.core.container);
// IE background/draggable hack
if (t.core.opt.is_msie) t.frame.css({
opacity: 0,
backgroundColor: 'white'
});
t.insertElements();
// Bind focus and blur events for this selection
t.frame.on('focus.jcrop',function(e){
t.core.setSelection(t);
t.element.trigger('cropfocus',t);
t.element.addClass('jcrop-focus');
}).on('blur.jcrop',function(e){
t.element.removeClass('jcrop-focus');
t.element.trigger('cropblur',t);
});
},
// }}}
// propagate: [{{{
propagate: [
'canDelete', 'canDrag', 'canResize', 'canSelect',
'minSize', 'maxSize', 'aspectRatio', 'edge'
],
// }}}
// setOptions: function(opt){{{
setOptions: function(opt){
Jcrop.propagate(this.propagate,opt,this);
this.refresh();
return this;
},
// }}}
// refresh: function(){{{
refresh: function(){
this.allowResize();
this.allowDrag();
this.allowSelect();
this.callFilterFunction('refresh');
this.updateRaw(this.get(),'se');
},
// }}}
// callFilterFunction: function(f,args){{{
callFilterFunction: function(f,args){
for(var i=0;i<this.filter.length;i++)
if (this.filter[i][f]) this.filter[i][f](this);
return this;
},
// }}}
//addFilter: function(filter){{{
addFilter: function(filter){
filter.core = this.core;
if (!this.hasFilter(filter)) {
this.filter.push(filter);
this.sortFilters();
if (filter.init) filter.init();
this.refresh();
}
},
//}}}
// hasFilter: function(filter){{{
hasFilter: function(filter){
var i, f = this.filter, n = [];
for(i=0;i<f.length;i++) if (f[i] === filter) return true;
},
// }}}
// sortFilters: function(){{{
sortFilters: function(){
this.filter.sort(
function(x,y){ return x.priority - y.priority; }
);
},
// }}}
//clearFilters: function(){{{
clearFilters: function(){
var i, f = this.filter;
for(var i=0;i<f.length;i++)
if (f[i].destroy) f[i].destroy();
this.filter = [];
},
//}}}
// removeFiltersByTag: function(tag){{{
removeFilter: function(tag){
var i, f = this.filter, n = [];
for(var i=0;i<f.length;i++)
if ((f[i].tag && (f[i].tag == tag)) || (tag === f[i])){
if (f[i].destroy) f[i].destroy();
}
else n.push(f[i]);
this.filter = n;
},
// }}}
// runFilters: function(b,ord){{{
runFilters: function(b,ord){
for(var i=0;i<this.filter.length;i++)
b = this.filter[i].filter(b,ord,this);
return b;
},
// }}}
//endDrag: function(){{{
endDrag: function(){
if (this.state) {
$(document.body).off('.jcrop');
this.focus();
this.state = null;
}
},
//}}}
// startDrag: function(e,ord){{{
startDrag: function(e,ord){
var t = this;
var m = t.core;
ord = ord || $(e.target).data('ord');
this.focus();
if ((ord == 'move') && t.element.hasClass(t.core.opt.css_nodrag))
return false;
this.state = new Jcrop.component.DragState(e,this,ord);
return false;
},
// }}}
// allowSelect: function(v){{{
allowSelect: function(v){
if (v === undefined) v = this.canSelect;
if (v && this.canSelect) this.frame.attr('disabled',false);
else this.frame.attr('disabled','disabled');
return this;
},
// }}}
// allowDrag: function(v){{{
allowDrag: function(v){
var t = this, o = t.core.opt;
if (v == undefined) v = t.canDrag;
if (v && t.canDrag) t.element.removeClass(o.css_nodrag);
else t.element.addClass(o.css_nodrag);
return this;
},
// }}}
// allowResize: function(v){{{
allowResize: function(v){
var t = this, o = t.core.opt;
if (v == undefined) v = t.canResize;
if (v && t.canResize) t.element.removeClass(o.css_noresize);
else t.element.addClass(o.css_noresize);
return this;
},
// }}}
// remove: function(){{{
remove: function(){
this.element.trigger('cropremove',this);
this.element.remove();
},
// }}}
// toBack: function(){{{
toBack: function(){
this.active = false;
this.element.removeClass('jcrop-current jcrop-focus');
},
// }}}
// toFront: function(){{{
toFront: function(){
this.active = true;
this.element.addClass('jcrop-current');
this.callFilterFunction('refresh');
this.refresh();
},
// }}}
// redraw: function(b){{{
redraw: function(b){
this.moveTo(b.x,b.y);
this.resize(b.w,b.h);
this.last = b;
return this;
},
// }}}
// update: function(b,ord){{{
update: function(b,ord){
return this.updateRaw(this.core.scale(b),ord);
},
// }}}
// update: function(b,ord){{{
updateRaw: function(b,ord){
b = this.runFilters(b,ord);
this.redraw(b);
this.element.trigger('cropmove',[this,this.core.unscale(b)]);
return this;
},
// }}}
// animateTo: function(box,cb){{{
animateTo: function(box,cb){
var ca = new Jcrop.component.Animator(this),
b = this.core.scale(Jcrop.wrapFromXywh(box));
ca.animate(b.x,b.y,b.w,b.h,cb);
},
// }}}
// center: function(instant){{{
center: function(instant){
var b = this.get(), m = this.core;
var elw = m.container.width(), elh = m.container.height();
var box = [ (elw-b.w)/2, (elh-b.h)/2, b.w, b.h ];
return this[instant?'setSelect':'animateTo'](box);
},
// }}}
//createElement: function(type,ord){{{
createElement: function(type,ord){
return $('<div />').addClass(type+' ord-'+ord).data('ord',ord);
},
//}}}
//moveTo: function(x,y){{{
moveTo: function(x,y){
this.element.css({top: y+'px', left: x+'px'});
},
//}}}
// blur: function(){{{
blur: function(){
this.element.blur();
return this;
},
// }}}
// focus: function(){{{
focus: function(){
this.core.setSelection(this);
this.frame.focus();
return this;
},
// }}}
//resize: function(w,h){{{
resize: function(w,h){
this.element.css({width: w+'px', height: h+'px'});
},
//}}}
//get: function(){{{
get: function(){
var b = this.element,
o = b.position(),
w = b.width(),
h = b.height(),
rv = { x: o.left, y: o.top };
rv.x2 = rv.x + w;
rv.y2 = rv.y + h;
rv.w = w;
rv.h = h;
return rv;
},
//}}}
//insertElements: function(){{{
insertElements: function(){
var t = this, i,
m = t.core,
fr = t.element,
o = t.core.opt,
b = o.borders,
h = o.handles,
d = o.dragbars;
for(i=0; i<d.length; i++)
fr.append(t.createElement(o.css_dragbars,d[i]));
for(i=0; i<h.length; i++)
fr.append(t.createElement(o.css_handles,h[i]));
for(i=0; i<b.length; i++)
fr.append(t.createElement(o.css_borders,b[i]));
}
//}}}
}
});
Jcrop.registerComponent('Selection',Selection);
@@ -0,0 +1,77 @@
/**
* StageDrag
* Facilitates dragging
*/
// var StageDrag = function(manager,opt){{{
var StageDrag = function(manager,opt){
$.extend(this,StageDrag.defaults,opt || {});
this.manager = manager;
this.core = manager.core;
};
// }}}
// StageDrag.defaults = {{{
StageDrag.defaults = {
offset: [ -8, -8 ],
active: true,
minsize: [ 20, 20 ]
};
// }}}
$.extend(StageDrag.prototype,{
// start: function(e){{{
start: function(e){
var c = this.core;
// Do nothing if allowSelect is off
if (!c.opt.allowSelect) return;
// Also do nothing if we can't draw any more selections
if (c.opt.multi && c.opt.multiMax && (c.ui.multi.length >= c.opt.multiMax)) return false;
// calculate a few variables for this drag operation
var o = $(e.currentTarget).offset();
var origx = e.pageX - o.left + this.offset[0];
var origy = e.pageY - o.top + this.offset[1];
var m = c.ui.multi;
// Determine newly dragged crop behavior if multi disabled
if (!c.opt.multi) {
// For multiCleaanup true, remove all existing selections
if (c.opt.multiCleanup){
for(var i=0;i<m.length;i++) m[i].remove();
c.ui.multi = [];
}
// If not, only remove the currently active selection
else {
c.removeSelection(c.ui.selection);
}
}
c.container.addClass('jcrop-dragging');
// Create the new selection
var sel = c.newSelection()
// and position it
.updateRaw(Jcrop.wrapFromXywh([origx,origy,1,1]));
sel.element.trigger('cropstart',[sel,this.core.unscale(sel.get())]);
return sel.startDrag(e,'se');
},
// }}}
// end: function(x,y){{{
end: function(x,y){
this.drag(x,y);
var b = this.sel.get();
this.core.container.removeClass('jcrop-dragging');
if ((b.w < this.minsize[0]) || (b.h < this.minsize[1]))
this.core.requestDelete();
else this.sel.focus();
}
// }}}
});
Jcrop.registerComponent('StageDrag',StageDrag);
@@ -0,0 +1,75 @@
/**
* StageManager
* Provides basic stage-specific functionality
*/
// var StageManager = function(core){{{
var StageManager = function(core){
this.core = core;
this.ui = core.ui;
this.init();
};
// }}}
$.extend(StageManager.prototype,{
// init: function(){{{
init: function(){
this.setupEvents();
this.dragger = new StageDrag(this);
},
// }}}
// tellConfigUpdate: function(options){{{
tellConfigUpdate: function(options){
for(var i=0,m=this.ui.multi,l=m.length;i<l;i++)
if (m[i].setOptions && (m[i].linked || (this.core.opt.linkCurrent && m[i] == this.ui.selection)))
m[i].setOptions(options);
},
// }}}
// startDragHandler: function(){{{
startDragHandler: function(){
var t = this;
return function(e){
if (!e.button || t.core.opt.is_ie_lt9) return t.dragger.start(e);
};
},
// }}}
// removeEvents: function(){{{
removeEvents: function(){
this.core.event.off('.jcrop-stage');
this.core.container.off('.jcrop-stage');
},
// }}}
// shimLegacyHandlers: function(options){{{
// This method uses the legacyHandlers configuration object to
// gracefully wrap old-style Jcrop events with new ones
shimLegacyHandlers: function(options){
var _x = {}, core = this.core, tmp;
$.each(core.opt.legacyHandlers,function(k,i){
if (k in options) {
tmp = options[k];
core.container.off('.jcrop-'+k)
.on(i+'.jcrop.jcrop-'+k,function(e,s,c){
tmp.call(core,c);
});
delete options[k];
}
});
},
// }}}
// setupEvents: function(){{{
setupEvents: function(){
var t = this, c = t.core;
c.event.on('configupdate.jcrop-stage',function(e){
t.shimLegacyHandlers(c.opt);
t.tellConfigUpdate(c.opt)
c.container.trigger('cropconfig',[c,c.opt]);
});
this.core.container
.on('mousedown.jcrop.jcrop-stage',this.startDragHandler());
}
// }}}
});
Jcrop.registerComponent('StageManager',StageManager);
@@ -0,0 +1,140 @@
var Thumbnailer = function(){
};
$.extend(Thumbnailer,{
defaults: {
// Set to a specific Selection object
// If this value is set, the preview will only track that Selection
selection: null,
fading: true,
fadeDelay: 1000,
fadeDuration: 1000,
autoHide: false,
width: 80,
height: 80,
_hiding: null
},
prototype: {
recopyCanvas: function(){
var s = this.core.ui.stage, cxt = s.context;
this.context.putImageData(cxt.getImageData(0,0,s.canvas.width,s.canvas.height),0,0);
},
init: function(core,options){
var t = this;
this.core = core;
$.extend(this,Thumbnailer.defaults,options);
t.initEvents();
t.refresh();
t.insertElements();
if (t.selection) {
t.renderSelection(t.selection);
t.selectionTarget = t.selection.element[0];
} else if (t.core.ui.selection) {
t.renderSelection(t.core.ui.selection);
}
if (t.core.ui.stage.canvas) {
t.context = t.preview[0].getContext('2d');
t.core.container.on('cropredraw',function(e){
t.recopyCanvas();
t.refresh();
});
}
},
updateImage: function(imgel){
this.preview.remove();
this.preview = $($.Jcrop.imageClone(imgel));
this.element.append(this.preview);
this.refresh();
return this;
},
insertElements: function(){
this.preview = $($.Jcrop.imageClone(this.core.ui.stage.imgsrc));
this.element = $('<div />').addClass('jcrop-thumb')
.width(this.width).height(this.height)
.append(this.preview)
.appendTo(this.core.container);
},
resize: function(w,h){
this.width = w;
this.height = h;
this.element.width(w).height(h);
this.renderCoords(this.last);
},
refresh: function(){
this.cw = (this.core.opt.xscale * this.core.container.width());
this.ch = (this.core.opt.yscale * this.core.container.height());
if (this.last) {
this.renderCoords(this.last);
}
},
renderCoords: function(c){
var rx = this.width / c.w;
var ry = this.height / c.h;
this.preview.css({
width: Math.round(rx * this.cw) + 'px',
height: Math.round(ry * this.ch) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
this.last = c;
return this;
},
renderSelection: function(s){
return this.renderCoords(s.core.unscale(s.get()));
},
selectionStart: function(s){
this.renderSelection(s);
},
show: function(){
if (this._hiding) clearTimeout(this._hiding);
if (!this.fading) this.element.stop().css({ opacity: 1 });
else this.element.stop().animate({ opacity: 1 },{ duration: 80, queue: false });
},
hide: function(){
var t = this;
if (!t.fading) t.element.hide();
else t._hiding = setTimeout(function(){
t._hiding = null;
t.element.stop().animate({ opacity: 0 },{ duration: t.fadeDuration, queue: false });
},t.fadeDelay);
},
initEvents: function(){
var t = this;
t.core.container.on('croprotstart croprotend cropimage cropstart cropmove cropend',function(e,s,c){
if (t.selectionTarget && (t.selectionTarget !== e.target)) return false;
switch(e.type){
case 'cropimage':
t.updateImage(c);
break;
case 'cropstart':
t.selectionStart(s);
case 'croprotstart':
t.show();
break;
case 'cropend':
t.renderCoords(c);
case 'croprotend':
if (t.autoHide) t.hide();
break;
case 'cropmove':
t.renderCoords(c);
break;
}
});
}
}
});
Jcrop.registerComponent('Thumbnailer',Thumbnailer);
@@ -0,0 +1,29 @@
// Jcrop constructor
var Jcrop = function(element,opt){
var _ua = navigator.userAgent.toLowerCase();
this.opt = $.extend({},Jcrop.defaults,opt || {});
this.container = $(element);
this.opt.is_msie = /msie/.test(_ua);
this.opt.is_ie_lt9 = /msie [1-8]\./.test(_ua);
this.container.addClass(this.opt.css_container);
this.ui = {};
this.state = null;
this.ui.multi = [];
this.ui.selection = null;
this.filter = {};
this.init();
this.setOptions(opt);
this.applySizeConstraints();
this.container.trigger('cropinit',this);
// IE<9 doesn't work if mouse events are attached to window
if (this.opt.is_ie_lt9)
this.opt.dragEventTarget = document.body;
};
+278
View File
@@ -0,0 +1,278 @@
@white: white;
@black: black;
@selectionBorderWidth: 1px;
@selectionBackgroundImage: "Jcrop.gif";
@selectionBackgroundColor: @white;
@selectionBackground: @selectionBackgroundColor url(@selectionBackgroundImage);
// Setting some variables to
// Used to set handle and dragbar size/width
// To center on a 1px selection line, use an odd number
@grabSize: 9px;
// Used to offset handles and dragbar
// Default value will center on 1px selection line
@grabOffset: (floor(@grabSize/2)+1) * -1;
@handleSize: @grabSize;
@handleOffset: @grabOffset;
@handleBorderWidth: 1px;
@handleBorderColor: #eee;
@handleBorderStyle: solid;
@handleBackgroundColor: rgba(49,28,28,0.58);
@handleOpacity: 0.8;
@dragbarWidth: @grabSize;
@dragbarOffset: @grabOffset;
/*
The outer-most container in a typical Jcrop instance
If you are having difficulty with formatting related to styles
on a parent element, place any fixes here or in a like selector
You can also style this element if you want to add a border, etc
A better method for styling can be seen below with .jcrop-light
(Add a class to the holder and style elements for that extended class)
*/
.jcrop-active {
direction: ltr;
text-align: left;
box-sizing: border-box;
/* IE10 touch compatibility */ -ms-touch-action: none;
}
.jcrop-dragging {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.jcrop-selection {
z-index: 2;
&.jcrop-current { z-index: 4; }
}
/* Selection Borders */
.jcrop-border {
background: @selectionBackground;
line-height: 1px !important;
font-size: 0 !important;
overflow: hidden;
position: absolute;
filter: Alpha(opacity=50) !important;
opacity: 0.5 !important;
&.ord-w, &.ord-e, &.ord-n { top: 0px; }
&.ord-n, &.ord-s { width: 100%; height: @selectionBorderWidth !important; }
&.ord-w, &.ord-e { height: 100%; width: @selectionBorderWidth !important; }
&.ord-e { right: -@selectionBorderWidth; }
&.ord-n { top: -@selectionBorderWidth; }
&.ord-w { left: -@selectionBorderWidth; }
&.ord-s { bottom: -@selectionBorderWidth; }
}
.jcrop-selection {
position: absolute;
}
.jcrop-box {
z-index: 2;
display: block;
background: none;
border: none;
padding: 0;
margin: 0;
font-size: 0;
&:hover { background: none; }
&:active { background: none; }
&:focus { outline: 1px rgba(128,128,128,.65) dotted; }
}
.jcrop-active, .jcrop-box { position: relative; }
.jcrop-box { width: 100%; height: 100%; cursor: move; }
.handles (@handleSize;@handleOffset;@bgColor;@bgOpacity;@borderWidth;@borderColor;@borderStyle) {
z-index: 4;
@ieopacity: @bgOpacity * 100;
font-size: 0;
background-color: @bgColor;
border: @borderWidth @borderColor @borderStyle;
width: @handleSize;
height: @handleSize;
font-size: 0;
position: absolute;
filter: Alpha(opacity=@ieopacity) !important;
opacity: @bgOpacity !important;
&.ord-n {left:50%;margin-left:@handleOffset;margin-top:@handleOffset;top:0;cursor:n-resize;}
&.ord-s {bottom:0;left:50%;margin-bottom:@handleOffset;margin-left:@handleOffset;cursor:s-resize;}
&.ord-e {margin-right:@handleOffset;margin-top:@handleOffset;right:0;top:50%;cursor:e-resize;}
&.ord-w {left:0;margin-left:@handleOffset;margin-top:@handleOffset;top:50%;cursor:w-resize;}
&.ord-nw {left:0;margin-left:@handleOffset;margin-top:@handleOffset;top:0;cursor:nw-resize;}
&.ord-ne {margin-right:@handleOffset;margin-top:@handleOffset;right:0;top:0;cursor:ne-resize;}
&.ord-se {bottom:0;margin-bottom:@handleOffset;margin-right:@handleOffset;right:0;cursor:se-resize;}
&.ord-sw {bottom:0;left:0;margin-bottom:@handleOffset;margin-left:@handleOffset;cursor:sw-resize;}
}
.standard-handles (@handleSize;@bgColor;@bgOpacity;@borderColor) {
@handleOffset: (floor(@handleSize/2)+1) * -1;
.handles(@handleSize;@handleOffset;@bgColor;@bgOpacity;@handleBorderWidth;@borderColor;@handleBorderStyle);
}
/* Selection Handles */
.jcrop-handle {
.standard-handles(@handleSize;@handleBackgroundColor;@handleOpacity;@handleBorderColor);
}
/* Larger Selection Handles for Touch */
.jcrop-touch .jcrop-handle {
.standard-handles(@handleSize * 2;@handleBackgroundColor;@handleOpacity;@handleBorderColor);
}
/* Selection Dragbars */
.jcrop-dragbar {
font-size: 0;
position: absolute;
&.ord-n, &.ord-s {height:@dragbarWidth !important;width:100%;}
&.ord-e, &.ord-w { top:0px; height:100%;width:@dragbarWidth !important;}
&.ord-n {margin-top:@dragbarOffset;cursor:n-resize; top:0px; }
&.ord-s {bottom:0;margin-bottom:@dragbarOffset;cursor:s-resize;}
&.ord-e {margin-right:@dragbarOffset;right:0;cursor:e-resize;}
&.ord-w {margin-left:@dragbarOffset;cursor:w-resize;}
}
/* Shading panels */
.jcrop-shades {
position: relative;
top: 0;
left: 0;
div { cursor: crosshair; }
}
/* Various special states */
.jcrop-noresize {
.jcrop-dragbar,
.jcrop-handle
{ display: none; }
}
.jcrop-selection.jcrop-nodrag .jcrop-box,
.jcrop-nodrag .jcrop-shades div
{ cursor: default; }
/* The "jcrop-light" class/extension */
.jcrop-light {
.jcrop-border {
background: @white;
filter:Alpha(opacity=70)!important;
opacity:.70!important;
}
.jcrop-handle {
background-color: @black;
border-color: @white;
}
}
/* The "jcrop-dark" class/extension */
.jcrop-dark {
.jcrop-border {
background: @black;
filter: Alpha(opacity=70) !important;
opacity: 0.7 !important;
}
.jcrop-handle {
background-color: @white;
border-color: @black;
}
}
/* Simple macro to turn off the antlines */
.solid-line {
.jcrop-border {
background: @selectionBackgroundColor;
}
}
.jcrop-thumb {
position: absolute;
overflow: hidden;
z-index: 5;
}
/* Fix for twitter bootstrap et al. */
.jcrop-active img,
.jcrop-thumb img,
.jcrop-thumb canvas {
min-width: none;
min-height: none;
max-width: none;
max-height: none;
}
/* Improved multiple selection styles - in progress */
.jcrop-hl-active {
.jcrop-border {
filter:Alpha(opacity=20)!important;
opacity:.20!important;
}
.jcrop-handle {
filter:Alpha(opacity=10)!important;
opacity:.10!important;
}
.jcrop-selection:hover {
.jcrop-border {
background-color: #ccc;
filter:Alpha(opacity=50)!important;
opacity:.50!important;
}
/*
.jcrop-handle {
filter:Alpha(opacity=35)!important;
opacity:.35!important;
}
*/
}
.jcrop-selection.jcrop-current {
.jcrop-border {
background: gray url('Jcrop.gif');
opacity:.35!important;
filter:Alpha(opacity=35)!important;
}
.jcrop-handle {
filter:Alpha(opacity=30)!important;
opacity:.30!important;
}
}
.jcrop-selection.jcrop-focus {
.jcrop-border {
background: url('Jcrop.gif');
opacity:.65!important;
filter:Alpha(opacity=65)!important;
}
.jcrop-handle {
filter:Alpha(opacity=60)!important;
opacity:.60!important;
}
}
}
/* Prevent background on button element */
button.jcrop-box { background: none; }
@@ -0,0 +1,8 @@
## LESScss source files
Files in this folder are used to compile the Jcrop.css file from .less definitions.
##### Compiling with Grunt
$ npm install
$ grunt css
@@ -0,0 +1,64 @@
/*!
* Bootstrap v2.2.1
*
* Copyright 2012 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
*/
// CSS Reset
@import "_reset.less";
// Core variables and mixins
@import "_variables.less"; // Modify this for custom colors, font-sizes, etc
@import "bs/less/mixins.less";
// Grid system and page structure
@import "bs/less/scaffolding.less";
@import "bs/less/grid.less";
@import "bs/less/layouts.less";
// Base CSS
@import "bs/less/type.less";
@import "bs/less/code.less";
@import "bs/less/forms.less";
@import "bs/less/tables.less";
// Components: common
@import "bs/less/sprites.less";
@import "bs/less/dropdowns.less";
@import "bs/less/wells.less";
@import "bs/less/component-animations.less";
@import "bs/less/close.less";
// Components: Buttons & Alerts
@import "bs/less/buttons.less";
@import "bs/less/button-groups.less";
@import "bs/less/alerts.less"; // Note: alerts share common CSS with buttons and thus have styles in buttons.less
// Components: Nav
@import "bs/less/navs.less";
@import "bs/less/navbar.less";
@import "bs/less/breadcrumbs.less";
@import "bs/less/pagination.less";
@import "bs/less/pager.less";
// Components: Popovers
@import "bs/less/modals.less";
@import "bs/less/tooltip.less";
@import "bs/less/popovers.less";
// Components: Misc
//@import "bs/less/thumbnails.less";
@import "bs/less/media.less";
@import "bs/less/labels-badges.less";
@import "bs/less/progress-bars.less";
@import "bs/less/accordion.less";
@import "bs/less/carousel.less";
@import "bs/less/hero-unit.less";
// Utility classes
@import "bs/less/utilities.less"; // Has to be last to override when necessary
@@ -0,0 +1,118 @@
//
// Modals
// Adapted from http://github.com/necolas/normalize.css
// --------------------------------------------------
// Display in IE6-9 and FF3
// -------------------------
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section {
display: block;
}
// Display block in IE6-9 and FF3
// -------------------------
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
// Prevents modern browsers from displaying 'audio' without controls
// -------------------------
audio:not([controls]) {
display: none;
}
// Base settings
// -------------------------
html {
font-size: 100%;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
// Focus states
a:focus {
.tab-focus();
}
// Hover & Active
a:hover,
a:active {
outline: 0;
}
// Prevents sub and sup affecting line-height in all browsers
// -------------------------
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
// Forms
// -------------------------
// Font size in all browsers, margin changes, misc consistency
button,
input,
select,
textarea {
margin: 0;
font-size: 100%;
vertical-align: middle;
}
button,
input {
*overflow: visible; // Inner spacing ie IE6/7
line-height: normal; // FF3/4 have !important on line-height in UA stylesheet
}
button::-moz-focus-inner,
input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
padding: 0;
border: 0;
}
button,
html input[type="button"], // Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls.
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; // Corrects inability to style clickable `input` types in iOS.
cursor: pointer; // Improves usability and consistency of cursor style between image-type `input` and others.
}
input[type="search"] { // Appearance in Safari/Chrome
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
-webkit-appearance: textfield;
}
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
}
textarea {
overflow: auto; // Remove vertical scrollbar in IE6-9
vertical-align: top; // Readability and alignment cross-browser
}
@@ -0,0 +1,29 @@
.tapmodo-logo
{
display: block;
width: 103px;
height: 21px;
background-repeat: no-repeat;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGcAAAAVCAYAAABbq/AzAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABUNJREFUeNrsWX9oU1cUvn0pkUDlSaDSEcgoRAqFN1IqhY79IRuFDUFRFEHp6LBYMhRBURREQSYbW5UOpaIoSkVpURDEYZlMWhiWDQNloigWgsFCoFCQBQphj3nu+C4cD/e+NCOTsnjgI+/d3nvfuef3uW0aHh5WjLJAHO8zhMdq+dRGCAhJwoR6T+OEDJ5vEb6rZXEzfjsIo4RPLXMWCPcJhwnzEXvlsIem1++V8w/1EtJ4fl7rYg+a/cOhGE2thJ2YE0Ts5bPnsIEV0kKI1WMjD5udg7VHURJKsjFzgbCFjcUxNmph9HPCdcIjhm9gBFLZ5u85zHlJ+BuGkrPw0o/vXkA02Eu4hz3GEHa1Ed7E2G+Y4zrvt4QpzL1LOERIRHjJE8KfhL8Iv2CPKOoknAUfj8BXv/ljE+Uc/bElCGcMwrOFtTOEvOUDaQjNRWuY4i8RdjvmFQhdbG61fTVdJAyx9+sOA1Is3PqW8a8J59l7N4TrO/j8DL9cMVMsV9voBmEXe9/jMF4FeX/hQdvaChf1ABjVRcBRCGstNtXMjBA2WQ6cF/mogrEZKF6JuKvnXiXcYX9rj1Cc+c5lwu/igN1VFFixhN6KmLNJeP2YUExZ8Dkq1h9higkRia5ZvmMoA1nGxPkM9REOeHD1UbhVAAv6CJXFLDxJh4lXhP2W8KM3XQ+GDJUw9rFgUM/5inASBy4B/OAuOkYYhNUuijBpI20UHxA2i/EfCKtEFZoSXtDJlKjPsFp4aJ9QHs/XWm77CF+Ks8nwm2Ce+CF45TLsb2aTslDQSXwghFd1RiT+WimHOO5y/6hEGjIrniP0sJzn8piSsHrFwpErx6bE3Bk8X4ORGj5T2CMmeMgvs+UwNE0osnLb5MC0J5iMI/H2Whg1tPgvFaOVfJopZh4HWVjm+iQzjgwbn69ztfVaCLGFhSJlCXWhMIC2Gr/R4XgueyKxmY/Ngimbl/xaxbKNUrUFXGHekBXzdyHElJfpOdpoXhCeMUVp77hdZ+XMMJ70+R/CY+6J3Flk75Ps+TjOPs56HEmTIoz+DFmN8DkeXElWZ2WLpSg0lnOODxaFkHWJOMAsLy8UOIUDtIsEH5V3Mswyl5CD6u05OjKcYO8B+EoxIxwSa06x3NqGs++I+MYDUQz1QVYJpoNTHqx3VihHWbQ+bWGK00+Ep5akXGHWNijCYgmCmINBbLV4sqEfkQsv4raiC3nAFXIX2W/oGFeO/HMGletji1DXQxactPw2iPPrCLMdZbGyhO+tKBxklXsVBVmhCXdr2rq/RxWhD7IOVdAY3PwyFlXr/GNI1AEEnnck3jSEUxbNbDmif5K9yLukTETEsN2UVEQLUY0SCNVvRYEmcfG5kighYrDscf731LyCeVuqEkZrpawI30pUqXFL2V0PSrIQGqgabvm9BjLEoujTOkTFtEO9fbGbEq2Ebynpux0hMMWKgxzmJcBDzNKb+eLqKN5oyjE3CVoJGyEs16XnNibk3Wz9TlZR9eF3AD1cDIrw8W6rOj9hPPDeJoAiB5DX9XVST7NqPGpFxWe8w0eFGCLkpDCnAAWZCkwXOgdFExrDmk6su2EpgAri1iBEldqG314UW3tRfCWByUZUTrWYz3PPhCiXFbP8aXZ3llHufyW42o4BKOMpK6MVqsIHjRbWbDcZvN/qgPUXWF7IsKusUPSCxltMKJpECAzgZWnWXqQtyishvJoK9D7WhRhvWcml9H9VNfks9PjwkhDPrayfCSDYWUvVZd7bEbJaWJjLQnlFppwA+/gi7LWK5tTcG2rFzb8RYADOuFkIlIcpJwAAAABJRU5ErkJggg==);
overflow: hidden;
text-indent: -99em;
}
.tapmodo-footer {
font-size: 10px;
color: #aaa;
line-height: 1.1;
border-top: 1px #eee solid;
padding: 22px 0 16px;
margin-top: 3.5em;
.segment {
float: left;
margin-right: 1.5em;
a {
color: #999;
text-decoration: underline;
&:hover { color: #888; text-decoration: none; }
}
}
}
+77
View File
@@ -0,0 +1,77 @@
/////////////////////////////////
// DEFAULT SETTINGS
Jcrop.defaults = {
// Selection Behavior
edge: { n: 0, s: 0, e: 0, w: 0 },
setSelect: null,
linked: true,
linkCurrent: true,
canDelete: true,
canSelect: true,
canDrag: true,
canResize: true,
// Component constructors
eventManagerComponent: Jcrop.component.EventManager,
keyboardComponent: Jcrop.component.Keyboard,
dragstateComponent: Jcrop.component.DragState,
stagemanagerComponent: Jcrop.component.StageManager,
animatorComponent: Jcrop.component.Animator,
selectionComponent: Jcrop.component.Selection,
// This is a function that is called, which returns a stage object
stageConstructor: Jcrop.stageConstructor,
// Stage Behavior
allowSelect: true,
multi: false,
multiMax: false,
multiCleanup: true,
animation: true,
animEasing: 'swing',
animDuration: 400,
fading: true,
fadeDuration: 300,
fadeEasing: 'swing',
bgColor: 'black',
bgOpacity: .5,
// Startup options
applyFilters: [ 'constrain', 'extent', 'backoff', 'ratio', 'shader', 'round' ],
borders: [ 'e', 'w', 's', 'n' ],
handles: [ 'n', 's', 'e', 'w', 'sw', 'ne', 'nw', 'se' ],
dragbars: [ 'n', 'e', 'w', 's' ],
dragEventTarget: window,
xscale: 1,
yscale: 1,
boxWidth: null,
boxHeight: null,
// CSS Classes
// @todo: These need to be moved to top-level object keys
// for better customization. Currently if you try to extend one
// via an options object to Jcrop, it will wipe out all
// the others you don't specify. Be careful for now!
css_nodrag: 'jcrop-nodrag',
css_drag: 'jcrop-drag',
css_container: 'jcrop-active',
css_shades: 'jcrop-shades',
css_selection: 'jcrop-selection',
css_borders: 'jcrop-border',
css_handles: 'jcrop-handle jcrop-drag',
css_button: 'jcrop-box jcrop-drag',
css_noresize: 'jcrop-noresize',
css_dragbars: 'jcrop-dragbar jcrop-drag',
legacyHandlers: {
onChange: 'cropmove',
onSelect: 'cropend'
}
};
@@ -0,0 +1,36 @@
/**
* BackoffFilter
* move out-of-bounds selection into allowed position at same size
*/
var BackoffFilter = function(){
this.minw = 40;
this.minh = 40;
this.maxw = 0;
this.maxh = 0;
this.core = null;
};
$.extend(BackoffFilter.prototype,{
tag: 'backoff',
priority: 22,
filter: function(b){
var r = this.bound;
if (b.x < r.minx) { b.x = r.minx; b.x2 = b.w + b.x; }
if (b.y < r.miny) { b.y = r.miny; b.y2 = b.h + b.y; }
if (b.x2 > r.maxx) { b.x2 = r.maxx; b.x = b.x2 - b.w; }
if (b.y2 > r.maxy) { b.y2 = r.maxy; b.y = b.y2 - b.h; }
return b;
},
refresh: function(sel){
this.elw = sel.core.container.width();
this.elh = sel.core.container.height();
this.bound = {
minx: 0 + sel.edge.w,
miny: 0 + sel.edge.n,
maxx: this.elw + sel.edge.e,
maxy: this.elh + sel.edge.s
};
}
});
Jcrop.registerFilter('backoff',BackoffFilter);
@@ -0,0 +1,36 @@
/**
* ConstrainFilter
* a filter to constrain crop selection to bounding element
*/
var ConstrainFilter = function(){
this.core = null;
};
$.extend(ConstrainFilter.prototype,{
tag: 'constrain',
priority: 5,
filter: function(b,ord){
if (ord == 'move') {
if (b.x < this.minx) { b.x = this.minx; b.x2 = b.w + b.x; }
if (b.y < this.miny) { b.y = this.miny; b.y2 = b.h + b.y; }
if (b.x2 > this.maxx) { b.x2 = this.maxx; b.x = b.x2 - b.w; }
if (b.y2 > this.maxy) { b.y2 = this.maxy; b.y = b.y2 - b.h; }
} else {
if (b.x < this.minx) { b.x = this.minx; }
if (b.y < this.miny) { b.y = this.miny; }
if (b.x2 > this.maxx) { b.x2 = this.maxx; }
if (b.y2 > this.maxy) { b.y2 = this.maxy; }
}
b.w = b.x2 - b.x;
b.h = b.y2 - b.y;
return b;
},
refresh: function(sel){
this.elw = sel.core.container.width();
this.elh = sel.core.container.height();
this.minx = 0 + sel.edge.w;
this.miny = 0 + sel.edge.n;
this.maxx = this.elw + sel.edge.e;
this.maxy = this.elh + sel.edge.s;
}
});
Jcrop.registerFilter('constrain',ConstrainFilter);
@@ -0,0 +1,58 @@
/**
* ExtentFilter
* a filter to implement minimum or maximum size
*/
var ExtentFilter = function(){
this.core = null;
};
$.extend(ExtentFilter.prototype,{
tag: 'extent',
priority: 12,
offsetFromCorner: function(corner,box,b){
var w = box[0], h = box[1];
switch(corner){
case 'bl': return [ b.x2 - w, b.y, w, h ];
case 'tl': return [ b.x2 - w , b.y2 - h, w, h ];
case 'br': return [ b.x, b.y, w, h ];
case 'tr': return [ b.x, b.y2 - h, w, h ];
}
},
getQuadrant: function(s){
var relx = s.opposite[0]-s.offsetx
var rely = s.opposite[1]-s.offsety;
if ((relx < 0) && (rely < 0)) return 'br';
else if ((relx >= 0) && (rely >= 0)) return 'tl';
else if ((relx < 0) && (rely >= 0)) return 'tr';
return 'bl';
},
filter: function(b,ord,sel){
if (ord == 'move') return b;
var w = b.w, h = b.h, st = sel.state, r = this.limits;
var quad = st? this.getQuadrant(st): 'br';
if (r.minw && (w < r.minw)) w = r.minw;
if (r.minh && (h < r.minh)) h = r.minh;
if (r.maxw && (w > r.maxw)) w = r.maxw;
if (r.maxh && (h > r.maxh)) h = r.maxh;
if ((w == b.w) && (h == b.h)) return b;
return Jcrop.wrapFromXywh(this.offsetFromCorner(quad,[w,h],b));
},
refresh: function(sel){
this.elw = sel.core.container.width();
this.elh = sel.core.container.height();
this.limits = {
minw: sel.minSize[0],
minh: sel.minSize[1],
maxw: sel.maxSize[0],
maxh: sel.maxSize[1]
};
}
});
Jcrop.registerFilter('extent',ExtentFilter);
@@ -0,0 +1,29 @@
/**
* GridFilter
* a rudimentary grid effect
*/
var GridFilter = function(){
this.stepx = 1;
this.stepy = 1;
this.core = null;
};
$.extend(GridFilter.prototype,{
tag: 'grid',
priority: 19,
filter: function(b){
var n = {
x: Math.round(b.x / this.stepx) * this.stepx,
y: Math.round(b.y / this.stepy) * this.stepy,
x2: Math.round(b.x2 / this.stepx) * this.stepx,
y2: Math.round(b.y2 / this.stepy) * this.stepy
};
n.w = n.x2 - n.x;
n.h = n.y2 - n.y;
return n;
}
});
Jcrop.registerFilter('grid',GridFilter);
@@ -0,0 +1,78 @@
/**
* RatioFilter
* implements aspectRatio locking
*/
var RatioFilter = function(){
this.ratio = 0;
this.core = null;
};
$.extend(RatioFilter.prototype,{
tag: 'ratio',
priority: 15,
offsetFromCorner: function(corner,box,b){
var w = box[0], h = box[1];
switch(corner){
case 'bl': return [ b.x2 - w, b.y, w, h ];
case 'tl': return [ b.x2 - w , b.y2 - h, w, h ];
case 'br': return [ b.x, b.y, w, h ];
case 'tr': return [ b.x, b.y2 - h, w, h ];
}
},
getBoundRatio: function(b,quad){
var box = Jcrop.getLargestBox(this.ratio,b.w,b.h);
return Jcrop.wrapFromXywh(this.offsetFromCorner(quad,box,b));
},
getQuadrant: function(s){
var relx = s.opposite[0]-s.offsetx
var rely = s.opposite[1]-s.offsety;
if ((relx < 0) && (rely < 0)) return 'br';
else if ((relx >= 0) && (rely >= 0)) return 'tl';
else if ((relx < 0) && (rely >= 0)) return 'tr';
return 'bl';
},
filter: function(b,ord,sel){
if (!this.ratio) return b;
var rt = b.w / b.h;
var st = sel.state;
var quad = st? this.getQuadrant(st): 'br';
ord = ord || 'se';
if (ord == 'move') return b;
switch(ord) {
case 'n':
b.x2 = this.elw;
b.w = b.x2 - b.x;
quad = 'tr';
break;
case 's':
b.x2 = this.elw;
b.w = b.x2 - b.x;
quad = 'br';
break;
case 'e':
b.y2 = this.elh;
b.h = b.y2 - b.y;
quad = 'br';
break;
case 'w':
b.y2 = this.elh;
b.h = b.y2 - b.y;
quad = 'bl';
break;
}
return this.getBoundRatio(b,quad);
},
refresh: function(sel){
this.ratio = sel.aspectRatio;
this.elw = sel.core.container.width();
this.elh = sel.core.container.height();
}
});
Jcrop.registerFilter('ratio',RatioFilter);
@@ -0,0 +1,27 @@
/**
* RoundFilter
* rounds coordinate values to integers
*/
var RoundFilter = function(){
this.core = null;
};
$.extend(RoundFilter.prototype,{
tag: 'round',
priority: 90,
filter: function(b){
var n = {
x: Math.round(b.x),
y: Math.round(b.y),
x2: Math.round(b.x2),
y2: Math.round(b.y2)
};
n.w = n.x2 - n.x;
n.h = n.y2 - n.y;
return n;
}
});
Jcrop.registerFilter('round',RoundFilter);
@@ -0,0 +1,123 @@
/**
* ShadeFilter
* A filter that implements div-based shading on any element
*
* The shading you see is actually four semi-opaque divs
* positioned inside the container, around the selection
*/
var ShadeFilter = function(opacity,color){
this.color = color || 'black';
this.opacity = opacity || 0.5;
this.core = null;
this.shades = {};
};
$.extend(ShadeFilter.prototype,{
tag: 'shader',
fade: true,
fadeEasing: 'swing',
fadeSpeed: 320,
priority: 95,
init: function(){
var t = this;
if (!t.attached) {
t.visible = false;
t.container = $('<div />').addClass(t.core.opt.css_shades)
.prependTo(this.core.container).hide();
t.elh = this.core.container.height();
t.elw = this.core.container.width();
t.shades = {
top: t.createShade(),
right: t.createShade(),
left: t.createShade(),
bottom: t.createShade()
};
t.attached = true;
}
},
destroy: function(){
this.container.remove();
},
setColor: function(color,instant){
var t = this;
if (color == t.color) return t;
this.color = color;
var colorfade = Jcrop.supportsColorFade();
$.each(t.shades,function(u,i){
if (!t.fade || instant || !colorfade) i.css('backgroundColor',color);
else i.animate({backgroundColor:color},{queue:false,duration:t.fadeSpeed,easing:t.fadeEasing});
});
return t;
},
setOpacity: function(opacity,instant){
var t = this;
if (opacity == t.opacity) return t;
t.opacity = opacity;
$.each(t.shades,function(u,i){
if (!t.fade || instant) i.css({opacity:opacity});
else i.animate({opacity:opacity},{queue:false,duration:t.fadeSpeed,easing:t.fadeEasing});
});
return t;
},
createShade: function(){
return $('<div />').css({
position: 'absolute',
backgroundColor: this.color,
opacity: this.opacity
}).appendTo(this.container);
},
refresh: function(sel){
var m = this.core, s = this.shades;
this.setColor(sel.bgColor?sel.bgColor:this.core.opt.bgColor);
this.setOpacity(sel.bgOpacity?sel.bgOpacity:this.core.opt.bgOpacity);
this.elh = m.container.height();
this.elw = m.container.width();
s.right.css('height',this.elh+'px');
s.left.css('height',this.elh+'px');
},
filter: function(b,ord,sel){
if (!sel.active) return b;
var t = this,
s = t.shades;
s.top.css({
left: Math.round(b.x)+'px',
width: Math.round(b.w)+'px',
height: Math.round(b.y)+'px'
});
s.bottom.css({
top: Math.round(b.y2)+'px',
left: Math.round(b.x)+'px',
width: Math.round(b.w)+'px',
height: (t.elh-Math.round(b.y2))+'px'
});
s.right.css({
left: Math.round(b.x2)+'px',
width: (t.elw-Math.round(b.x2))+'px'
});
s.left.css({
width: Math.round(b.x)+'px'
});
if (!t.visible) {
t.container.show();
t.visible = true;
}
return b;
}
});
Jcrop.registerFilter('shader',ShadeFilter);
+2
View File
@@ -0,0 +1,2 @@
(function($){
'use strict';
+378
View File
@@ -0,0 +1,378 @@
/* Modernizr 2.7.1 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-csstransforms-canvas-canvastext-draganddrop-inlinesvg-svg-svgclippaths-touch-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-url_data_uri
*/
;
var Modernizr = (function( window, document, undefined ) {
var version = '2.7.1',
Modernizr = {},
docElement = document.documentElement,
mod = 'modernizr',
modElem = document.createElement(mod),
mStyle = modElem.style,
inputElem ,
toString = {}.toString,
prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
omPrefixes = 'Webkit Moz O ms',
cssomPrefixes = omPrefixes.split(' '),
domPrefixes = omPrefixes.toLowerCase().split(' '),
ns = {'svg': 'http://www.w3.org/2000/svg'},
tests = {},
inputs = {},
attrs = {},
classes = [],
slice = classes.slice,
featureName,
injectElementWithStyles = function( rule, callback, nodes, testnames ) {
var style, ret, node, docOverflow,
div = document.createElement('div'),
body = document.body,
fakeBody = body || document.createElement('body');
if ( parseInt(nodes, 10) ) {
while ( nodes-- ) {
node = document.createElement('div');
node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
div.appendChild(node);
}
}
style = ['&#173;','<style id="s', mod, '">', rule, '</style>'].join('');
div.id = mod;
(body ? div : fakeBody).innerHTML += style;
fakeBody.appendChild(div);
if ( !body ) {
fakeBody.style.background = '';
fakeBody.style.overflow = 'hidden';
docOverflow = docElement.style.overflow;
docElement.style.overflow = 'hidden';
docElement.appendChild(fakeBody);
}
ret = callback(div, rule);
if ( !body ) {
fakeBody.parentNode.removeChild(fakeBody);
docElement.style.overflow = docOverflow;
} else {
div.parentNode.removeChild(div);
}
return !!ret;
},
isEventSupported = (function() {
var TAGNAMES = {
'select': 'input', 'change': 'input',
'submit': 'form', 'reset': 'form',
'error': 'img', 'load': 'img', 'abort': 'img'
};
function isEventSupported( eventName, element ) {
element = element || document.createElement(TAGNAMES[eventName] || 'div');
eventName = 'on' + eventName;
var isSupported = eventName in element;
if ( !isSupported ) {
if ( !element.setAttribute ) {
element = document.createElement('div');
}
if ( element.setAttribute && element.removeAttribute ) {
element.setAttribute(eventName, '');
isSupported = is(element[eventName], 'function');
if ( !is(element[eventName], 'undefined') ) {
element[eventName] = undefined;
}
element.removeAttribute(eventName);
}
}
element = null;
return isSupported;
}
return isEventSupported;
})(),
_hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
hasOwnProp = function (object, property) {
return _hasOwnProperty.call(object, property);
};
}
else {
hasOwnProp = function (object, property) {
return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
};
}
if (!Function.prototype.bind) {
Function.prototype.bind = function bind(that) {
var target = this;
if (typeof target != "function") {
throw new TypeError();
}
var args = slice.call(arguments, 1),
bound = function () {
if (this instanceof bound) {
var F = function(){};
F.prototype = target.prototype;
var self = new F();
var result = target.apply(
self,
args.concat(slice.call(arguments))
);
if (Object(result) === result) {
return result;
}
return self;
} else {
return target.apply(
that,
args.concat(slice.call(arguments))
);
}
};
return bound;
};
}
function setCss( str ) {
mStyle.cssText = str;
}
function setCssAll( str1, str2 ) {
return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
}
function is( obj, type ) {
return typeof obj === type;
}
function contains( str, substr ) {
return !!~('' + str).indexOf(substr);
}
function testProps( props, prefixed ) {
for ( var i in props ) {
var prop = props[i];
if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
return prefixed == 'pfx' ? prop : true;
}
}
return false;
}
function testDOMProps( props, obj, elem ) {
for ( var i in props ) {
var item = obj[props[i]];
if ( item !== undefined) {
if (elem === false) return props[i];
if (is(item, 'function')){
return item.bind(elem || obj);
}
return item;
}
}
return false;
}
function testPropsAll( prop, prefixed, elem ) {
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
if(is(prefixed, "string") || is(prefixed, "undefined")) {
return testProps(props, prefixed);
} else {
props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
return testDOMProps(props, prefixed, elem);
}
}
tests['canvas'] = function() {
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
};
tests['canvastext'] = function() {
return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
};
tests['touch'] = function() {
var bool;
if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
bool = true;
} else {
injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {
bool = node.offsetTop === 9;
});
}
return bool;
};
tests['draganddrop'] = function() {
var div = document.createElement('div');
return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
};
tests['csstransforms'] = function() {
return !!testPropsAll('transform');
};
tests['svg'] = function() {
return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
};
tests['inlinesvg'] = function() {
var div = document.createElement('div');
div.innerHTML = '<svg/>';
return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
};
tests['svgclippaths'] = function() {
return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
};
for ( var feature in tests ) {
if ( hasOwnProp(tests, feature) ) {
featureName = feature.toLowerCase();
Modernizr[featureName] = tests[feature]();
classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
}
}
Modernizr.addTest = function ( feature, test ) {
if ( typeof feature == 'object' ) {
for ( var key in feature ) {
if ( hasOwnProp( feature, key ) ) {
Modernizr.addTest( key, feature[ key ] );
}
}
} else {
feature = feature.toLowerCase();
if ( Modernizr[feature] !== undefined ) {
return Modernizr;
}
test = typeof test == 'function' ? test() : test;
if (typeof enableClasses !== "undefined" && enableClasses) {
docElement.className += ' ' + (test ? '' : 'no-') + feature;
}
Modernizr[feature] = test;
}
return Modernizr;
};
setCss('');
modElem = inputElem = null;
Modernizr._version = version;
Modernizr._prefixes = prefixes;
Modernizr._domPrefixes = domPrefixes;
Modernizr._cssomPrefixes = cssomPrefixes;
Modernizr.hasEvent = isEventSupported;
Modernizr.testProp = function(prop){
return testProps([prop]);
};
Modernizr.testAllProps = testPropsAll;
Modernizr.testStyles = injectElementWithStyles;
return Modernizr;
})(window, window.document);
// data uri test.
// https://github.com/Modernizr/Modernizr/issues/14
// This test is asynchronous. Watch out.
// in IE7 in HTTPS this can cause a Mixed Content security popup.
// github.com/Modernizr/Modernizr/issues/362
// To avoid that you can create a new iframe and inject this.. perhaps..
(function(){
var datauri = new Image();
datauri.onerror = function() {
Modernizr.addTest('datauri', function () { return false; });
};
datauri.onload = function() {
Modernizr.addTest('datauri', function () { return (datauri.width == 1 && datauri.height == 1); });
};
datauri.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
})();
;
+14
View File
@@ -0,0 +1,14 @@
// Attach to jQuery object
$.Jcrop = Jcrop;
$.Jcrop.supportsCanvas = Modernizr.canvas;
$.Jcrop.supportsCanvasText = Modernizr.canvastext;
$.Jcrop.supportsDragAndDrop = Modernizr.draganddrop;
$.Jcrop.supportsDataURI = Modernizr.datauri;
$.Jcrop.supportsSVG = Modernizr.svg;
$.Jcrop.supportsInlineSVG = Modernizr.inlinesvg;
$.Jcrop.supportsSVGClipPaths = Modernizr.svgclippaths;
$.Jcrop.supportsCSSTransforms = Modernizr.csstransforms;
$.Jcrop.supportsTouch = Modernizr.touch;
})(jQuery);
+63
View File
@@ -0,0 +1,63 @@
// Jcrop jQuery plugin function
$.fn.Jcrop = function(options,callback){
options = options || {};
var first = this.eq(0).data('Jcrop');
var args = Array.prototype.slice.call(arguments);
// Return API if requested
if (options == 'api') { return first; }
// Allow calling API methods (with arguments)
else if (first && (typeof options == 'string')) {
// Call method if it exists
if (first[options]) {
args.shift();
first[options].apply(first,args);
return first;
}
// Unknown input/method does not exist
return false;
}
// Otherwise, loop over selected elements
this.each(function(){
var t = this, $t = $(this);
var exists = $t.data('Jcrop');
var obj;
// If Jcrop already exists on this element only setOptions()
if (exists)
exists.setOptions(options);
else {
if (!options.stageConstructor)
options.stageConstructor = $.Jcrop.stageConstructor;
options.stageConstructor(this,options,function(stage,options){
var selection = options.setSelect;
if (selection) delete(options.setSelect);
var obj = $.Jcrop.attach(stage.element,options);
if (typeof stage.attach == 'function')
stage.attach(obj);
$t.data('Jcrop',obj);
if (selection) {
obj.newSelection();
obj.setSelect(selection);
}
if (typeof callback == 'function')
callback.call(obj);
});
}
return this;
});
};
@@ -0,0 +1,32 @@
var AbstractStage = function(){
};
$.extend(AbstractStage,{
isSupported: function(el,o){
// @todo: should actually check if it's an HTML element
return true;
},
// A higher priority means less desirable
// AbstractStage is the last one we want to use
priority: 100,
create: function(el,options,callback){
var obj = new AbstractStage;
obj.element = el;
callback.call(this,obj,options);
},
prototype: {
attach: function(core){
this.init(core);
core.ui.stage = this;
},
triggerEvent: function(ev){
$(this.element).trigger(ev);
return this;
},
getElement: function(){
return this.element;
}
}
});
Jcrop.registerStageType('Block',AbstractStage);
@@ -0,0 +1,116 @@
var CanvasStage = function(){
this.angle = 0;
this.scale = 1;
this.scaleMin = 0.2;
this.scaleMax = 1.25;
this.offset = [0,0];
};
CanvasStage.prototype = new ImageStage();
$.extend(CanvasStage,{
isSupported: function(el,o){
if ($.Jcrop.supportsCanvas && (el.tagName == 'IMG')) return true;
},
priority: 60,
create: function(el,options,callback){
var $el = $(el);
var opt = $.extend({},options);
$.Jcrop.component.ImageLoader.attach(el,function(w,h){
var obj = new CanvasStage;
$el.hide();
obj.createCanvas(el,w,h);
$el.before(obj.element);
obj.imgsrc = el;
opt.imgsrc = el;
if (typeof callback == 'function'){
callback(obj,opt);
obj.redraw();
}
});
}
});
$.extend(CanvasStage.prototype,{
init: function(core){
this.core = core;
},
// setOffset: function(x,y) {{{
setOffset: function(x,y) {
this.offset = [x,y];
return this;
},
// }}}
// setAngle: function(v) {{{
setAngle: function(v) {
this.angle = v;
return this;
},
// }}}
// setScale: function(v) {{{
setScale: function(v) {
this.scale = this.boundScale(v);
return this;
},
// }}}
boundScale: function(v){
if (v<this.scaleMin) v = this.scaleMin;
else if (v>this.scaleMax) v = this.scaleMax;
return v;
},
createCanvas: function(img,w,h){
this.width = w;
this.height = h;
this.canvas = document.createElement('canvas');
this.canvas.width = w;
this.canvas.height = h;
this.$canvas = $(this.canvas).width('100%').height('100%');
this.context = this.canvas.getContext('2d');
this.fillstyle = "rgb(0,0,0)";
this.element = this.$canvas.wrap('<div />').parent().width(w).height(h);
},
triggerEvent: function(ev){
this.$canvas.trigger(ev);
return this;
},
// clear: function() {{{
clear: function() {
this.context.fillStyle = this.fillstyle;
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
return this;
},
// }}}
// redraw: function() {{{
redraw: function() {
// Save the current context
this.context.save();
this.clear();
// Translate to the center point of our image
this.context.translate(parseInt(this.width * 0.5), parseInt(this.height * 0.5));
// Perform the rotation and scaling
this.context.translate(this.offset[0]/this.core.opt.xscale,this.offset[1]/this.core.opt.yscale);
this.context.rotate(this.angle * (Math.PI/180));
this.context.scale(this.scale,this.scale);
// Translate back to the top left of our image
this.context.translate(-parseInt(this.width * 0.5), -parseInt(this.height * 0.5));
// Finally we draw the image
this.context.drawImage(this.imgsrc,0,0,this.width,this.height);
// And restore the updated context
this.context.restore();
this.$canvas.trigger('cropredraw');
return this;
},
// }}}
// setFillStyle: function(v) {{{
setFillStyle: function(v) {
this.fillstyle = v;
return this;
}
// }}}
});
Jcrop.registerStageType('Canvas',CanvasStage);
@@ -0,0 +1,80 @@
var TransformStage = function(){
this.angle = 0;
this.scale = 1;
this.scaleMin = 0.2;
this.scaleMax = 1.25;
this.offset = [0,0];
};
TransformStage.prototype = new ImageStage();
$.extend(TransformStage,{
isSupported: function(el,o){
if ($.Jcrop.supportsCSSTransforms && (el.tagName == 'IMG')) return true;
},
priority: 101,
create: function(el,options,callback){
$.Jcrop.component.ImageLoader.attach(el,function(w,h){
var obj = new TransformStage;
obj.$img = $(el);
obj.element = obj.$img.wrap('<div />').parent();
obj.element.width(w).height(h);
obj.imgsrc = el;
if (typeof callback == 'function')
callback.call(this,obj,options);
});
}
});
$.extend(TransformStage.prototype,{
init: function(core){
this.core = core;
},
boundScale: function(v){
if (v<this.scaleMin) v = this.scaleMin;
else if (v>this.scaleMax) v = this.scaleMax;
return v;
},
// setOffset: function(x,y) {{{
setOffset: function(x,y) {
this.offset = [x,y];
return this;
},
// }}}
// setAngle: function(v) {{{
setAngle: function(v) {
this.angle = v;
return this;
},
// }}}
// setScale: function(v) {{{
setScale: function(v) {
this.scale = this.boundScale(v);
return this;
},
// }}}
// clear: function() {{{
clear: function() {
},
// }}}
triggerEvent: function(ev){
this.$img.trigger(ev);
return this;
},
// redraw: function() {{{
redraw: function() {
this.$img.css({
transform:
'translate('+(-this.offset[0])+'px,'+(-this.offset[1])+'px) '+
'rotate('+this.angle+'deg) '+
'scale('+this.scale+','+this.scale+')'
});
this.$img.trigger('cropredraw');
return this;
},
// }}}
});
Jcrop.registerStageType('Transform',TransformStage);
@@ -0,0 +1,25 @@
var ImageStage = function(){
};
ImageStage.prototype = new AbstractStage();
$.extend(ImageStage,{
isSupported: function(el,o){
if (el.tagName == 'IMG') return true;
},
priority: 90,
create: function(el,options,callback){
$.Jcrop.component.ImageLoader.attach(el,function(w,h){
var obj = new ImageStage;
obj.element = $(el).wrap('<div />').parent();
obj.element.width(w).height(h);
obj.imgsrc = el;
if (typeof callback == 'function')
callback.call(this,obj,options);
});
}
});
Jcrop.registerStageType('Image',ImageStage);
+95
View File
@@ -0,0 +1,95 @@
// Jcrop static functions
$.extend(Jcrop,{
component: { },
filter: { },
stage: { },
registerComponent: function(name,component){
Jcrop.component[name] = component;
},
registerFilter: function(name,filter){
Jcrop.filter[name] = filter;
},
registerStageType: function(name,stage){
Jcrop.stage[name] = stage;
},
// attach: function(element,opt){{{
attach: function(element,opt){
var obj = new $.Jcrop(element,opt);
return obj;
},
// }}}
// imgCopy: function(imgel){{{
imgCopy: function(imgel){
var img = new Image;
img.src = imgel.src;
return img;
},
// }}}
// imageClone: function(imgel){{{
imageClone: function(imgel){
return $.Jcrop.supportsCanvas?
Jcrop.canvasClone(imgel):
Jcrop.imgCopy(imgel);
},
// }}}
// canvasClone: function(imgel){{{
canvasClone: function(imgel){
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
$(canvas).width(imgel.width).height(imgel.height),
canvas.width = imgel.naturalWidth;
canvas.height = imgel.naturalHeight;
ctx.drawImage(imgel,0,0,imgel.naturalWidth,imgel.naturalHeight);
return canvas;
},
// }}}
// propagate: function(plist,config,obj){{{
propagate: function(plist,config,obj){
for(var i=0,l=plist.length;i<l;i++)
if (config.hasOwnProperty(plist[i]))
obj[plist[i]] = config[plist[i]];
},
// }}}
// getLargestBox: function(ratio,w,h){{{
getLargestBox: function(ratio,w,h){
if ((w/h) > ratio)
return [ h * ratio, h ];
else return [ w, w / ratio ];
},
// }}}
// stageConstructor: function(el,options,callback){{{
stageConstructor: function(el,options,callback){
// Get a priority-ordered list of available stages
var stages = [];
$.each(Jcrop.stage,function(i,e){
stages.push(e);
});
stages.sort(function(a,b){ return a.priority - b.priority; });
// Find the first one that supports this element
for(var i=0,l=stages.length;i<l;i++){
if (stages[i].isSupported(el,options)){
stages[i].create(el,options,function(obj,opt){
if (typeof callback == 'function') callback(obj,opt);
});
break;
}
}
},
// }}}
// supportsColorFade: function(){{{
supportsColorFade: function(){
return $.fx.step.hasOwnProperty('backgroundColor');
},
// }}}
// wrapFromXywh: function(xywh){{{
wrapFromXywh: function(xywh){
var b = { x: xywh[0], y: xywh[1], w: xywh[2], h: xywh[3] };
b.x2 = b.x + b.w;
b.y2 = b.y + b.h;
return b;
}
// }}}
});