mirror of https://github.com/friendica/friendica
Merge pull request #4711 from rabuzarus/20180329_-_cropperjs
update javascript cropper librarypull/4718/head
commit
8a2d41e53f
@ -1,182 +0,0 @@
|
||||
.imgCrop_wrap {
|
||||
/* width: 500px; @done_in_js */
|
||||
/* height: 375px; @done_in_js */
|
||||
position: relative;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
/* an extra classname is applied for Opera < 9.0 to fix it's lack of opacity support */
|
||||
.imgCrop_wrap.opera8 .imgCrop_overlay,
|
||||
.imgCrop_wrap.opera8 .imgCrop_clickArea {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* fix for IE displaying all boxes at line-height by default, although they are still 1 pixel high until we combine them with the pointless span */
|
||||
.imgCrop_wrap,
|
||||
.imgCrop_wrap * {
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.imgCrop_overlay {
|
||||
background-color: #000;
|
||||
opacity: 0.5;
|
||||
filter:alpha(opacity=50);
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.imgCrop_selArea {
|
||||
position: absolute;
|
||||
/* @done_in_js
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: transparent url(castle.jpg) no-repeat -210px -110px;
|
||||
*/
|
||||
cursor: move;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* clickArea is all a fix for IE 5.5 & 6 to allow the user to click on the given area */
|
||||
.imgCrop_clickArea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #FFF;
|
||||
opacity: 0.01;
|
||||
filter:alpha(opacity=01);
|
||||
}
|
||||
|
||||
.imgCrop_marqueeHoriz {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: transparent url(marqueeHoriz.gif) repeat-x 0 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.imgCrop_marqueeVert {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
background: transparent url(marqueeVert.gif) repeat-y 0 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIX MARCHING ANTS IN IE
|
||||
* As IE <6 tries to load background images we can uncomment the follwoing hack
|
||||
* to remove that issue, not as pretty - but is anything in IE?
|
||||
* And yes I do know that 'filter' is evil, but it will make it look semi decent in IE
|
||||
*
|
||||
* html .imgCrop_marqueeHoriz,
|
||||
* html .imgCrop_marqueeVert {
|
||||
background: transparent;
|
||||
filter: Invert;
|
||||
}
|
||||
* html .imgCrop_marqueeNorth { border-top: 1px dashed #000; }
|
||||
* html .imgCrop_marqueeEast { border-right: 1px dashed #000; }
|
||||
* html .imgCrop_marqueeSouth { border-bottom: 1px dashed #000; }
|
||||
* html .imgCrop_marqueeWest { border-left: 1px dashed #000; }
|
||||
*/
|
||||
|
||||
.imgCrop_marqueeNorth { top: 0; left: 0; }
|
||||
.imgCrop_marqueeEast { top: 0; right: 0; }
|
||||
.imgCrop_marqueeSouth { bottom: 0px; left: 0; }
|
||||
.imgCrop_marqueeWest { top: 0; left: 0; }
|
||||
|
||||
|
||||
.imgCrop_handle {
|
||||
position: absolute;
|
||||
border: 1px solid #333;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: #FFF;
|
||||
opacity: 0.5;
|
||||
filter:alpha(opacity=50);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
/* fix IE 5 box model */
|
||||
* html .imgCrop_handle {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
wid\th: 6px;
|
||||
hei\ght: 6px;
|
||||
}
|
||||
|
||||
.imgCrop_handleN {
|
||||
top: -3px;
|
||||
left: 0;
|
||||
/* margin-left: 49%; @done_in_js */
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleNE {
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
cursor: ne-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleE {
|
||||
top: 0;
|
||||
right: -3px;
|
||||
/* margin-top: 49%; @done_in_js */
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleSE {
|
||||
right: -3px;
|
||||
bottom: -3px;
|
||||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleS {
|
||||
right: 0;
|
||||
bottom: -3px;
|
||||
/* margin-right: 49%; @done_in_js */
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleSW {
|
||||
left: -3px;
|
||||
bottom: -3px;
|
||||
cursor: sw-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleW {
|
||||
top: 0;
|
||||
left: -3px;
|
||||
/* margin-top: 49%; @done_in_js */
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
.imgCrop_handleNW {
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
cursor: nw-resize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an area to click & drag around on as the default browser behaviour is to let you drag the image
|
||||
*/
|
||||
.imgCrop_dragArea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 200;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.imgCrop_previewWrap {
|
||||
/* width: 200px; @done_in_js */
|
||||
/* height: 200px; @done_in_js */
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.imgCrop_previewWrap img {
|
||||
position: absolute;
|
||||
}
|
@ -1,228 +0,0 @@
|
||||
1.
|
||||
<script type="text/javascript" src="scripts/cropper/lib/prototype.js" language="javascript"></script>
|
||||
2.
|
||||
<script type="text/javascript" src="scripts/cropper/lib/scriptaculous.js?load=builder,dragdrop" language="javascript"></script>
|
||||
3.
|
||||
<script type="text/javascript" src="scripts/cropper/cropper.js" language="javascript"></script>
|
||||
|
||||
Options
|
||||
|
||||
ratioDim obj
|
||||
The pixel dimensions to apply as a restrictive ratio, with properties x & y.
|
||||
minWidth int
|
||||
The minimum width for the select area in pixels.
|
||||
minHeight int
|
||||
The mimimum height for the select area in pixels.
|
||||
maxWidth int
|
||||
The maximum width for the select areas in pixels (if both minWidth & maxWidth set to same the width of the cropper will be fixed)
|
||||
maxHeight int
|
||||
The maximum height for the select areas in pixels (if both minHeight & maxHeight set to same the height of the cropper will be fixed)
|
||||
displayOnInit int
|
||||
Whether to display the select area on initialisation, only used when providing minimum width & height or ratio.
|
||||
onEndCrop func
|
||||
The callback function to provide the crop details to on end of a crop.
|
||||
captureKeys boolean
|
||||
Whether to capture the keys for moving the select area, as these can cause some problems at the moment.
|
||||
onloadCoords obj
|
||||
A coordinates object with properties x1, y1, x2 & y2; for the coordinates of the select area to display onload
|
||||
|
||||
The callback function
|
||||
|
||||
The callback function is a function that allows you to capture the crop co-ordinates when the user finished a crop movement, it is passed two arguments:
|
||||
|
||||
* coords, obj, coordinates object with properties x1, y1, x2 & y2; for the coordinates of the select area.
|
||||
* dimensions, obj, dimensions object with properities width & height; for the dimensions of the select area.
|
||||
|
||||
An example function which outputs the crop values to form fields:
|
||||
Display code as plain text
|
||||
JavaScript:
|
||||
|
||||
1.
|
||||
function onEndCrop( coords, dimensions ) {
|
||||
2.
|
||||
$PR( 'x1' ).value = coords.x1;
|
||||
3.
|
||||
$PR( 'y1' ).value = coords.y1;
|
||||
4.
|
||||
$PR( 'x2' ).value = coords.x2;
|
||||
5.
|
||||
$PR( 'y2' ).value = coords.y2;
|
||||
6.
|
||||
$PR( 'width' ).value = dimensions.width;
|
||||
7.
|
||||
$PR( 'height' ).value = dimensions.height;
|
||||
8.
|
||||
}
|
||||
|
||||
Basic interface
|
||||
|
||||
This basic example will attach the cropper UI to the test image and return crop results to the provided callback function.
|
||||
Display code as plain text
|
||||
HTML:
|
||||
|
||||
1.
|
||||
<img src="test.jpg" alt="Test image" id="testImage" width="500" height="333" />
|
||||
2.
|
||||
|
||||
3.
|
||||
<script type="text/javascript" language="javascript">
|
||||
4.
|
||||
Event.observe( window, 'load', function() {
|
||||
5.
|
||||
new Cropper.Img(
|
||||
6.
|
||||
'testImage',
|
||||
7.
|
||||
{ onEndCrop: onEndCrop }
|
||||
8.
|
||||
);
|
||||
9.
|
||||
} );
|
||||
10.
|
||||
</script>
|
||||
|
||||
Minimum dimensions
|
||||
|
||||
You can apply minimum dimensions to a single axis or both, this example applies minimum dimensions to both axis.
|
||||
Display code as plain text
|
||||
HTML:
|
||||
|
||||
1.
|
||||
<img src="test.jpg" alt="Test image" id="testImage" width="500" height="333" />
|
||||
2.
|
||||
|
||||
3.
|
||||
<script type="text/javascript" language="javascript">
|
||||
4.
|
||||
Event.observe( window, 'load', function() {
|
||||
5.
|
||||
new Cropper.Img(
|
||||
6.
|
||||
'testImage',
|
||||
7.
|
||||
{
|
||||
8.
|
||||
minWidth: 220,
|
||||
9.
|
||||
minHeight: 120,
|
||||
10.
|
||||
onEndCrop: onEndCrop
|
||||
11.
|
||||
}
|
||||
12.
|
||||
);
|
||||
13.
|
||||
} );
|
||||
14.
|
||||
</script>
|
||||
|
||||
Select area ratio
|
||||
|
||||
You can apply a ratio to the selection area, this example applies a 4:3 ratio to the select area.
|
||||
Display code as plain text
|
||||
HTML:
|
||||
|
||||
1.
|
||||
<img src="test.jpg" alt="Test image" id="testImage" width="500" height="333" />
|
||||
2.
|
||||
|
||||
3.
|
||||
<script type="text/javascript" language="javascript">
|
||||
4.
|
||||
Event.observe( window, 'load', function() {
|
||||
5.
|
||||
new Cropper.Img(
|
||||
6.
|
||||
'testImage',
|
||||
7.
|
||||
{
|
||||
8.
|
||||
ratioDim: {
|
||||
9.
|
||||
x: 220,
|
||||
10.
|
||||
y: 165
|
||||
11.
|
||||
},
|
||||
12.
|
||||
displayOnInit: true,
|
||||
13.
|
||||
onEndCrop: onEndCrop
|
||||
14.
|
||||
}
|
||||
15.
|
||||
);
|
||||
16.
|
||||
} );
|
||||
17.
|
||||
</script>
|
||||
|
||||
With crop preview
|
||||
|
||||
You can display a dynamically prouced preview of the resulting crop by using the ImgWithPreview subclass, a preview can only be displayed when we have a fixed size (set via minWidth & minHeight options). Note that the displayOnInit option is not required as this is the default behaviour when displaying a crop preview.
|
||||
Display code as plain text
|
||||
HTML:
|
||||
|
||||
1.
|
||||
<img src="test.jpg" alt="Test image" id="testImage" width="500" height="333" />
|
||||
2.
|
||||
<div id="previewWrap"></div>
|
||||
3.
|
||||
|
||||
4.
|
||||
<script type="text/javascript" language="javascript">
|
||||
5.
|
||||
Event.observe( window, 'load', function() {
|
||||
6.
|
||||
new Cropper.ImgWithPreview(
|
||||
7.
|
||||
'testImage',
|
||||
8.
|
||||
{
|
||||
9.
|
||||
previewWrap: 'previewWrap',
|
||||
10.
|
||||
minWidth: 120,
|
||||
11.
|
||||
minHeight: 120,
|
||||
12.
|
||||
ratioDim: { x: 200, y: 120 },
|
||||
13.
|
||||
onEndCrop: onEndCrop
|
||||
14.
|
||||
}
|
||||
15.
|
||||
);
|
||||
16.
|
||||
} );
|
||||
17.
|
||||
</script>
|
||||
|
||||
Known Issues
|
||||
|
||||
* Safari animated gifs, only one of each will animate, this seems to be a known Safari issue.
|
||||
* After drawing an area and then clicking to start a new drag in IE 5.5 the rendered height appears as the last height until the user drags, this appears to be the related to another IE error (which has been fixed) where IE does not always redraw the select area properly.
|
||||
* Lack of CSS opacity support in Opera before version 9 mean we disable those style rules, if Opera 8 support is important you & you want the overlay to work then you can use the Opera rules in the CSS to apply a black PNG with 50% alpha transparency to replicate the effect.
|
||||
* Styling & borders on image, any CSS styling applied directly to the image itself (floats, borders, padding, margin, etc.) will cause problems with the cropper. The use of a wrapper element to apply these styles to is recommended.
|
||||
* overflow: auto or overflow: scroll on parent will cause cropper to burst out of parent in IE and Opera when applied (maybe Mac browsers too) I'm not sure why yet.
|
||||
|
||||
If you use CakePHP you will notice that including this in your script will break the CSS layout. This is due to the CSS rule
|
||||
|
||||
form div{
|
||||
vertical-align: text-top;
|
||||
margin-left: 1em;
|
||||
margin-bottom:2em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
A simple workaround is to add another rule directly after this like so:
|
||||
|
||||
form div.no_cake, form div.no_cake div {
|
||||
margin:0;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
and then in your code surround the img tag with a div with the class name of no_cake.
|
||||
|
||||
Cheers
|
||||
|
@ -1,568 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2006, David Spurr (http://www.defusion.org.uk/)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the David Spurr nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://www.opensource.org/licenses/bsd-license.php
|
||||
*
|
||||
* See scriptaculous.js for full scriptaculous licence
|
||||
*
|
||||
* Modified 2013/06/01 Zach P to change $() to $PR() for eliminating conflicts with jQuery
|
||||
*/
|
||||
|
||||
var CropDraggable=Class.create();
|
||||
Object.extend(Object.extend(CropDraggable.prototype,Draggable.prototype),{initialize:function(_1){
|
||||
this.options=Object.extend({drawMethod:function(){
|
||||
}},arguments[1]||{});
|
||||
this.element=$PR(_1);
|
||||
this.handle=this.element;
|
||||
this.delta=this.currentDelta();
|
||||
this.dragging=false;
|
||||
this.eventMouseDown=this.initDrag.bindAsEventListener(this);
|
||||
Event.observe(this.handle,"mousedown",this.eventMouseDown);
|
||||
Draggables.register(this);
|
||||
},draw:function(_2){
|
||||
var _3=Position.cumulativeOffset(this.element);
|
||||
var d=this.currentDelta();
|
||||
_3[0]-=d[0];
|
||||
_3[1]-=d[1];
|
||||
var p=[0,1].map(function(i){
|
||||
return (_2[i]-_3[i]-this.offset[i]);
|
||||
}.bind(this));
|
||||
this.options.drawMethod(p);
|
||||
}});
|
||||
var Cropper={};
|
||||
Cropper.Img=Class.create();
|
||||
Cropper.Img.prototype={initialize:function(_7,_8){
|
||||
this.options=Object.extend({ratioDim:{x:0,y:0},minWidth:0,minHeight:0,displayOnInit:false,onEndCrop:Prototype.emptyFunction,captureKeys:true,onloadCoords:null,maxWidth:0,maxHeight:0},_8||{});
|
||||
this.img=$PR(_7);
|
||||
this.clickCoords={x:0,y:0};
|
||||
this.dragging=false;
|
||||
this.resizing=false;
|
||||
this.isWebKit=/Konqueror|Safari|KHTML/.test(navigator.userAgent);
|
||||
this.isIE=/MSIE/.test(navigator.userAgent);
|
||||
this.isOpera8=/Opera\s[1-8]/.test(navigator.userAgent);
|
||||
this.ratioX=0;
|
||||
this.ratioY=0;
|
||||
this.attached=false;
|
||||
this.fixedWidth=(this.options.maxWidth>0&&(this.options.minWidth>=this.options.maxWidth));
|
||||
this.fixedHeight=(this.options.maxHeight>0&&(this.options.minHeight>=this.options.maxHeight));
|
||||
if(typeof this.img=="undefined"){
|
||||
return;
|
||||
}
|
||||
$A(document.getElementsByTagName("script")).each(function(s){
|
||||
if(s.src.match(/cropper\.js/)){
|
||||
var _a=s.src.replace(/cropper\.js(.*)?/,"");
|
||||
var _b=document.createElement("link");
|
||||
_b.rel="stylesheet";
|
||||
_b.type="text/css";
|
||||
_b.href=_a+"cropper.css";
|
||||
_b.media="screen";
|
||||
document.getElementsByTagName("head")[0].appendChild(_b);
|
||||
}
|
||||
});
|
||||
if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0){
|
||||
var _c=this.getGCD(this.options.ratioDim.x,this.options.ratioDim.y);
|
||||
this.ratioX=this.options.ratioDim.x/_c;
|
||||
this.ratioY=this.options.ratioDim.y/_c;
|
||||
}
|
||||
this.subInitialize();
|
||||
if(this.img.complete||this.isWebKit){
|
||||
this.onLoad();
|
||||
}else{
|
||||
Event.observe(this.img,"load",this.onLoad.bindAsEventListener(this));
|
||||
}
|
||||
},getGCD:function(a,b){
|
||||
if(b==0){
|
||||
return a;
|
||||
}
|
||||
return this.getGCD(b,a%b);
|
||||
},onLoad:function(){
|
||||
var _f="imgCrop_";
|
||||
var _10=this.img.parentNode;
|
||||
var _11="";
|
||||
if(this.isOpera8){
|
||||
_11=" opera8";
|
||||
}
|
||||
this.imgWrap=Builder.node("div",{"class":_f+"wrap"+_11});
|
||||
this.north=Builder.node("div",{"class":_f+"overlay "+_f+"north"},[Builder.node("span")]);
|
||||
this.east=Builder.node("div",{"class":_f+"overlay "+_f+"east"},[Builder.node("span")]);
|
||||
this.south=Builder.node("div",{"class":_f+"overlay "+_f+"south"},[Builder.node("span")]);
|
||||
this.west=Builder.node("div",{"class":_f+"overlay "+_f+"west"},[Builder.node("span")]);
|
||||
var _12=[this.north,this.east,this.south,this.west];
|
||||
this.dragArea=Builder.node("div",{"class":_f+"dragArea"},_12);
|
||||
this.handleN=Builder.node("div",{"class":_f+"handle "+_f+"handleN"});
|
||||
this.handleNE=Builder.node("div",{"class":_f+"handle "+_f+"handleNE"});
|
||||
this.handleE=Builder.node("div",{"class":_f+"handle "+_f+"handleE"});
|
||||
this.handleSE=Builder.node("div",{"class":_f+"handle "+_f+"handleSE"});
|
||||
this.handleS=Builder.node("div",{"class":_f+"handle "+_f+"handleS"});
|
||||
this.handleSW=Builder.node("div",{"class":_f+"handle "+_f+"handleSW"});
|
||||
this.handleW=Builder.node("div",{"class":_f+"handle "+_f+"handleW"});
|
||||
this.handleNW=Builder.node("div",{"class":_f+"handle "+_f+"handleNW"});
|
||||
this.selArea=Builder.node("div",{"class":_f+"selArea"},[Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeNorth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeEast"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeSouth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeWest"},[Builder.node("span")]),this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW,Builder.node("div",{"class":_f+"clickArea"})]);
|
||||
this.imgWrap.appendChild(this.img);
|
||||
this.imgWrap.appendChild(this.dragArea);
|
||||
this.dragArea.appendChild(this.selArea);
|
||||
this.dragArea.appendChild(Builder.node("div",{"class":_f+"clickArea"}));
|
||||
_10.appendChild(this.imgWrap);
|
||||
this.startDragBind=this.startDrag.bindAsEventListener(this);
|
||||
Event.observe(this.dragArea,"mousedown",this.startDragBind);
|
||||
this.onDragBind=this.onDrag.bindAsEventListener(this);
|
||||
Event.observe(document,"mousemove",this.onDragBind);
|
||||
this.endCropBind=this.endCrop.bindAsEventListener(this);
|
||||
Event.observe(document,"mouseup",this.endCropBind);
|
||||
this.resizeBind=this.startResize.bindAsEventListener(this);
|
||||
this.handles=[this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW];
|
||||
this.registerHandles(true);
|
||||
if(this.options.captureKeys){
|
||||
this.keysBind=this.handleKeys.bindAsEventListener(this);
|
||||
Event.observe(document,"keypress",this.keysBind);
|
||||
}
|
||||
new CropDraggable(this.selArea,{drawMethod:this.moveArea.bindAsEventListener(this)});
|
||||
this.setParams();
|
||||
},registerHandles:function(_13){
|
||||
for(var i=0;i<this.handles.length;i++){
|
||||
var _15=$PR(this.handles[i]);
|
||||
if(_13){
|
||||
var _16=false;
|
||||
if(this.fixedWidth&&this.fixedHeight){
|
||||
_16=true;
|
||||
}else{
|
||||
if(this.fixedWidth||this.fixedHeight){
|
||||
var _17=_15.className.match(/([S|N][E|W])$/);
|
||||
var _18=_15.className.match(/(E|W)$/);
|
||||
var _19=_15.className.match(/(N|S)$/);
|
||||
if(_17){
|
||||
_16=true;
|
||||
}else{
|
||||
if(this.fixedWidth&&_18){
|
||||
_16=true;
|
||||
}else{
|
||||
if(this.fixedHeight&&_19){
|
||||
_16=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_16){
|
||||
_15.hide();
|
||||
}else{
|
||||
Event.observe(_15,"mousedown",this.resizeBind);
|
||||
}
|
||||
}else{
|
||||
_15.show();
|
||||
Event.stopObserving(_15,"mousedown",this.resizeBind);
|
||||
}
|
||||
}
|
||||
},setParams:function(){
|
||||
this.imgW=this.img.width;
|
||||
this.imgH=this.img.height;
|
||||
$PR(this.north).setStyle({height:0});
|
||||
$PR(this.east).setStyle({width:0,height:0});
|
||||
$PR(this.south).setStyle({height:0});
|
||||
$PR(this.west).setStyle({width:0,height:0});
|
||||
$PR(this.imgWrap).setStyle({"width":this.imgW+"px","height":this.imgH+"px"});
|
||||
$PR(this.selArea).hide();
|
||||
var _1a={x1:0,y1:0,x2:0,y2:0};
|
||||
var _1b=false;
|
||||
if(this.options.onloadCoords!=null){
|
||||
_1a=this.cloneCoords(this.options.onloadCoords);
|
||||
_1b=true;
|
||||
}else{
|
||||
if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0){
|
||||
_1a.x1=Math.ceil((this.imgW-this.options.ratioDim.x)/2);
|
||||
_1a.y1=Math.ceil((this.imgH-this.options.ratioDim.y)/2);
|
||||
_1a.x2=_1a.x1+this.options.ratioDim.x;
|
||||
_1a.y2=_1a.y1+this.options.ratioDim.y;
|
||||
_1b=true;
|
||||
}
|
||||
}
|
||||
this.setAreaCoords(_1a,false,false,1);
|
||||
if(this.options.displayOnInit&&_1b){
|
||||
this.selArea.show();
|
||||
this.drawArea();
|
||||
this.endCrop();
|
||||
}
|
||||
this.attached=true;
|
||||
},remove:function(){
|
||||
if(this.attached){
|
||||
this.attached=false;
|
||||
this.imgWrap.parentNode.insertBefore(this.img,this.imgWrap);
|
||||
this.imgWrap.parentNode.removeChild(this.imgWrap);
|
||||
Event.stopObserving(this.dragArea,"mousedown",this.startDragBind);
|
||||
Event.stopObserving(document,"mousemove",this.onDragBind);
|
||||
Event.stopObserving(document,"mouseup",this.endCropBind);
|
||||
this.registerHandles(false);
|
||||
if(this.options.captureKeys){
|
||||
Event.stopObserving(document,"keypress",this.keysBind);
|
||||
}
|
||||
}
|
||||
},reset:function(){
|
||||
if(!this.attached){
|
||||
this.onLoad();
|
||||
}else{
|
||||
this.setParams();
|
||||
}
|
||||
this.endCrop();
|
||||
},handleKeys:function(e){
|
||||
var dir={x:0,y:0};
|
||||
if(!this.dragging){
|
||||
switch(e.keyCode){
|
||||
case (37):
|
||||
dir.x=-1;
|
||||
break;
|
||||
case (38):
|
||||
dir.y=-1;
|
||||
break;
|
||||
case (39):
|
||||
dir.x=1;
|
||||
break;
|
||||
case (40):
|
||||
dir.y=1;
|
||||
break;
|
||||
}
|
||||
if(dir.x!=0||dir.y!=0){
|
||||
if(e.shiftKey){
|
||||
dir.x*=10;
|
||||
dir.y*=10;
|
||||
}
|
||||
this.moveArea([this.areaCoords.x1+dir.x,this.areaCoords.y1+dir.y]);
|
||||
Event.stop(e);
|
||||
}
|
||||
}
|
||||
},calcW:function(){
|
||||
return (this.areaCoords.x2-this.areaCoords.x1);
|
||||
},calcH:function(){
|
||||
return (this.areaCoords.y2-this.areaCoords.y1);
|
||||
},moveArea:function(_1e){
|
||||
this.setAreaCoords({x1:_1e[0],y1:_1e[1],x2:_1e[0]+this.calcW(),y2:_1e[1]+this.calcH()},true,false);
|
||||
this.drawArea();
|
||||
},cloneCoords:function(_1f){
|
||||
return {x1:_1f.x1,y1:_1f.y1,x2:_1f.x2,y2:_1f.y2};
|
||||
},setAreaCoords:function(_20,_21,_22,_23,_24){
|
||||
if(_21){
|
||||
var _25=_20.x2-_20.x1;
|
||||
var _26=_20.y2-_20.y1;
|
||||
if(_20.x1<0){
|
||||
_20.x1=0;
|
||||
_20.x2=_25;
|
||||
}
|
||||
if(_20.y1<0){
|
||||
_20.y1=0;
|
||||
_20.y2=_26;
|
||||
}
|
||||
if(_20.x2>this.imgW){
|
||||
_20.x2=this.imgW;
|
||||
_20.x1=this.imgW-_25;
|
||||
}
|
||||
if(_20.y2>this.imgH){
|
||||
_20.y2=this.imgH;
|
||||
_20.y1=this.imgH-_26;
|
||||
}
|
||||
}else{
|
||||
if(_20.x1<0){
|
||||
_20.x1=0;
|
||||
}
|
||||
if(_20.y1<0){
|
||||
_20.y1=0;
|
||||
}
|
||||
if(_20.x2>this.imgW){
|
||||
_20.x2=this.imgW;
|
||||
}
|
||||
if(_20.y2>this.imgH){
|
||||
_20.y2=this.imgH;
|
||||
}
|
||||
if(_23!=null){
|
||||
if(this.ratioX>0){
|
||||
this.applyRatio(_20,{x:this.ratioX,y:this.ratioY},_23,_24);
|
||||
}else{
|
||||
if(_22){
|
||||
this.applyRatio(_20,{x:1,y:1},_23,_24);
|
||||
}
|
||||
}
|
||||
var _27=[this.options.minWidth,this.options.minHeight];
|
||||
var _28=[this.options.maxWidth,this.options.maxHeight];
|
||||
if(_27[0]>0||_27[1]>0||_28[0]>0||_28[1]>0){
|
||||
var _29={a1:_20.x1,a2:_20.x2};
|
||||
var _2a={a1:_20.y1,a2:_20.y2};
|
||||
var _2b={min:0,max:this.imgW};
|
||||
var _2c={min:0,max:this.imgH};
|
||||
if((_27[0]!=0||_27[1]!=0)&&_22){
|
||||
if(_27[0]>0){
|
||||
_27[1]=_27[0];
|
||||
}else{
|
||||
if(_27[1]>0){
|
||||
_27[0]=_27[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if((_28[0]!=0||_28[0]!=0)&&_22){
|
||||
if(_28[0]>0&&_28[0]<=_28[1]){
|
||||
_28[1]=_28[0];
|
||||
}else{
|
||||
if(_28[1]>0&&_28[1]<=_28[0]){
|
||||
_28[0]=_28[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_27[0]>0){
|
||||
this.applyDimRestriction(_29,_27[0],_23.x,_2b,"min");
|
||||
}
|
||||
if(_27[1]>1){
|
||||
this.applyDimRestriction(_2a,_27[1],_23.y,_2c,"min");
|
||||
}
|
||||
if(_28[0]>0){
|
||||
this.applyDimRestriction(_29,_28[0],_23.x,_2b,"max");
|
||||
}
|
||||
if(_28[1]>1){
|
||||
this.applyDimRestriction(_2a,_28[1],_23.y,_2c,"max");
|
||||
}
|
||||
_20={x1:_29.a1,y1:_2a.a1,x2:_29.a2,y2:_2a.a2};
|
||||
}
|
||||
}
|
||||
}
|
||||
this.areaCoords=_20;
|
||||
},applyDimRestriction:function(_2d,val,_2f,_30,_31){
|
||||
var _32;
|
||||
if(_31=="min"){
|
||||
_32=((_2d.a2-_2d.a1)<val);
|
||||
}else{
|
||||
_32=((_2d.a2-_2d.a1)>val);
|
||||
}
|
||||
if(_32){
|
||||
if(_2f==1){
|
||||
_2d.a2=_2d.a1+val;
|
||||
}else{
|
||||
_2d.a1=_2d.a2-val;
|
||||
}
|
||||
if(_2d.a1<_30.min){
|
||||
_2d.a1=_30.min;
|
||||
_2d.a2=val;
|
||||
}else{
|
||||
if(_2d.a2>_30.max){
|
||||
_2d.a1=_30.max-val;
|
||||
_2d.a2=_30.max;
|
||||
}
|
||||
}
|
||||
}
|
||||
},applyRatio:function(_33,_34,_35,_36){
|
||||
var _37;
|
||||
if(_36=="N"||_36=="S"){
|
||||
_37=this.applyRatioToAxis({a1:_33.y1,b1:_33.x1,a2:_33.y2,b2:_33.x2},{a:_34.y,b:_34.x},{a:_35.y,b:_35.x},{min:0,max:this.imgW});
|
||||
_33.x1=_37.b1;
|
||||
_33.y1=_37.a1;
|
||||
_33.x2=_37.b2;
|
||||
_33.y2=_37.a2;
|
||||
}else{
|
||||
_37=this.applyRatioToAxis({a1:_33.x1,b1:_33.y1,a2:_33.x2,b2:_33.y2},{a:_34.x,b:_34.y},{a:_35.x,b:_35.y},{min:0,max:this.imgH});
|
||||
_33.x1=_37.a1;
|
||||
_33.y1=_37.b1;
|
||||
_33.x2=_37.a2;
|
||||
_33.y2=_37.b2;
|
||||
}
|
||||
},applyRatioToAxis:function(_38,_39,_3a,_3b){
|
||||
var _3c=Object.extend(_38,{});
|
||||
var _3d=_3c.a2-_3c.a1;
|
||||
var _3e=Math.floor(_3d*_39.b/_39.a);
|
||||
var _3f;
|
||||
var _40;
|
||||
var _41=null;
|
||||
if(_3a.b==1){
|
||||
_3f=_3c.b1+_3e;
|
||||
if(_3f>_3b.max){
|
||||
_3f=_3b.max;
|
||||
_41=_3f-_3c.b1;
|
||||
}
|
||||
_3c.b2=_3f;
|
||||
}else{
|
||||
_3f=_3c.b2-_3e;
|
||||
if(_3f<_3b.min){
|
||||
_3f=_3b.min;
|
||||
_41=_3f+_3c.b2;
|
||||
}
|
||||
_3c.b1=_3f;
|
||||
}
|
||||
if(_41!=null){
|
||||
_40=Math.floor(_41*_39.a/_39.b);
|
||||
if(_3a.a==1){
|
||||
_3c.a2=_3c.a1+_40;
|
||||
}else{
|
||||
_3c.a1=_3c.a1=_3c.a2-_40;
|
||||
}
|
||||
}
|
||||
return _3c;
|
||||
},drawArea:function(){
|
||||
var _42=this.calcW();
|
||||
var _43=this.calcH();
|
||||
var px="px";
|
||||
var _45=[this.areaCoords.x1+px,this.areaCoords.y1+px,_42+px,_43+px,this.areaCoords.x2+px,this.areaCoords.y2+px,(this.img.width-this.areaCoords.x2)+px,(this.img.height-this.areaCoords.y2)+px];
|
||||
var _46=this.selArea.style;
|
||||
_46.left=_45[0];
|
||||
_46.top=_45[1];
|
||||
_46.width=_45[2];
|
||||
_46.height=_45[3];
|
||||
var _47=Math.ceil((_42-6)/2)+px;
|
||||
var _48=Math.ceil((_43-6)/2)+px;
|
||||
this.handleN.style.left=_47;
|
||||
this.handleE.style.top=_48;
|
||||
this.handleS.style.left=_47;
|
||||
this.handleW.style.top=_48;
|
||||
this.north.style.height=_45[1];
|
||||
var _49=this.east.style;
|
||||
_49.top=_45[1];
|
||||
_49.height=_45[3];
|
||||
_49.left=_45[4];
|
||||
_49.width=_45[6];
|
||||
var _4a=this.south.style;
|
||||
_4a.top=_45[5];
|
||||
_4a.height=_45[7];
|
||||
var _4b=this.west.style;
|
||||
_4b.top=_45[1];
|
||||
_4b.height=_45[3];
|
||||
_4b.width=_45[0];
|
||||
this.subDrawArea();
|
||||
this.forceReRender();
|
||||
},forceReRender:function(){
|
||||
if(this.isIE||this.isWebKit){
|
||||
var n=document.createTextNode(" ");
|
||||
var d,el,fixEL,i;
|
||||
if(this.isIE){
|
||||
fixEl=this.selArea;
|
||||
}else{
|
||||
if(this.isWebKit){
|
||||
fixEl=document.getElementsByClassName("imgCrop_marqueeSouth",this.imgWrap)[0];
|
||||
d=Builder.node("div","");
|
||||
d.style.visibility="hidden";
|
||||
var _4e=["SE","S","SW"];
|
||||
for(i=0;i<_4e.length;i++){
|
||||
el=document.getElementsByClassName("imgCrop_handle"+_4e[i],this.selArea)[0];
|
||||
if(el.childNodes.length){
|
||||
el.removeChild(el.childNodes[0]);
|
||||
}
|
||||
el.appendChild(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
fixEl.appendChild(n);
|
||||
fixEl.removeChild(n);
|
||||
}
|
||||
},startResize:function(e){
|
||||
this.startCoords=this.cloneCoords(this.areaCoords);
|
||||
this.resizing=true;
|
||||
this.resizeHandle=Event.element(e).classNames().toString().replace(/([^N|NE|E|SE|S|SW|W|NW])+/,"");
|
||||
Event.stop(e);
|
||||
},startDrag:function(e){
|
||||
this.selArea.show();
|
||||
this.clickCoords=this.getCurPos(e);
|
||||
this.setAreaCoords({x1:this.clickCoords.x,y1:this.clickCoords.y,x2:this.clickCoords.x,y2:this.clickCoords.y},false,false,null);
|
||||
this.dragging=true;
|
||||
this.onDrag(e);
|
||||
Event.stop(e);
|
||||
},getCurPos:function(e){
|
||||
var el=this.imgWrap,wrapOffsets=Position.cumulativeOffset(el);
|
||||
while(el.nodeName!="BODY"){
|
||||
wrapOffsets[1]-=el.scrollTop||0;
|
||||
wrapOffsets[0]-=el.scrollLeft||0;
|
||||
el=el.parentNode;
|
||||
}
|
||||
return curPos={x:Event.pointerX(e)-wrapOffsets[0],y:Event.pointerY(e)-wrapOffsets[1]};
|
||||
},onDrag:function(e){
|
||||
if(this.dragging||this.resizing){
|
||||
var _54=null;
|
||||
var _55=this.getCurPos(e);
|
||||
var _56=this.cloneCoords(this.areaCoords);
|
||||
var _57={x:1,y:1};
|
||||
if(this.dragging){
|
||||
if(_55.x<this.clickCoords.x){
|
||||
_57.x=-1;
|
||||
}
|
||||
if(_55.y<this.clickCoords.y){
|
||||
_57.y=-1;
|
||||
}
|
||||
this.transformCoords(_55.x,this.clickCoords.x,_56,"x");
|
||||
this.transformCoords(_55.y,this.clickCoords.y,_56,"y");
|
||||
}else{
|
||||
if(this.resizing){
|
||||
_54=this.resizeHandle;
|
||||
if(_54.match(/E/)){
|
||||
this.transformCoords(_55.x,this.startCoords.x1,_56,"x");
|
||||
if(_55.x<this.startCoords.x1){
|
||||
_57.x=-1;
|
||||
}
|
||||
}else{
|
||||
if(_54.match(/W/)){
|
||||
this.transformCoords(_55.x,this.startCoords.x2,_56,"x");
|
||||
if(_55.x<this.startCoords.x2){
|
||||
_57.x=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_54.match(/N/)){
|
||||
this.transformCoords(_55.y,this.startCoords.y2,_56,"y");
|
||||
if(_55.y<this.startCoords.y2){
|
||||
_57.y=-1;
|
||||
}
|
||||
}else{
|
||||
if(_54.match(/S/)){
|
||||
this.transformCoords(_55.y,this.startCoords.y1,_56,"y");
|
||||
if(_55.y<this.startCoords.y1){
|
||||
_57.y=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setAreaCoords(_56,false,e.shiftKey,_57,_54);
|
||||
this.drawArea();
|
||||
Event.stop(e);
|
||||
}
|
||||
},transformCoords:function(_58,_59,_5a,_5b){
|
||||
var _5c=[_58,_59];
|
||||
if(_58>_59){
|
||||
_5c.reverse();
|
||||
}
|
||||
_5a[_5b+"1"]=_5c[0];
|
||||
_5a[_5b+"2"]=_5c[1];
|
||||
},endCrop:function(){
|
||||
this.dragging=false;
|
||||
this.resizing=false;
|
||||
this.options.onEndCrop(this.areaCoords,{width:this.calcW(),height:this.calcH()});
|
||||
},subInitialize:function(){
|
||||
},subDrawArea:function(){
|
||||
}};
|
||||
Cropper.ImgWithPreview=Class.create();
|
||||
Object.extend(Object.extend(Cropper.ImgWithPreview.prototype,Cropper.Img.prototype),{subInitialize:function(){
|
||||
this.hasPreviewImg=false;
|
||||
if(typeof (this.options.previewWrap)!="undefined"&&this.options.minWidth>0&&this.options.minHeight>0){
|
||||
this.previewWrap=$PR(this.options.previewWrap);
|
||||
this.previewImg=this.img.cloneNode(false);
|
||||
this.previewImg.id="imgCrop_"+this.previewImg.id;
|
||||
this.options.displayOnInit=true;
|
||||
this.hasPreviewImg=true;
|
||||
this.previewWrap.addClassName("imgCrop_previewWrap");
|
||||
this.previewWrap.setStyle({width:this.options.minWidth+"px",height:this.options.minHeight+"px"});
|
||||
this.previewWrap.appendChild(this.previewImg);
|
||||
}
|
||||
},subDrawArea:function(){
|
||||
if(this.hasPreviewImg){
|
||||
var _5d=this.calcW();
|
||||
var _5e=this.calcH();
|
||||
var _5f={x:this.imgW/_5d,y:this.imgH/_5e};
|
||||
var _60={x:_5d/this.options.minWidth,y:_5e/this.options.minHeight};
|
||||
var _61={w:Math.ceil(this.options.minWidth*_5f.x)+"px",h:Math.ceil(this.options.minHeight*_5f.y)+"px",x:"-"+Math.ceil(this.areaCoords.x1/_60.x)+"px",y:"-"+Math.ceil(this.areaCoords.y1/_60.y)+"px"};
|
||||
var _62=this.previewImg.style;
|
||||
_62.width=_61.w;
|
||||
_62.height=_61.h;
|
||||
_62.left=_61.x;
|
||||
_62.top=_61.y;
|
||||
}
|
||||
}});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,101 +0,0 @@
|
||||
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
||||
//
|
||||
// See scriptaculous.js for full license.
|
||||
|
||||
var Builder = {
|
||||
NODEMAP: {
|
||||
AREA: 'map',
|
||||
CAPTION: 'table',
|
||||
COL: 'table',
|
||||
COLGROUP: 'table',
|
||||
LEGEND: 'fieldset',
|
||||
OPTGROUP: 'select',
|
||||
OPTION: 'select',
|
||||
PARAM: 'object',
|
||||
TBODY: 'table',
|
||||
TD: 'table',
|
||||
TFOOT: 'table',
|
||||
TH: 'table',
|
||||
THEAD: 'table',
|
||||
TR: 'table'
|
||||
},
|
||||
// note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
|
||||
// due to a Firefox bug
|
||||
node: function(elementName) {
|
||||
elementName = elementName.toUpperCase();
|
||||
|
||||
// try innerHTML approach
|
||||
var parentTag = this.NODEMAP[elementName] || 'div';
|
||||
var parentElement = document.createElement(parentTag);
|
||||
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
|
||||
parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
|
||||
} catch(e) {}
|
||||
var element = parentElement.firstChild || null;
|
||||
|
||||
// see if browser added wrapping tags
|
||||
if(element && (element.tagName != elementName))
|
||||
element = element.getElementsByTagName(elementName)[0];
|
||||
|
||||
// fallback to createElement approach
|
||||
if(!element) element = document.createElement(elementName);
|
||||
|
||||
// abort if nothing could be created
|
||||
if(!element) return;
|
||||
|
||||
// attributes (or text)
|
||||
if(arguments[1])
|
||||
if(this._isStringOrNumber(arguments[1]) ||
|
||||
(arguments[1] instanceof Array)) {
|
||||
this._children(element, arguments[1]);
|
||||
} else {
|
||||
var attrs = this._attributes(arguments[1]);
|
||||
if(attrs.length) {
|
||||
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
|
||||
parentElement.innerHTML = "<" +elementName + " " +
|
||||
attrs + "></" + elementName + ">";
|
||||
} catch(e) {}
|
||||
element = parentElement.firstChild || null;
|
||||
// workaround firefox 1.0.X bug
|
||||
if(!element) {
|
||||
element = document.createElement(elementName);
|
||||
for(attr in arguments[1])
|
||||
element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
|
||||
}
|
||||
if(element.tagName != elementName)
|
||||
element = parentElement.getElementsByTagName(elementName)[0];
|
||||
}
|
||||
}
|
||||
|
||||
// text, or array of children
|
||||
if(arguments[2])
|
||||
this._children(element, arguments[2]);
|
||||
|
||||
return element;
|
||||
},
|
||||
_text: function(text) {
|
||||
return document.createTextNode(text);
|
||||
},
|
||||
_attributes: function(attributes) {
|
||||
var attrs = [];
|
||||
for(attribute in attributes)
|
||||
attrs.push((attribute=='className' ? 'class' : attribute) +
|
||||
'="' + attributes[attribute].toString().escapeHTML() + '"');
|
||||
return attrs.join(" ");
|
||||
},
|
||||
_children: function(element, children) {
|
||||
if(typeof children=='object') { // array can hold nodes and text
|
||||
children.flatten().each( function(e) {
|
||||
if(typeof e=='object')
|
||||
element.appendChild(e)
|
||||
else
|
||||
if(Builder._isStringOrNumber(e))
|
||||
element.appendChild(Builder._text(e));
|
||||
});
|
||||
} else
|
||||
if(Builder._isStringOrNumber(children))
|
||||
element.appendChild(Builder._text(children));
|
||||
},
|
||||
_isStringOrNumber: function(param) {
|
||||
return(typeof param=='string' || typeof param=='number');
|
||||
}
|
||||
}
|
@ -1,815 +0,0 @@
|
||||
// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
|
||||
// (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
|
||||
// (c) 2005 Jon Tirsen (http://www.tirsen.com)
|
||||
// Contributors:
|
||||
// Richard Livsey
|
||||
// Rahul Bhargava
|
||||
// Rob Wills
|
||||
//
|
||||
// See scriptaculous.js for full license.
|
||||
|
||||
// Autocompleter.Base handles all the autocompletion functionality
|
||||
// that's independent of the data source for autocompletion. This
|
||||
// includes drawing the autocompletion menu, observing keyboard
|
||||
// and mouse events, and similar.
|
||||
//
|
||||
// Specific autocompleters need to provide, at the very least,
|
||||
// a getUpdatedChoices function that will be invoked every time
|
||||
// the text inside the monitored textbox changes. This method
|
||||
// should get the text for which to provide autocompletion by
|
||||
// invoking this.getToken(), NOT by directly accessing
|
||||
// this.element.value. This is to allow incremental tokenized
|
||||
// autocompletion. Specific auto-completion logic (AJAX, etc)
|
||||
// belongs in getUpdatedChoices.
|
||||
//
|
||||
// Tokenized incremental autocompletion is enabled automatically
|
||||
// when an autocompleter is instantiated with the 'tokens' option
|
||||
// in the options parameter, e.g.:
|
||||
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
|
||||
// will incrementally autocomplete with a comma as the token.
|
||||
// Additionally, ',' in the above example can be replaced with
|
||||
// a token array, e.g. { tokens: [',', '\n'] } which
|
||||
// enables autocompletion on multiple tokens. This is most
|
||||
// useful when one of the tokens is \n (a newline), as it
|
||||
// allows smart autocompletion after linebreaks.
|
||||
|
||||
var Autocompleter = {}
|
||||
Autocompleter.Base = function() {};
|
||||
Autocompleter.Base.prototype = {
|
||||
baseInitialize: function(element, update, options) {
|
||||
this.element = $PR(element);
|
||||
this.update = $PR(update);
|
||||
this.hasFocus = false;
|
||||
this.changed = false;
|
||||
this.active = false;
|
||||
this.index = 0;
|
||||
this.entryCount = 0;
|
||||
|
||||
if (this.setOptions)
|
||||
this.setOptions(options);
|
||||
else
|
||||
this.options = options || {};
|
||||
|
||||
this.options.paramName = this.options.paramName || this.element.name;
|
||||
this.options.tokens = this.options.tokens || [];
|
||||
this.options.frequency = this.options.frequency || 0.4;
|
||||
this.options.minChars = this.options.minChars || 1;
|
||||
this.options.onShow = this.options.onShow ||
|
||||
function(element, update){
|
||||
if(!update.style.position || update.style.position=='absolute') {
|
||||
update.style.position = 'absolute';
|
||||
Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
|
||||
}
|
||||
Effect.Appear(update,{duration:0.15});
|
||||
};
|
||||
this.options.onHide = this.options.onHide ||
|
||||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
|
||||
|
||||
if (typeof(this.options.tokens) == 'string')
|
||||
this.options.tokens = new Array(this.options.tokens);
|
||||
|
||||
this.observer = null;
|
||||
|
||||
this.element.setAttribute('autocomplete','off');
|
||||
|
||||
Element.hide(this.update);
|
||||
|
||||
Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
|
||||
Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
|
||||
if(!this.iefix &&
|
||||
(navigator.appVersion.indexOf('MSIE')>0) &&
|
||||
(navigator.userAgent.indexOf('Opera')<0) &&
|
||||
(Element.getStyle(this.update, 'position')=='absolute')) {
|
||||
new Insertion.After(this.update,
|
||||
'<iframe id="' + this.update.id + '_iefix" '+
|
||||
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
|
||||
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
|
||||
this.iefix = $PR(this.update.id+'_iefix');
|
||||
}
|
||||
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
|
||||
},
|
||||
|
||||
fixIEOverlapping: function() {
|
||||
Position.clone(this.update, this.iefix);
|
||||
this.iefix.style.zIndex = 1;
|
||||
this.update.style.zIndex = 2;
|
||||
Element.show(this.iefix);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.stopIndicator();
|
||||
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
|
||||
if(this.iefix) Element.hide(this.iefix);
|
||||
},
|
||||
|
||||
startIndicator: function() {
|
||||
if(this.options.indicator) Element.show(this.options.indicator);
|
||||
},
|
||||
|
||||
stopIndicator: function() {
|
||||
if(this.options.indicator) Element.hide(this.options.indicator);
|
||||
},
|
||||
|
||||
onKeyPress: function(event) {
|
||||
if(this.active)
|
||||
switch(event.keyCode) {
|
||||
case Event.KEY_TAB:
|
||||
case Event.KEY_RETURN:
|
||||
this.selectEntry();
|
||||
Event.stop(event);
|
||||
case Event.KEY_ESC:
|
||||
this.hide();
|
||||
this.active = false;
|
||||
Event.stop(event);
|
||||
return;
|
||||
case Event.KEY_LEFT:
|
||||
case Event.KEY_RIGHT:
|
||||
return;
|
||||
case Event.KEY_UP:
|
||||
this.markPrevious();
|
||||
this.render();
|
||||
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
|
||||
return;
|
||||
case Event.KEY_DOWN:
|
||||
this.markNext();
|
||||
this.render();
|
||||
if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
|
||||
return;
|
||||
}
|
||||
else
|
||||
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
|
||||
(navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
|
||||
|
||||
this.changed = true;
|
||||
this.hasFocus = true;
|
||||
|
||||
if(this.observer) clearTimeout(this.observer);
|
||||
this.observer =
|
||||
setTimeout(this.onObserverEvent.bind(this), |