From 34204ca580baad05a2ac443796b963c5709f124c Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Thu, 29 Mar 2018 17:57:06 +0200 Subject: [PATCH] update javascript cropper library --- composer.json | 34 +- composer.lock | 115 +- view/global.css | 4 + view/js/cropper/cropper.css | 182 -- view/js/cropper/cropper.html | 228 -- view/js/cropper/cropper.js | 568 ----- view/js/cropper/cropper.uncompressed.js | 1333 ----------- view/js/cropper/lib/builder.js | 101 - view/js/cropper/lib/controls.js | 815 ------- view/js/cropper/lib/dragdrop.js | 915 -------- view/js/cropper/lib/effects.js | 958 -------- view/js/cropper/lib/prototype.js | 2006 ----------------- view/js/cropper/lib/scriptaculous.js | 47 - view/js/cropper/lib/slider.js | 283 --- view/js/cropper/lib/unittest.js | 383 ---- view/js/cropper/licence.txt | 12 - view/js/cropper/marqueeHoriz.gif | Bin 1125 -> 0 bytes view/js/cropper/marqueeVert.gif | Bin 1141 -> 0 bytes view/js/cropper/tests/castle.jpg | Bin 34429 -> 0 bytes view/js/cropper/tests/castleMed.jpg | Bin 50584 -> 0 bytes view/js/cropper/tests/example-Basic.htm | 106 - .../js/cropper/tests/example-CSS-Absolute.htm | 162 -- view/js/cropper/tests/example-CSS-Float.htm | 124 - .../js/cropper/tests/example-CSS-Relative.htm | 116 - .../js/cropper/tests/example-CoordsOnLoad.htm | 108 - .../tests/example-CoordsOnLoadWithRatio.htm | 109 - view/js/cropper/tests/example-Dimensions.htm | 225 -- .../js/cropper/tests/example-DynamicImage.htm | 203 -- view/js/cropper/tests/example-FixedRatio.htm | 104 - .../tests/example-MinimumDimensions.htm | 105 - .../js/cropper/tests/example-MinimumWidth.htm | 105 - view/js/cropper/tests/example-Preview.htm | 117 - view/js/cropper/tests/poppy.jpg | Bin 18338 -> 0 bytes view/js/cropper/tests/staticHTMLStructure.htm | 236 -- view/templates/cropbody.tpl | 80 +- view/templates/crophead.tpl | 6 +- view/theme/duepuntozero/style.css | 3 + view/theme/frio/css/style.css | 3 + 38 files changed, 139 insertions(+), 9757 deletions(-) delete mode 100644 view/js/cropper/cropper.css delete mode 100644 view/js/cropper/cropper.html delete mode 100644 view/js/cropper/cropper.js delete mode 100644 view/js/cropper/cropper.uncompressed.js delete mode 100644 view/js/cropper/lib/builder.js delete mode 100644 view/js/cropper/lib/controls.js delete mode 100644 view/js/cropper/lib/dragdrop.js delete mode 100644 view/js/cropper/lib/effects.js delete mode 100644 view/js/cropper/lib/prototype.js delete mode 100644 view/js/cropper/lib/scriptaculous.js delete mode 100644 view/js/cropper/lib/slider.js delete mode 100644 view/js/cropper/lib/unittest.js delete mode 100644 view/js/cropper/licence.txt delete mode 100644 view/js/cropper/marqueeHoriz.gif delete mode 100644 view/js/cropper/marqueeVert.gif delete mode 100644 view/js/cropper/tests/castle.jpg delete mode 100644 view/js/cropper/tests/castleMed.jpg delete mode 100644 view/js/cropper/tests/example-Basic.htm delete mode 100644 view/js/cropper/tests/example-CSS-Absolute.htm delete mode 100644 view/js/cropper/tests/example-CSS-Float.htm delete mode 100644 view/js/cropper/tests/example-CSS-Relative.htm delete mode 100644 view/js/cropper/tests/example-CoordsOnLoad.htm delete mode 100644 view/js/cropper/tests/example-CoordsOnLoadWithRatio.htm delete mode 100644 view/js/cropper/tests/example-Dimensions.htm delete mode 100644 view/js/cropper/tests/example-DynamicImage.htm delete mode 100644 view/js/cropper/tests/example-FixedRatio.htm delete mode 100644 view/js/cropper/tests/example-MinimumDimensions.htm delete mode 100644 view/js/cropper/tests/example-MinimumWidth.htm delete mode 100644 view/js/cropper/tests/example-Preview.htm delete mode 100644 view/js/cropper/tests/poppy.jpg delete mode 100644 view/js/cropper/tests/staticHTMLStructure.htm diff --git a/composer.json b/composer.json index 81f0b99737..9cef6f379b 100644 --- a/composer.json +++ b/composer.json @@ -34,14 +34,26 @@ "npm-asset/jquery-colorbox": "^1.6", "npm-asset/jquery-datetimepicker": "^2.4.0", "npm-asset/jgrowl": "^1.4", - "npm-asset/fullcalendar": "^3.0.1" + "npm-asset/fullcalendar": "^3.0.1", + "fengyuanchen/cropperjs": "1.2.2" }, "repositories": [ - { - "type": "vcs", - "url": "https://github.com/pear/Text_Highlighter" - } - ], + { + "type": "vcs", + "url": "https://github.com/pear/Text_Highlighter" + }, + { + "type": "package", + "package": { + "name": "fengyuanchen/cropperjs", + "version": "1.2.2", + "dist": { + "url": "https://github.com/fengyuanchen/cropperjs/archive/v1.2.2.zip", + "type": "zip" + } + } + } + ], "autoload": { "psr-4": { "Friendica\\": "src/" @@ -55,11 +67,11 @@ "optimize-autoloader": true, "preferred-install": "dist", "fxp-asset": { - "installer-paths": { - "npm-asset-library": "view/asset", - "bower-asset-library": "view/asset" - } - } + "installer-paths": { + "npm-asset-library": "view/asset", + "bower-asset-library": "view/asset" + } + } }, "archive": { "exclude": [ diff --git a/composer.lock b/composer.lock index 20b89bfbef..5d15aef12a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "0811acc361f70e08cce3ec09940cbf2d", + "content-hash": "c665c4d63bd0317db0c1992ad7c6c7a1", "packages": [ { "name": "asika/simple-console", @@ -41,16 +41,16 @@ }, { "name": "bower-asset/Chart-js", - "version": "v2.7.1", + "version": "v2.7.2", "source": { "type": "git", "url": "https://github.com/chartjs/Chart.js.git", - "reference": "0fead21939b92c15093c1b7d5ee2627fb5900fff" + "reference": "98f104cdd03617f1300b417b3d60c23d4e3e3403" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chartjs/Chart.js/zipball/0fead21939b92c15093c1b7d5ee2627fb5900fff", - "reference": "0fead21939b92c15093c1b7d5ee2627fb5900fff", + "url": "https://api.github.com/repos/chartjs/Chart.js/zipball/98f104cdd03617f1300b417b3d60c23d4e3e3403", + "reference": "98f104cdd03617f1300b417b3d60c23d4e3e3403", "shasum": "" }, "type": "bower-asset-library", @@ -69,7 +69,7 @@ "MIT" ], "description": "Simple HTML5 charts using the canvas element.", - "time": "2017-10-28T15:01:52+00:00" + "time": "2018-03-01T21:45:21+00:00" }, { "name": "bower-asset/base64", @@ -225,6 +225,17 @@ ], "time": "2015-08-05T01:03:42+00:00" }, + { + "name": "fengyuanchen/cropperjs", + "version": "1.2.2", + "dist": { + "type": "zip", + "url": "https://github.com/fengyuanchen/cropperjs/archive/v1.2.2.zip", + "reference": null, + "shasum": null + }, + "type": "library" + }, { "name": "fxp/composer-asset-plugin", "version": "v1.4.2", @@ -286,16 +297,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "6.3.0", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/68d0ea14d5a3f42a20e87632a5f84931e2709c90", + "reference": "68d0ea14d5a3f42a20e87632a5f84931e2709c90", "shasum": "" }, "require": { @@ -305,7 +316,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4", "psr/log": "^1.0" }, "suggest": { @@ -314,7 +325,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "6.3-dev" } }, "autoload": { @@ -347,7 +358,7 @@ "rest", "web service" ], - "time": "2017-06-22T18:50:49+00:00" + "time": "2018-03-26T16:33:04+00:00" }, { "name": "guzzlehttp/promises", @@ -610,16 +621,16 @@ }, { "name": "mobiledetect/mobiledetectlib", - "version": "2.8.30", + "version": "2.8.31", "source": { "type": "git", "url": "https://github.com/serbanghita/Mobile-Detect.git", - "reference": "5500bbbf312fe77ef0c7223858dad84fe49ee0c3" + "reference": "adb882ea3b9d154f087ecb2c333180dad6f4dd37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/5500bbbf312fe77ef0c7223858dad84fe49ee0c3", - "reference": "5500bbbf312fe77ef0c7223858dad84fe49ee0c3", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/adb882ea3b9d154f087ecb2c333180dad6f4dd37", + "reference": "adb882ea3b9d154f087ecb2c333180dad6f4dd37", "shasum": "" }, "require": { @@ -658,31 +669,31 @@ "mobile detector", "php mobile detect" ], - "time": "2017-12-18T10:38:51+00:00" + "time": "2018-02-26T19:39:55+00:00" }, { "name": "npm-asset/fullcalendar", - "version": "3.8.2", + "version": "3.9.0", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.8.2.tgz", + "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.9.0.tgz", "reference": null, - "shasum": "ef7dc77b89134bbe6163e51136f7a1f8bfc1d807" + "shasum": "b608a9989f3416f0b1d526c6bdfeeaf2ac79eda5" }, "require": { "npm-asset/jquery": ">=2,<4.0", - "npm-asset/moment": ">=2.9.0,<3.0.0" + "npm-asset/moment": ">=2.20.1,<3.0.0" }, "require-dev": { - "npm-asset/awesome-typescript-loader": ">=3.3.0,<4.0.0", + "npm-asset/awesome-typescript-loader": ">=3.5.0,<4.0.0", "npm-asset/bootstrap": ">=3.3.7,<4.0.0", "npm-asset/components-jqueryui": "dev-github:components/jqueryui", - "npm-asset/css-loader": ">=0.28.7,<0.29.0", + "npm-asset/css-loader": ">=0.28.10,<0.29.0", "npm-asset/del": ">=2.2.1,<3.0.0", "npm-asset/dts-generator": ">=2.1.0,<3.0.0", - "npm-asset/eslint": ">=4.13.1,<5.0.0", - "npm-asset/eslint-config-standard": ">=11.0.0-beta.0,<12.0.0", - "npm-asset/eslint-plugin-import": ">=2.8.0,<3.0.0", + "npm-asset/eslint": ">=4.18.2,<5.0.0", + "npm-asset/eslint-config-standard": ">=11.0.0,<12.0.0", + "npm-asset/eslint-plugin-import": ">=2.9.0,<3.0.0", "npm-asset/eslint-plugin-node": ">=5.2.1,<6.0.0", "npm-asset/eslint-plugin-promise": ">=3.6.0,<4.0.0", "npm-asset/eslint-plugin-standard": ">=3.0.1,<4.0.0", @@ -695,7 +706,7 @@ "npm-asset/gulp-modify-file": ">=1.0.0,<2.0.0", "npm-asset/gulp-rename": ">=1.2.2,<2.0.0", "npm-asset/gulp-shell": ">=0.6.5,<0.7.0", - "npm-asset/gulp-tslint": ">=8.1.2,<9.0.0", + "npm-asset/gulp-tslint": ">=8.1.3,<9.0.0", "npm-asset/gulp-uglify": ">=2.0.0,<3.0.0", "npm-asset/gulp-util": ">=3.0.7,<4.0.0", "npm-asset/gulp-watch": ">=4.3.11,<5.0.0", @@ -714,14 +725,14 @@ "npm-asset/native-promise-only": ">=0.8.1,<0.9.0", "npm-asset/node-sass": ">=4.7.2,<5.0.0", "npm-asset/phantomjs-prebuilt": ">=2.1.7,<3.0.0", - "npm-asset/sass-loader": ">=6.0.6,<7.0.0", + "npm-asset/sass-loader": ">=6.0.7,<7.0.0", "npm-asset/tslib": ">=1.8.0,<2.0.0", "npm-asset/tslint": ">=5.8.0,<6.0.0", "npm-asset/tslint-config-standard": ">=7.0.0,<8.0.0", "npm-asset/types--jquery": "2.0.47", - "npm-asset/typescript": ">=2.6.2,<3.0.0", - "npm-asset/webpack": ">=3.8.1,<4.0.0", - "npm-asset/webpack-stream": ">=4.0.0,<5.0.0", + "npm-asset/typescript": ">=2.7.2,<3.0.0", + "npm-asset/webpack": ">=3.11.0,<4.0.0", + "npm-asset/webpack-stream": ">=4.0.2,<5.0.0", "npm-asset/yargs": ">=4.8.1,<5.0.0" }, "type": "npm-asset-library", @@ -770,7 +781,7 @@ "full-sized", "jquery-plugin" ], - "time": "2018-01-30T23:49:01+00:00" + "time": "2018-03-05T03:30:23+00:00" }, { "name": "npm-asset/jgrowl", @@ -933,12 +944,12 @@ }, { "name": "npm-asset/jquery-datetimepicker", - "version": "2.5.17", + "version": "2.5.20", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/jquery-datetimepicker/-/jquery-datetimepicker-2.5.17.tgz", + "url": "https://registry.npmjs.org/jquery-datetimepicker/-/jquery-datetimepicker-2.5.20.tgz", "reference": null, - "shasum": "8857a631f248081d4072563bde40fa8c17e407b1" + "shasum": "687d6204b90b03dc93f725f8df036e1d061f37ac" }, "require": { "npm-asset/jquery": ">=1.7.2", @@ -946,8 +957,14 @@ "npm-asset/php-date-formatter": ">=1.3.4,<2.0.0" }, "require-dev": { + "npm-asset/chai": ">=4.1.2,<5.0.0", "npm-asset/concat": "dev-github:azer/concat", "npm-asset/concat-cli": ">=4.0.0,<5.0.0", + "npm-asset/karma": ">=2.0.0,<3.0.0", + "npm-asset/karma-chai": ">=0.1.0,<0.2.0", + "npm-asset/karma-firefox-launcher": ">=1.1.0,<2.0.0", + "npm-asset/karma-mocha": ">=1.3.0,<2.0.0", + "npm-asset/mocha": ">=5.0.4,<6.0.0", "npm-asset/uglifycss": ">=0.0.27,<0.0.28", "npm-asset/uglifyjs": ">=2.4.10,<3.0.0" }, @@ -963,13 +980,13 @@ "url": "git+https://github.com/xdan/datetimepicker.git" }, "npm-asset-scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "karma start --browsers Firefox karma.conf.js --single-run", "concat": "concat-cli -f node_modules/php-date-formatter/js/php-date-formatter.min.js jquery.datetimepicker.js node_modules/jquery-mousewheel/jquery.mousewheel.js -o build/jquery.datetimepicker.full.js", "minify": "uglifyjs jquery.datetimepicker.js -c -m -o build/jquery.datetimepicker.min.js && uglifycss jquery.datetimepicker.css > build/jquery.datetimepicker.min.css", "minifyconcat": "uglifyjs build/jquery.datetimepicker.full.js -c -m -o build/jquery.datetimepicker.full.min.js", "github": "git add --all && git commit -m \"New version %npm_package_version% \" && git tag %npm_package_version% && git push --tags origin HEAD:master && npm publish", "build": "npm run minify && npm run concat && npm run minifyconcat", - "public": "npm version patch --no-git-tag-version && npm run build && npm run github" + "public": "npm run test && npm version patch --no-git-tag-version && npm run build && npm run github" } }, "license": [ @@ -979,7 +996,7 @@ { "name": "Chupurnov", "email": "chupurnov@gmail.com", - "url": "http://xdsoft.net/" + "url": "https://xdsoft.net/" } ], "description": "jQuery Plugin DateTimePicker it is DatePicker and TimePicker in one", @@ -993,7 +1010,7 @@ "time", "timepicker" ], - "time": "2018-01-23T05:56:50+00:00" + "time": "2018-03-21T16:26:39+00:00" }, { "name": "npm-asset/jquery-mousewheel", @@ -1052,12 +1069,12 @@ }, { "name": "npm-asset/moment", - "version": "2.20.1", + "version": "2.21.0", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", + "url": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", "reference": null, - "shasum": "d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd" + "shasum": "2a114b51d2a6ec9e6d83cf803f838a878d8a023a" }, "require-dev": { "npm-asset/benchmark": "dev-default|*", @@ -1160,7 +1177,7 @@ "time", "validate" ], - "time": "2017-12-19T04:44:18+00:00" + "time": "2018-03-02T20:41:10+00:00" }, { "name": "npm-asset/php-date-formatter", @@ -1372,16 +1389,16 @@ }, { "name": "paragonie/sodium_compat", - "version": "v1.6.0", + "version": "v1.6.1", "source": { "type": "git", "url": "https://github.com/paragonie/sodium_compat.git", - "reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432" + "reference": "9857e17bf9c1464485d8cc804eb13f2bcddc4cf0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/1f6e5682eff4a5a6a394b14331a1904f1740e432", - "reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/9857e17bf9c1464485d8cc804eb13f2bcddc4cf0", + "reference": "9857e17bf9c1464485d8cc804eb13f2bcddc4cf0", "shasum": "" }, "require": { @@ -1450,7 +1467,7 @@ "secret-key cryptography", "side-channel resistant" ], - "time": "2018-02-15T05:50:20+00:00" + "time": "2018-03-21T17:08:08+00:00" }, { "name": "pear/console_getopt", diff --git a/view/global.css b/view/global.css index ef76b5ffbe..30dbeeff09 100644 --- a/view/global.css +++ b/view/global.css @@ -201,6 +201,10 @@ blockquote.shared_content { content: ' »'; } +#profile-photo-wrapper { + overflow: hidden; +} + /* headers */ h1, h2, h3, h4, h5, h6 { margin: 5px 0px 5px 0px; diff --git a/view/js/cropper/cropper.css b/view/js/cropper/cropper.css deleted file mode 100644 index c2e759818a..0000000000 --- a/view/js/cropper/cropper.css +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/view/js/cropper/cropper.html b/view/js/cropper/cropper.html deleted file mode 100644 index ebdf1ffc26..0000000000 --- a/view/js/cropper/cropper.html +++ /dev/null @@ -1,228 +0,0 @@ - 1. - - 2. - - 3. - - -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. - Test image - 2. - - 3. - - -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. - Test image - 2. - - 3. - - -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. - Test image - 2. - - 3. - - -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. - Test image - 2. -
- 3. - - 4. - - -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 - diff --git a/view/js/cropper/cropper.js b/view/js/cropper/cropper.js deleted file mode 100644 index 427a9ba0a2..0000000000 --- a/view/js/cropper/cropper.js +++ /dev/null @@ -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;i0&&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); -} -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_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; -} -}}); - diff --git a/view/js/cropper/cropper.uncompressed.js b/view/js/cropper/cropper.uncompressed.js deleted file mode 100644 index 0ea0b803d0..0000000000 --- a/view/js/cropper/cropper.uncompressed.js +++ /dev/null @@ -1,1333 +0,0 @@ -/** - * Image Cropper (v. 1.2.0 - 2006-10-30 ) - * Copyright (c) 2006 David Spurr (http://www.defusion.org.uk/) - * - * The image cropper provides a way to draw a crop area on an image and capture - * the coordinates of the drawn crop area. - * - * Features include: - * - Based on Prototype and Scriptaculous - * - Image editing package styling, the crop area functions and looks - * like those found in popular image editing software - * - Dynamic inclusion of required styles - * - Drag to draw areas - * - Shift drag to draw/resize areas as squares - * - Selection area can be moved - * - Seleciton area can be resized using resize handles - * - Allows dimension ratio limited crop areas - * - Allows minimum dimension crop areas - * - Allows maximum dimesion crop areas - * - If both min & max dimension options set to the same value for a single axis,then the cropper will not - * display the resize handles as appropriate (when min & max dimensions are passed for both axes this - * results in a 'fixed size' crop area) - * - Allows dynamic preview of resultant crop ( if minimum width & height are provided ), this is - * implemented as a subclass so can be excluded when not required - * - Movement of selection area by arrow keys ( shift + arrow key will move selection area by - * 10 pixels ) - * - All operations stay within bounds of image - * - All functionality & display compatible with most popular browsers supported by Prototype: - * PC: IE 7, 6 & 5.5, Firefox 1.5, Opera 8.5 (see known issues) & 9.0b - * MAC: Camino 1.0, Firefox 1.5, Safari 2.0 - * - * Requires: - * - Prototype v. 1.5.0_rc0 > (as packaged with Scriptaculous 1.6.1) - * - Scriptaculous v. 1.6.1 > modules: builder, dragdrop - * - * 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 the error - * that the forceReRender() method fixes for IE 6, i.e. IE 5.5 is not redrawing the box properly. - * - * - Lack of CSS opacity support in Opera before version 9 mean we disable those style rules, these - * could be fixed by using PNGs with transparency if Opera 8.5 support is high priority for you - * - * - Marching ants keep reloading in IE <6 (not tested in IE7), it is a known issue in IE and I have - * found no viable workarounds that can be included in the release. If this really is an issue for you - * either try this post: http://mir.aculo.us/articles/2005/08/28/internet-explorer-and-ajax-image-caching-woes - * or uncomment the 'FIX MARCHING ANTS IN IE' rules in the CSS file - * - * - 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 (maybe Mac browsers too) - * I'm not sure why yet. - * - * Usage: - * See Cropper.Img & Cropper.ImgWithPreview for usage details - * - * Changelog: - * v1.2.0 - 2006-10-30 - * + Added id to the preview image element using 'imgCrop_[originalImageID]' - * * #00001 - Fixed bug: Doesn't account for scroll offsets - * * #00009 - Fixed bug: Placing the cropper inside differently positioned elements causes incorrect co-ordinates and display - * * #00013 - Fixed bug: I-bar cursor appears on drag plane - * * #00014 - Fixed bug: If ID for image tag is not found in document script throws error - * * Fixed bug with drag start co-ordinates if wrapper element has moved in browser (e.g. dragged to a new position) - * * Fixed bug with drag start co-ordinates if image contained in a wrapper with scrolling - this may be buggy if image - * has other ancestors with scrolling applied (except the body) - * * #00015 - Fixed bug: When cropper removed and then reapplied onEndCrop callback gets called multiple times, solution suggestion from Bill Smith - * * Various speed increases & code cleanup which meant improved performance in Mac - which allowed removal of different overlay methods for - * IE and all other browsers, which led to a fix for: - * * #00010 - Fixed bug: Select area doesn't adhere to image size when image resized using img attributes - * - #00006 - Removed default behaviour of automatically setting a ratio when both min width & height passed, the ratioDimensions must be passed in - * + #00005 - Added ability to set maximum crop dimensions, if both min & max set as the same value then we'll get a fixed cropper size on the axes as appropriate - * and the resize handles will not be displayed as appropriate - * * Switched keydown for keypress for moving select area with cursor keys (makes for nicer action) - doesn't appear to work in Safari - * - * v1.1.3 - 2006-08-21 - * * Fixed wrong cursor on western handle in CSS - * + #00008 & #00003 - Added feature: Allow to set dimensions & position for cropper on load - * * #00002 - Fixed bug: Pressing 'remove cropper' twice removes image in IE - * - * v1.1.2 - 2006-06-09 - * * Fixed bugs with ratios when GCD is low (patch submitted by Andy Skelton) - * - * v1.1.1 - 2006-06-03 - * * Fixed bug with rendering issues fix in IE 5.5 - * * Fixed bug with endCrop callback issues once cropper had been removed & reset in IE - * - * v1.1.0 - 2006-06-02 - * * Fixed bug with IE constantly trying to reload select area background image - * * Applied more robust fix to Safari & IE rendering issues - * + Added method to reset parameters - useful for when dynamically changing img cropper attached to - * + Added method to remove cropper from image - * - * v1.0.0 - 2006-05-18 - * + Initial verison - * - * - * 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 - */ - -/** - * Extend the Draggable class to allow us to pass the rendering - * down to the Cropper object. - */ -var CropDraggable = Class.create(); - -Object.extend( Object.extend( CropDraggable.prototype, Draggable.prototype), { - - initialize: function(element) { - this.options = Object.extend( - { - /** - * The draw method to defer drawing to - */ - drawMethod: function() {} - }, - arguments[1] || {} - ); - - this.element = $PR(element); - - 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); - }, - - /** - * Defers the drawing of the draggable to the supplied method - */ - draw: function(point) { - var pos = Position.cumulativeOffset(this.element); - var d = this.currentDelta(); - pos[0] -= d[0]; - pos[1] -= d[1]; - - var p = [0,1].map(function(i) { - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - this.options.drawMethod( p ); - } - -}); - - -/** - * The Cropper object, this will attach itself to the provided image by wrapping it with - * the generated xHTML structure required by the cropper. - * - * Usage: - * @param obj Image element to attach to - * @param obj Optional 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 (see below) - * - * - 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 provided via the onEndCrop option should accept the following parameters: - * - coords obj - * The coordinates object with properties x1, y1, x2 & y2; for the coordinates of the select area - * - * - dimensions obj - * The dimensions object with properites width & height; for the dimensions of the select area - * - * - * Example: - * function onEndCrop( coords, dimensions ) { - * $PR( 'x1' ).value = coords.x1; - * $PR( 'y1' ).value = coords.y1; - * $PR( 'x2' ).value = coords.x2; - * $PR( 'y2' ).value = coords.y2; - * $PR( 'width' ).value = dimensions.width; - * $PR( 'height' ).value = dimensions.height; - * } - * - */ -var Cropper = {}; -Cropper.Img = Class.create(); -Cropper.Img.prototype = { - - /** - * Initialises the class - * - * @access public - * @param obj Image element to attach to - * @param obj Options - * @return void - */ - initialize: function(element, options) { - this.options = Object.extend( - { - /** - * @var obj - * The pixel dimensions to apply as a restrictive ratio - */ - ratioDim: { x: 0, y: 0 }, - /** - * @var int - * The minimum pixel width, also used as restrictive ratio if min height passed too - */ - minWidth: 0, - /** - * @var int - * The minimum pixel height, also used as restrictive ratio if min width passed too - */ - minHeight: 0, - /** - * @var boolean - * Whether to display the select area on initialisation, only used when providing minimum width & height or ratio - */ - displayOnInit: false, - /** - * @var function - * The call back function to pass the final values to - */ - onEndCrop: Prototype.emptyFunction, - /** - * @var boolean - * Whether to capture key presses or not - */ - captureKeys: true, - /** - * @var obj Coordinate object x1, y1, x2, y2 - * The coordinates to optionally display the select area at onload - */ - onloadCoords: null, - /** - * @var 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) - */ - maxWidth: 0, - /** - * @var 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) - */ - maxHeight: 0 - }, - options || {} - ); - /** - * @var obj - * The img node to attach to - */ - this.img = $PR( element ); - /** - * @var obj - * The x & y coordinates of the click point - */ - this.clickCoords = { x: 0, y: 0 }; - /** - * @var boolean - * Whether the user is dragging - */ - this.dragging = false; - /** - * @var boolean - * Whether the user is resizing - */ - this.resizing = false; - /** - * @var boolean - * Whether the user is on a webKit browser - */ - this.isWebKit = /Konqueror|Safari|KHTML/.test( navigator.userAgent ); - /** - * @var boolean - * Whether the user is on IE - */ - this.isIE = /MSIE/.test( navigator.userAgent ); - /** - * @var boolean - * Whether the user is on Opera below version 9 - */ - this.isOpera8 = /Opera\s[1-8]/.test( navigator.userAgent ); - /** - * @var int - * The x ratio - */ - this.ratioX = 0; - /** - * @var int - * The y ratio - */ - this.ratioY = 0; - /** - * @var boolean - * Whether we've attached sucessfully - */ - this.attached = false; - /** - * @var boolean - * Whether we've got a fixed width (if minWidth EQ or GT maxWidth then we have a fixed width - * in the case of minWidth > maxWidth maxWidth wins as the fixed width) - */ - this.fixedWidth = ( this.options.maxWidth > 0 && ( this.options.minWidth >= this.options.maxWidth ) ); - /** - * @var boolean - * Whether we've got a fixed height (if minHeight EQ or GT maxHeight then we have a fixed height - * in the case of minHeight > maxHeight maxHeight wins as the fixed height) - */ - this.fixedHeight = ( this.options.maxHeight > 0 && ( this.options.minHeight >= this.options.maxHeight ) ); - - // quit if the image element doesn't exist - if( typeof this.img == 'undefined' ) return; - - // include the stylesheet - $A( document.getElementsByTagName( 'script' ) ).each( - function(s) { - if( s.src.match( /cropper\.js/ ) ) { - var path = s.src.replace( /cropper\.js(.*)?/, '' ); - // ''; - var style = document.createElement( 'link' ); - style.rel = 'stylesheet'; - style.type = 'text/css'; - style.href = path + 'cropper.css'; - style.media = 'screen'; - document.getElementsByTagName( 'head' )[0].appendChild( style ); - } - } - ); - - // calculate the ratio when neccessary - if( this.options.ratioDim.x > 0 && this.options.ratioDim.y > 0 ) { - var gcd = this.getGCD( this.options.ratioDim.x, this.options.ratioDim.y ); - this.ratioX = this.options.ratioDim.x / gcd; - this.ratioY = this.options.ratioDim.y / gcd; - // dump( 'RATIO : ' + this.ratioX + ':' + this.ratioY + '\n' ); - } - - // initialise sub classes - this.subInitialize(); - - // only load the event observers etc. once the image is loaded - // this is done after the subInitialize() call just in case the sub class does anything - // that will affect the result of the call to onLoad() - if( this.img.complete || this.isWebKit ) this.onLoad(); // for some reason Safari seems to support img.complete but returns 'undefined' on the this.img object - else Event.observe( this.img, 'load', this.onLoad.bindAsEventListener( this) ); - }, - - /** - * The Euclidean algorithm used to find the greatest common divisor - * - * @acces private - * @param int Value 1 - * @param int Value 2 - * @return int - */ - getGCD : function( a , b ) { - if( b == 0 ) return a; - return this.getGCD(b, a % b ); - }, - - /** - * Attaches the cropper to the image once it has loaded - * - * @access private - * @return void - */ - onLoad: function( ) { - /* - * Build the container and all related elements, will result in the following - * - *
- * - *
- * - *
- *
- *
- *
- *
- * - * - *
- *
- *
- *
- * - *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- *
- */ - var cNamePrefix = 'imgCrop_'; - - // get the point to insert the container - var insertPoint = this.img.parentNode; - - // apply an extra class to the wrapper to fix Opera below version 9 - var fixOperaClass = ''; - if( this.isOpera8 ) fixOperaClass = ' opera8'; - this.imgWrap = Builder.node( 'div', { 'class': cNamePrefix + 'wrap' + fixOperaClass } ); - - this.north = Builder.node( 'div', { 'class': cNamePrefix + 'overlay ' + cNamePrefix + 'north' }, [Builder.node( 'span' )] ); - this.east = Builder.node( 'div', { 'class': cNamePrefix + 'overlay ' + cNamePrefix + 'east' } , [Builder.node( 'span' )] ); - this.south = Builder.node( 'div', { 'class': cNamePrefix + 'overlay ' + cNamePrefix + 'south' }, [Builder.node( 'span' )] ); - this.west = Builder.node( 'div', { 'class': cNamePrefix + 'overlay ' + cNamePrefix + 'west' } , [Builder.node( 'span' )] ); - - var overlays = [ this.north, this.east, this.south, this.west ]; - - this.dragArea = Builder.node( 'div', { 'class': cNamePrefix + 'dragArea' }, overlays ); - - this.handleN = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleN' } ); - this.handleNE = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleNE' } ); - this.handleE = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleE' } ); - this.handleSE = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleSE' } ); - this.handleS = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleS' } ); - this.handleSW = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleSW' } ); - this.handleW = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleW' } ); - this.handleNW = Builder.node( 'div', { 'class': cNamePrefix + 'handle ' + cNamePrefix + 'handleNW' } ); - - this.selArea = Builder.node( 'div', { 'class': cNamePrefix + 'selArea' }, - [ - Builder.node( 'div', { 'class': cNamePrefix + 'marqueeHoriz ' + cNamePrefix + 'marqueeNorth' }, [Builder.node( 'span' )] ), - Builder.node( 'div', { 'class': cNamePrefix + 'marqueeVert ' + cNamePrefix + 'marqueeEast' } , [Builder.node( 'span' )] ), - Builder.node( 'div', { 'class': cNamePrefix + 'marqueeHoriz ' + cNamePrefix + 'marqueeSouth' }, [Builder.node( 'span' )] ), - Builder.node( 'div', { 'class': cNamePrefix + 'marqueeVert ' + cNamePrefix + 'marqueeWest' } , [Builder.node( 'span' )] ), - this.handleN, - this.handleNE, - this.handleE, - this.handleSE, - this.handleS, - this.handleSW, - this.handleW, - this.handleNW, - Builder.node( 'div', { 'class': cNamePrefix + 'clickArea' } ) - ] - ); - - this.imgWrap.appendChild( this.img ); - this.imgWrap.appendChild( this.dragArea ); - this.dragArea.appendChild( this.selArea ); - this.dragArea.appendChild( Builder.node( 'div', { 'class': cNamePrefix + 'clickArea' } ) ); - - insertPoint.appendChild( this.imgWrap ); - - // add event observers - 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 ); - } - - // attach the dragable to the select area - new CropDraggable( this.selArea, { drawMethod: this.moveArea.bindAsEventListener( this ) } ); - - this.setParams(); - }, - - /** - * Manages adding or removing the handle event handler and hiding or displaying them as appropriate - * - * @access private - * @param boolean registration true = add, false = remove - * @return void - */ - registerHandles: function( registration ) { - for( var i = 0; i < this.handles.length; i++ ) { - var handle = $PR( this.handles[i] ); - - if( registration ) { - var hideHandle = false; // whether to hide the handle - - // disable handles asappropriate if we've got fixed dimensions - // if both dimensions are fixed we don't need to do much - if( this.fixedWidth && this.fixedHeight ) hideHandle = true; - else if( this.fixedWidth || this.fixedHeight ) { - // if one of the dimensions is fixed then just hide those handles - var isCornerHandle = handle.className.match( /([S|N][E|W])$/ ) - var isWidthHandle = handle.className.match( /(E|W)$/ ); - var isHeightHandle = handle.className.match( /(N|S)$/ ); - if( isCornerHandle ) hideHandle = true; - else if( this.fixedWidth && isWidthHandle ) hideHandle = true; - else if( this.fixedHeight && isHeightHandle ) hideHandle = true; - } - if( hideHandle ) handle.hide(); - else Event.observe( handle, 'mousedown', this.resizeBind ); - } else { - handle.show(); - Event.stopObserving( handle, 'mousedown', this.resizeBind ); - } - } - }, - - /** - * Sets up all the cropper parameters, this can be used to reset the cropper when dynamically - * changing the images - * - * @access private - * @return void - */ - setParams: function() { - /** - * @var int - * The image width - */ - this.imgW = this.img.width; - /** - * @var int - * The image height - */ - 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 } ); - - // resize the container to fit the image - $PR( this.imgWrap ).setStyle( { 'width': this.imgW + 'px', 'height': this.imgH + 'px' } ); - - // hide the select area - $PR( this.selArea ).hide(); - - // setup the starting position of the select area - var startCoords = { x1: 0, y1: 0, x2: 0, y2: 0 }; - var validCoordsSet = false; - - // display the select area - if( this.options.onloadCoords != null ) { - // if we've being given some coordinates to - startCoords = this.cloneCoords( this.options.onloadCoords ); - validCoordsSet = true; - } else if( this.options.ratioDim.x > 0 && this.options.ratioDim.y > 0 ) { - // if there is a ratio limit applied and the then set it to initial ratio - startCoords.x1 = Math.ceil( ( this.imgW - this.options.ratioDim.x ) / 2 ); - startCoords.y1 = Math.ceil( ( this.imgH - this.options.ratioDim.y ) / 2 ); - startCoords.x2 = startCoords.x1 + this.options.ratioDim.x; - startCoords.y2 = startCoords.y1 + this.options.ratioDim.y; - validCoordsSet = true; - } - - this.setAreaCoords( startCoords, false, false, 1 ); - - if( this.options.displayOnInit && validCoordsSet ) { - this.selArea.show(); - this.drawArea(); - this.endCrop(); - } - - this.attached = true; - }, - - /** - * Removes the cropper - * - * @access public - * @return void - */ - remove: function() { - if( this.attached ) { - this.attached = false; - - // remove the elements we inserted - this.imgWrap.parentNode.insertBefore( this.img, this.imgWrap ); - this.imgWrap.parentNode.removeChild( this.imgWrap ); - - // remove the event observers - 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 ); - } - }, - - /** - * Resets the cropper, can be used either after being removed or any time you wish - * - * @access public - * @return void - */ - reset: function() { - if( !this.attached ) this.onLoad(); - else this.setParams(); - this.endCrop(); - }, - - /** - * Handles the key functionality, currently just using arrow keys to move, if the user - * presses shift then the area will move by 10 pixels - */ - handleKeys: function( e ) { - var dir = { x: 0, y: 0 }; // direction to move it in & the amount in pixels - if( !this.dragging ) { - - // catch the arrow keys - switch( e.keyCode ) { - case( 37 ) : // left - dir.x = -1; - break; - case( 38 ) : // up - dir.y = -1; - break; - case( 39 ) : // right - dir.x = 1; - break - case( 40 ) : // down - dir.y = 1; - break; - } - - if( dir.x != 0 || dir.y != 0 ) { - // if shift is pressed then move by 10 pixels - if( e.shiftKey ) { - dir.x *= 10; - dir.y *= 10; - } - - this.moveArea( [ this.areaCoords.x1 + dir.x, this.areaCoords.y1 + dir.y ] ); - Event.stop( e ); - } - } - }, - - /** - * Calculates the width from the areaCoords - * - * @access private - * @return int - */ - calcW: function() { - return (this.areaCoords.x2 - this.areaCoords.x1) - }, - - /** - * Calculates the height from the areaCoords - * - * @access private - * @return int - */ - calcH: function() { - return (this.areaCoords.y2 - this.areaCoords.y1) - }, - - /** - * Moves the select area to the supplied point (assumes the point is x1 & y1 of the select area) - * - * @access public - * @param array Point for x1 & y1 to move select area to - * @return void - */ - moveArea: function( point ) { - // dump( 'moveArea : ' + point[0] + ',' + point[1] + ',' + ( point[0] + ( this.areaCoords.x2 - this.areaCoords.x1 ) ) + ',' + ( point[1] + ( this.areaCoords.y2 - this.areaCoords.y1 ) ) + '\n' ); - this.setAreaCoords( - { - x1: point[0], - y1: point[1], - x2: point[0] + this.calcW(), - y2: point[1] + this.calcH() - }, - true, - false - ); - this.drawArea(); - }, - - /** - * Clones a co-ordinates object, stops problems with handling them by reference - * - * @access private - * @param obj Coordinate object x1, y1, x2, y2 - * @return obj Coordinate object x1, y1, x2, y2 - */ - cloneCoords: function( coords ) { - return { x1: coords.x1, y1: coords.y1, x2: coords.x2, y2: coords.y2 }; - }, - - /** - * Sets the select coords to those provided but ensures they don't go - * outside the bounding box - * - * @access private - * @param obj Coordinates x1, y1, x2, y2 - * @param boolean Whether this is a move - * @param boolean Whether to apply squaring - * @param obj Direction of mouse along both axis x, y ( -1 = negative, 1 = positive ) only required when moving etc. - * @param string The current resize handle || null - * @return void - */ - setAreaCoords: function( coords, moving, square, direction, resizeHandle ) { - // dump( 'setAreaCoords (in) : ' + coords.x1 + ',' + coords.y1 + ',' + coords.x2 + ',' + coords.y2 ); - if( moving ) { - // if moving - var targW = coords.x2 - coords.x1; - var targH = coords.y2 - coords.y1; - - // ensure we're within the bounds - if( coords.x1 < 0 ) { - coords.x1 = 0; - coords.x2 = targW; - } - if( coords.y1 < 0 ) { - coords.y1 = 0; - coords.y2 = targH; - } - if( coords.x2 > this.imgW ) { - coords.x2 = this.imgW; - coords.x1 = this.imgW - targW; - } - if( coords.y2 > this.imgH ) { - coords.y2 = this.imgH; - coords.y1 = this.imgH - targH; - } - } else { - // ensure we're within the bounds - if( coords.x1 < 0 ) coords.x1 = 0; - if( coords.y1 < 0 ) coords.y1 = 0; - if( coords.x2 > this.imgW ) coords.x2 = this.imgW; - if( coords.y2 > this.imgH ) coords.y2 = this.imgH; - - // This is passed as null in onload - if( direction != null ) { - - // apply the ratio or squaring where appropriate - if( this.ratioX > 0 ) this.applyRatio( coords, { x: this.ratioX, y: this.ratioY }, direction, resizeHandle ); - else if( square ) this.applyRatio( coords, { x: 1, y: 1 }, direction, resizeHandle ); - - var mins = [ this.options.minWidth, this.options.minHeight ]; // minimum dimensions [x,y] - var maxs = [ this.options.maxWidth, this.options.maxHeight ]; // maximum dimensions [x,y] - - // apply dimensions where appropriate - if( mins[0] > 0 || mins[1] > 0 || maxs[0] > 0 || maxs[1] > 0) { - - var coordsTransX = { a1: coords.x1, a2: coords.x2 }; - var coordsTransY = { a1: coords.y1, a2: coords.y2 }; - var boundsX = { min: 0, max: this.imgW }; - var boundsY = { min: 0, max: this.imgH }; - - // handle squaring properly on single axis minimum dimensions - if( (mins[0] != 0 || mins[1] != 0) && square ) { - if( mins[0] > 0 ) mins[1] = mins[0]; - else if( mins[1] > 0 ) mins[0] = mins[1]; - } - - if( (maxs[0] != 0 || maxs[0] != 0) && square ) { - // if we have a max x value & it is less than the max y value then we set the y max to the max x (so we don't go over the minimum maximum of one of the axes - if that makes sense) - if( maxs[0] > 0 && maxs[0] <= maxs[1] ) maxs[1] = maxs[0]; - else if( maxs[1] > 0 && maxs[1] <= maxs[0] ) maxs[0] = maxs[1]; - } - - if( mins[0] > 0 ) this.applyDimRestriction( coordsTransX, mins[0], direction.x, boundsX, 'min' ); - if( mins[1] > 1 ) this.applyDimRestriction( coordsTransY, mins[1], direction.y, boundsY, 'min' ); - - if( maxs[0] > 0 ) this.applyDimRestriction( coordsTransX, maxs[0], direction.x, boundsX, 'max' ); - if( maxs[1] > 1 ) this.applyDimRestriction( coordsTransY, maxs[1], direction.y, boundsY, 'max' ); - - coords = { x1: coordsTransX.a1, y1: coordsTransY.a1, x2: coordsTransX.a2, y2: coordsTransY.a2 }; - } - - } - } - - // dump( 'setAreaCoords (out) : ' + coords.x1 + ',' + coords.y1 + ',' + coords.x2 + ',' + coords.y2 + '\n' ); - this.areaCoords = coords; - }, - - /** - * Applies the supplied dimension restriction to the supplied coordinates along a single axis - * - * @access private - * @param obj Single axis coordinates, a1, a2 (e.g. for the x axis a1 = x1 & a2 = x2) - * @param int The restriction value - * @param int The direction ( -1 = negative, 1 = positive ) - * @param obj The bounds of the image ( for this axis ) - * @param string The dimension restriction type ( 'min' | 'max' ) - * @return void - */ - applyDimRestriction: function( coords, val, direction, bounds, type ) { - var check; - if( type == 'min' ) check = ( ( coords.a2 - coords.a1 ) < val ); - else check = ( ( coords.a2 - coords.a1 ) > val ); - if( check ) { - if( direction == 1 ) coords.a2 = coords.a1 + val; - else coords.a1 = coords.a2 - val; - - // make sure we're still in the bounds (not too pretty for the user, but needed) - if( coords.a1 < bounds.min ) { - coords.a1 = bounds.min; - coords.a2 = val; - } else if( coords.a2 > bounds.max ) { - coords.a1 = bounds.max - val; - coords.a2 = bounds.max; - } - } - }, - - /** - * Applies the supplied ratio to the supplied coordinates - * - * @access private - * @param obj Coordinates, x1, y1, x2, y2 - * @param obj Ratio, x, y - * @param obj Direction of mouse, x & y : -1 == negative 1 == positive - * @param string The current resize handle || null - * @return void - */ - applyRatio : function( coords, ratio, direction, resizeHandle ) { - // dump( 'direction.y : ' + direction.y + '\n'); - var newCoords; - if( resizeHandle == 'N' || resizeHandle == 'S' ) { - // dump( 'north south \n'); - // if moving on either the lone north & south handles apply the ratio on the y axis - newCoords = this.applyRatioToAxis( - { a1: coords.y1, b1: coords.x1, a2: coords.y2, b2: coords.x2 }, - { a: ratio.y, b: ratio.x }, - { a: direction.y, b: direction.x }, - { min: 0, max: this.imgW } - ); - coords.x1 = newCoords.b1; - coords.y1 = newCoords.a1; - coords.x2 = newCoords.b2; - coords.y2 = newCoords.a2; - } else { - // otherwise deal with it as if we're applying the ratio on the x axis - newCoords = this.applyRatioToAxis( - { a1: coords.x1, b1: coords.y1, a2: coords.x2, b2: coords.y2 }, - { a: ratio.x, b: ratio.y }, - { a: direction.x, b: direction.y }, - { min: 0, max: this.imgH } - ); - coords.x1 = newCoords.a1; - coords.y1 = newCoords.b1; - coords.x2 = newCoords.a2; - coords.y2 = newCoords.b2; - } - - }, - - /** - * Applies the provided ratio to the provided coordinates based on provided direction & bounds, - * use to encapsulate functionality to make it easy to apply to either axis. This is probably - * quite hard to visualise so see the x axis example within applyRatio() - * - * Example in parameter details & comments is for requesting applying ratio to x axis. - * - * @access private - * @param obj Coords object (a1, b1, a2, b2) where a = x & b = y in example - * @param obj Ratio object (a, b) where a = x & b = y in example - * @param obj Direction object (a, b) where a = x & b = y in example - * @param obj Bounds (min, max) - * @return obj Coords object (a1, b1, a2, b2) where a = x & b = y in example - */ - applyRatioToAxis: function( coords, ratio, direction, bounds ) { - var newCoords = Object.extend( coords, {} ); - var calcDimA = newCoords.a2 - newCoords.a1; // calculate dimension a (e.g. width) - var targDimB = Math.floor( calcDimA * ratio.b / ratio.a ); // the target dimension b (e.g. height) - var targB; // to hold target b (e.g. y value) - var targDimA; // to hold target dimension a (e.g. width) - var calcDimB = null; // to hold calculated dimension b (e.g. height) - - // dump( 'newCoords[0]: ' + newCoords.a1 + ',' + newCoords.b1 + ','+ newCoords.a2 + ',' + newCoords.b2 + '\n'); - - if( direction.b == 1 ) { // if travelling in a positive direction - // make sure we're not going out of bounds - targB = newCoords.b1 + targDimB; - if( targB > bounds.max ) { - targB = bounds.max; - calcDimB = targB - newCoords.b1; // calcuate dimension b (e.g. height) - } - - newCoords.b2 = targB; - } else { // if travelling in a negative direction - // make sure we're not going out of bounds - targB = newCoords.b2 - targDimB; - if( targB < bounds.min ) { - targB = bounds.min; - calcDimB = targB + newCoords.b2; // calcuate dimension b (e.g. height) - } - newCoords.b1 = targB; - } - - // dump( 'newCoords[1]: ' + newCoords.a1 + ',' + newCoords.b1 + ','+ newCoords.a2 + ',' + newCoords.b2 + '\n'); - - // apply the calculated dimensions - if( calcDimB != null ) { - targDimA = Math.floor( calcDimB * ratio.a / ratio.b ); - - if( direction.a == 1 ) newCoords.a2 = newCoords.a1 + targDimA; - else newCoords.a1 = newCoords.a1 = newCoords.a2 - targDimA; - } - - // dump( 'newCoords[2]: ' + newCoords.a1 + ',' + newCoords.b1 + ','+ newCoords.a2 + ',' + newCoords.b2 + '\n'); - - return newCoords; - }, - - /** - * Draws the select area - * - * @access private - * @return void - */ - drawArea: function( ) { - /* - * NOTE: I'm not using the Element.setStyle() shortcut as they make it - * quite sluggish on Mac based browsers - */ - // dump( 'drawArea : ' + this.areaCoords.x1 + ',' + this.areaCoords.y1 + ',' + this.areaCoords.x2 + ',' + this.areaCoords.y2 + '\n' ); - var areaWidth = this.calcW(); - var areaHeight = this.calcH(); - - /* - * Calculate all the style strings before we use them, allows reuse & produces quicker - * rendering (especially noticable in Mac based browsers) - */ - var px = 'px'; - var params = [ - this.areaCoords.x1 + px, // the left of the selArea - this.areaCoords.y1 + px, // the top of the selArea - areaWidth + px, // width of the selArea - areaHeight + px, // height of the selArea - this.areaCoords.x2 + px, // bottom of the selArea - this.areaCoords.y2 + px, // right of the selArea - (this.img.width - this.areaCoords.x2) + px, // right edge of selArea - (this.img.height - this.areaCoords.y2) + px // bottom edge of selArea - ]; - - // do the select area - var areaStyle = this.selArea.style; - areaStyle.left = params[0]; - areaStyle.top = params[1]; - areaStyle.width = params[2]; - areaStyle.height = params[3]; - - // position the north, east, south & west handles - var horizHandlePos = Math.ceil( (areaWidth - 6) / 2 ) + px; - var vertHandlePos = Math.ceil( (areaHeight - 6) / 2 ) + px; - - this.handleN.style.left = horizHandlePos; - this.handleE.style.top = vertHandlePos; - this.handleS.style.left = horizHandlePos; - this.handleW.style.top = vertHandlePos; - - // draw the four overlays - this.north.style.height = params[1]; - - var eastStyle = this.east.style; - eastStyle.top = params[1]; - eastStyle.height = params[3]; - eastStyle.left = params[4]; - eastStyle.width = params[6]; - - var southStyle = this.south.style; - southStyle.top = params[5]; - southStyle.height = params[7]; - - var westStyle = this.west.style; - westStyle.top = params[1]; - westStyle.height = params[3]; - westStyle.width = params[0]; - - // call the draw method on sub classes - this.subDrawArea(); - - this.forceReRender(); - }, - - /** - * Force the re-rendering of the selArea element which fixes rendering issues in Safari - * & IE PC, especially evident when re-sizing perfectly vertical using any of the south handles - * - * @access private - * @return void - */ - 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]; - /* we have to be a bit more forceful for Safari, otherwise the the marquee & - * the south handles still don't move - */ - d = Builder.node( 'div', '' ); - d.style.visibility = 'hidden'; - - var classList = ['SE','S','SW']; - for( i = 0; i < classList.length; i++ ) { - el = document.getElementsByClassName( 'imgCrop_handle' + classList[i], this.selArea )[0]; - if( el.childNodes.length ) el.removeChild( el.childNodes[0] ); - el.appendChild(d); - } - } - fixEl.appendChild(n); - fixEl.removeChild(n); - } - }, - - /** - * Starts the resize - * - * @access private - * @param obj Event - * @return void - */ - 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])+/, ''); - // dump( 'this.resizeHandle : ' + this.resizeHandle + '\n' ); - Event.stop( e ); - }, - - /** - * Starts the drag - * - * @access private - * @param obj Event - * @return void - */ - 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 ); // incase the user just clicks once after already making a selection - Event.stop( e ); - }, - - /** - * Gets the current cursor position relative to the image - * - * @access private - * @param obj Event - * @return obj x,y pixels of the cursor - */ - getCurPos: function( e ) { - // get the offsets for the wrapper within the document - var el = this.imgWrap, wrapOffsets = Position.cumulativeOffset( el ); - // remove any scrolling that is applied to the wrapper (this may be buggy) - don't count the scroll on the body as that won't affect us - 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] - } - }, - - /** - * Performs the drag for both resize & inital draw dragging - * - * @access private - * @param obj Event - * @return void - */ - onDrag: function( e ) { - if( this.dragging || this.resizing ) { - - var resizeHandle = null; - var curPos = this.getCurPos( e ); - var newCoords = this.cloneCoords( this.areaCoords ); - var direction = { x: 1, y: 1 }; - - if( this.dragging ) { - if( curPos.x < this.clickCoords.x ) direction.x = -1; - if( curPos.y < this.clickCoords.y ) direction.y = -1; - - this.transformCoords( curPos.x, this.clickCoords.x, newCoords, 'x' ); - this.transformCoords( curPos.y, this.clickCoords.y, newCoords, 'y' ); - } else if( this.resizing ) { - resizeHandle = this.resizeHandle; - // do x movements first - if( resizeHandle.match(/E/) ) { - // if we're moving an east handle - this.transformCoords( curPos.x, this.startCoords.x1, newCoords, 'x' ); - if( curPos.x < this.startCoords.x1 ) direction.x = -1; - } else if( resizeHandle.match(/W/) ) { - // if we're moving an west handle - this.transformCoords( curPos.x, this.startCoords.x2, newCoords, 'x' ); - if( curPos.x < this.startCoords.x2 ) direction.x = -1; - } - - // do y movements second - if( resizeHandle.match(/N/) ) { - // if we're moving an north handle - this.transformCoords( curPos.y, this.startCoords.y2, newCoords, 'y' ); - if( curPos.y < this.startCoords.y2 ) direction.y = -1; - } else if( resizeHandle.match(/S/) ) { - // if we're moving an south handle - this.transformCoords( curPos.y, this.startCoords.y1, newCoords, 'y' ); - if( curPos.y < this.startCoords.y1 ) direction.y = -1; - } - - } - - this.setAreaCoords( newCoords, false, e.shiftKey, direction, resizeHandle ); - this.drawArea(); - Event.stop( e ); // stop the default event (selecting images & text) in Safari & IE PC - } - }, - - /** - * Applies the appropriate transform to supplied co-ordinates, on the - * defined axis, depending on the relationship of the supplied values - * - * @access private - * @param int Current value of pointer - * @param int Base value to compare current pointer val to - * @param obj Coordinates to apply transformation on x1, x2, y1, y2 - * @param string Axis to apply transformation on 'x' || 'y' - * @return void - */ - transformCoords : function( curVal, baseVal, coords, axis ) { - var newVals = [ curVal, baseVal ]; - if( curVal > baseVal ) newVals.reverse(); - coords[ axis + '1' ] = newVals[0]; - coords[ axis + '2' ] = newVals[1]; - }, - - /** - * Ends the crop & passes the values of the select area on to the appropriate - * callback function on completion of a crop - * - * @access private - * @return void - */ - endCrop : function() { - this.dragging = false; - this.resizing = false; - - this.options.onEndCrop( - this.areaCoords, - { - width: this.calcW(), - height: this.calcH() - } - ); - }, - - /** - * Abstract method called on the end of initialization - * - * @access private - * @abstract - * @return void - */ - subInitialize: function() {}, - - /** - * Abstract method called on the end of drawArea() - * - * @access private - * @abstract - * @return void - */ - subDrawArea: function() {} -}; - - - - -/** - * Extend the Cropper.Img class to allow for presentation of a preview image of the resulting crop, - * the option for displayOnInit is always overridden to true when displaying a preview image - * - * Usage: - * @param obj Image element to attach to - * @param obj Optional options: - * - see Cropper.Img for base options - * - * - previewWrap obj - * HTML element that will be used as a container for the preview image - */ -Cropper.ImgWithPreview = Class.create(); - -Object.extend( Object.extend( Cropper.ImgWithPreview.prototype, Cropper.Img.prototype ), { - - /** - * Implements the abstract method from Cropper.Img to initialize preview image settings. - * Will only attach a preview image is the previewWrap element is defined and the minWidth - * & minHeight options are set. - * - * @see Croper.Img.subInitialize - */ - subInitialize: function() { - /** - * Whether or not we've attached a preview image - * @var boolean - */ - this.hasPreviewImg = false; - if( typeof(this.options.previewWrap) != 'undefined' - && this.options.minWidth > 0 - && this.options.minHeight > 0 - ) { - /** - * The preview image wrapper element - * @var obj HTML element - */ - this.previewWrap = $PR( this.options.previewWrap ); - /** - * The preview image element - * @var obj HTML IMG element - */ - this.previewImg = this.img.cloneNode( false ); - // set the ID of the preview image to be unique - this.previewImg.id = 'imgCrop_' + this.previewImg.id; - - - // set the displayOnInit option to true so we display the select area at the same time as the thumbnail - 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 ); - } - }, - - /** - * Implements the abstract method from Cropper.Img to draw the preview image - * - * @see Croper.Img.subDrawArea - */ - subDrawArea: function() { - if( this.hasPreviewImg ) { - // get the ratio of the select area to the src image - var calcWidth = this.calcW(); - var calcHeight = this.calcH(); - // ratios for the dimensions of the preview image - var dimRatio = { - x: this.imgW / calcWidth, - y: this.imgH / calcHeight - }; - //ratios for the positions within the preview - var posRatio = { - x: calcWidth / this.options.minWidth, - y: calcHeight / this.options.minHeight - }; - - // setting the positions in an obj before apply styles for rendering speed increase - var calcPos = { - w: Math.ceil( this.options.minWidth * dimRatio.x ) + 'px', - h: Math.ceil( this.options.minHeight * dimRatio.y ) + 'px', - x: '-' + Math.ceil( this.areaCoords.x1 / posRatio.x ) + 'px', - y: '-' + Math.ceil( this.areaCoords.y1 / posRatio.y ) + 'px' - } - - var previewStyle = this.previewImg.style; - previewStyle.width = calcPos.w; - previewStyle.height = calcPos.h; - previewStyle.left = calcPos.x; - previewStyle.top = calcPos.y; - } - } - -}); diff --git a/view/js/cropper/lib/builder.js b/view/js/cropper/lib/builder.js deleted file mode 100644 index 5b15ba9397..0000000000 --- a/view/js/cropper/lib/builder.js +++ /dev/null @@ -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 + ">"; - } 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 + ">"; - } 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'); - } -} \ No newline at end of file diff --git a/view/js/cropper/lib/controls.js b/view/js/cropper/lib/controls.js deleted file mode 100644 index 9606948779..0000000000 --- a/view/js/cropper/lib/controls.js +++ /dev/null @@ -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, - ''); - 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), this.options.frequency*1000); - }, - - activate: function() { - this.changed = false; - this.hasFocus = true; - this.getUpdatedChoices(); - }, - - onHover: function(event) { - var element = Event.findElement(event, 'LI'); - if(this.index != element.autocompleteIndex) - { - this.index = element.autocompleteIndex; - this.render(); - } - Event.stop(event); - }, - - onClick: function(event) { - var element = Event.findElement(event, 'LI'); - this.index = element.autocompleteIndex; - this.selectEntry(); - this.hide(); - }, - - onBlur: function(event) { - // needed to make click events working - setTimeout(this.hide.bind(this), 250); - this.hasFocus = false; - this.active = false; - }, - - render: function() { - if(this.entryCount > 0) { - for (var i = 0; i < this.entryCount; i++) - this.index==i ? - Element.addClassName(this.getEntry(i),"selected") : - Element.removeClassName(this.getEntry(i),"selected"); - - if(this.hasFocus) { - this.show(); - this.active = true; - } - } else { - this.active = false; - this.hide(); - } - }, - - markPrevious: function() { - if(this.index > 0) this.index-- - else this.index = this.entryCount-1; - }, - - markNext: function() { - if(this.index < this.entryCount-1) this.index++ - else this.index = 0; - }, - - getEntry: function(index) { - return this.update.firstChild.childNodes[index]; - }, - - getCurrentEntry: function() { - return this.getEntry(this.index); - }, - - selectEntry: function() { - this.active = false; - this.updateElement(this.getCurrentEntry()); - }, - - updateElement: function(selectedElement) { - if (this.options.updateElement) { - this.options.updateElement(selectedElement); - return; - } - var value = ''; - if (this.options.select) { - var nodes = document.getElementsByClassName(this.options.select, selectedElement) || []; - if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); - } else - value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); - - var lastTokenPos = this.findLastToken(); - if (lastTokenPos != -1) { - var newValue = this.element.value.substr(0, lastTokenPos + 1); - var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/); - if (whitespace) - newValue += whitespace[0]; - this.element.value = newValue + value; - } else { - this.element.value = value; - } - this.element.focus(); - - if (this.options.afterUpdateElement) - this.options.afterUpdateElement(this.element, selectedElement); - }, - - updateChoices: function(choices) { - if(!this.changed && this.hasFocus) { - this.update.innerHTML = choices; - Element.cleanWhitespace(this.update); - Element.cleanWhitespace(this.update.firstChild); - - if(this.update.firstChild && this.update.firstChild.childNodes) { - this.entryCount = - this.update.firstChild.childNodes.length; - for (var i = 0; i < this.entryCount; i++) { - var entry = this.getEntry(i); - entry.autocompleteIndex = i; - this.addObservers(entry); - } - } else { - this.entryCount = 0; - } - - this.stopIndicator(); - - this.index = 0; - this.render(); - } - }, - - addObservers: function(element) { - Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); - Event.observe(element, "click", this.onClick.bindAsEventListener(this)); - }, - - onObserverEvent: function() { - this.changed = false; - if(this.getToken().length>=this.options.minChars) { - this.startIndicator(); - this.getUpdatedChoices(); - } else { - this.active = false; - this.hide(); - } - }, - - getToken: function() { - var tokenPos = this.findLastToken(); - if (tokenPos != -1) - var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,''); - else - var ret = this.element.value; - - return /\n/.test(ret) ? '' : ret; - }, - - findLastToken: function() { - var lastTokenPos = -1; - - for (var i=0; i lastTokenPos) - lastTokenPos = thisTokenPos; - } - return lastTokenPos; - } -} - -Ajax.Autocompleter = Class.create(); -Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { - initialize: function(element, update, url, options) { - this.baseInitialize(element, update, options); - this.options.asynchronous = true; - this.options.onComplete = this.onComplete.bind(this); - this.options.defaultParams = this.options.parameters || null; - this.url = url; - }, - - getUpdatedChoices: function() { - entry = encodeURIComponent(this.options.paramName) + '=' + - encodeURIComponent(this.getToken()); - - this.options.parameters = this.options.callback ? - this.options.callback(this.element, entry) : entry; - - if(this.options.defaultParams) - this.options.parameters += '&' + this.options.defaultParams; - - new Ajax.Request(this.url, this.options); - }, - - onComplete: function(request) { - this.updateChoices(request.responseText); - } - -}); - -// The local array autocompleter. Used when you'd prefer to -// inject an array of autocompletion options into the page, rather -// than sending out Ajax queries, which can be quite slow sometimes. -// -// The constructor takes four parameters. The first two are, as usual, -// the id of the monitored textbox, and id of the autocompletion menu. -// The third is the array you want to autocomplete from, and the fourth -// is the options block. -// -// Extra local autocompletion options: -// - choices - How many autocompletion choices to offer -// -// - partialSearch - If false, the autocompleter will match entered -// text only at the beginning of strings in the -// autocomplete array. Defaults to true, which will -// match text at the beginning of any *word* in the -// strings in the autocomplete array. If you want to -// search anywhere in the string, additionally set -// the option fullSearch to true (default: off). -// -// - fullSsearch - Search anywhere in autocomplete array strings. -// -// - partialChars - How many characters to enter before triggering -// a partial match (unlike minChars, which defines -// how many characters are required to do any match -// at all). Defaults to 2. -// -// - ignoreCase - Whether to ignore case when autocompleting. -// Defaults to true. -// -// It's possible to pass in a custom function as the 'selector' -// option, if you prefer to write your own autocompletion logic. -// In that case, the other options above will not apply unless -// you support them. - -Autocompleter.Local = Class.create(); -Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), { - initialize: function(element, update, array, options) { - this.baseInitialize(element, update, options); - this.options.array = array; - }, - - getUpdatedChoices: function() { - this.updateChoices(this.options.selector(this)); - }, - - setOptions: function(options) { - this.options = Object.extend({ - choices: 10, - partialSearch: true, - partialChars: 2, - ignoreCase: true, - fullSearch: false, - selector: function(instance) { - var ret = []; // Beginning matches - var partial = []; // Inside matches - var entry = instance.getToken(); - var count = 0; - - for (var i = 0; i < instance.options.array.length && - ret.length < instance.options.choices ; i++) { - - var elem = instance.options.array[i]; - var foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase()) : - elem.indexOf(entry); - - while (foundPos != -1) { - if (foundPos == 0 && elem.length != entry.length) { - ret.push("
  • " + elem.substr(0, entry.length) + "" + - elem.substr(entry.length) + "
  • "); - break; - } else if (entry.length >= instance.options.partialChars && - instance.options.partialSearch && foundPos != -1) { - if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { - partial.push("
  • " + elem.substr(0, foundPos) + "" + - elem.substr(foundPos, entry.length) + "" + elem.substr( - foundPos + entry.length) + "
  • "); - break; - } - } - - foundPos = instance.options.ignoreCase ? - elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : - elem.indexOf(entry, foundPos + 1); - - } - } - if (partial.length) - ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) - return "
      " + ret.join('') + "
    "; - } - }, options || {}); - } -}); - -// AJAX in-place editor -// -// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor - -// Use this if you notice weird scrolling problems on some browsers, -// the DOM might be a bit confused when this gets called so do this -// waits 1 ms (with setTimeout) until it does the activation -Field.scrollFreeActivate = function(field) { - setTimeout(function() { - Field.activate(field); - }, 1); -} - -Ajax.InPlaceEditor = Class.create(); -Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99"; -Ajax.InPlaceEditor.prototype = { - initialize: function(element, url, options) { - this.url = url; - this.element = $PR(element); - - this.options = Object.extend({ - okButton: true, - okText: "ok", - cancelLink: true, - cancelText: "cancel", - savingText: "Saving...", - clickToEditText: "Click to edit", - okText: "ok", - rows: 1, - onComplete: function(transport, element) { - new Effect.Highlight(element, {startcolor: this.options.highlightcolor}); - }, - onFailure: function(transport) { - alert("Error communicating with the server: " + transport.responseText.stripTags()); - }, - callback: function(form) { - return Form.serialize(form); - }, - handleLineBreaks: true, - loadingText: 'Loading...', - savingClassName: 'inplaceeditor-saving', - loadingClassName: 'inplaceeditor-loading', - formClassName: 'inplaceeditor-form', - highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, - highlightendcolor: "#FFFFFF", - externalControl: null, - submitOnBlur: false, - ajaxOptions: {}, - evalScripts: false - }, options || {}); - - if(!this.options.formId && this.element.id) { - this.options.formId = this.element.id + "-inplaceeditor"; - if ($PR(this.options.formId)) { - // there's already a form with that name, don't specify an id - this.options.formId = null; - } - } - - if (this.options.externalControl) { - this.options.externalControl = $PR(this.options.externalControl); - } - - this.originalBackground = Element.getStyle(this.element, 'background-color'); - if (!this.originalBackground) { - this.originalBackground = "transparent"; - } - - this.element.title = this.options.clickToEditText; - - this.onclickListener = this.enterEditMode.bindAsEventListener(this); - this.mouseoverListener = this.enterHover.bindAsEventListener(this); - this.mouseoutListener = this.leaveHover.bindAsEventListener(this); - Event.observe(this.element, 'click', this.onclickListener); - Event.observe(this.element, 'mouseover', this.mouseoverListener); - Event.observe(this.element, 'mouseout', this.mouseoutListener); - if (this.options.externalControl) { - Event.observe(this.options.externalControl, 'click', this.onclickListener); - Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener); - Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener); - } - }, - enterEditMode: function(evt) { - if (this.saving) return; - if (this.editing) return; - this.editing = true; - this.onEnterEditMode(); - if (this.options.externalControl) { - Element.hide(this.options.externalControl); - } - Element.hide(this.element); - this.createForm(); - this.element.parentNode.insertBefore(this.form, this.element); - Field.scrollFreeActivate(this.editField); - // stop the event to avoid a page refresh in Safari - if (evt) { - Event.stop(evt); - } - return false; - }, - createForm: function() { - this.form = document.createElement("form"); - this.form.id = this.options.formId; - Element.addClassName(this.form, this.options.formClassName) - this.form.onsubmit = this.onSubmit.bind(this); - - this.createEditField(); - - if (this.options.textarea) { - var br = document.createElement("br"); - this.form.appendChild(br); - } - - if (this.options.okButton) { - okButton = document.createElement("input"); - okButton.type = "submit"; - okButton.value = this.options.okText; - okButton.className = 'editor_ok_button'; - this.form.appendChild(okButton); - } - - if (this.options.cancelLink) { - cancelLink = document.createElement("a"); - cancelLink.href = "#"; - cancelLink.appendChild(document.createTextNode(this.options.cancelText)); - cancelLink.onclick = this.onclickCancel.bind(this); - cancelLink.className = 'editor_cancel'; - this.form.appendChild(cancelLink); - } - }, - hasHTMLLineBreaks: function(string) { - if (!this.options.handleLineBreaks) return false; - return string.match(/
    /i); - }, - convertHTMLLineBreaks: function(string) { - return string.replace(/
    /gi, "\n").replace(//gi, "\n").replace(/<\/p>/gi, "\n").replace(/

    /gi, ""); - }, - createEditField: function() { - var text; - if(this.options.loadTextURL) { - text = this.options.loadingText; - } else { - text = this.getText(); - } - - var obj = this; - - if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { - this.options.textarea = false; - var textField = document.createElement("input"); - textField.obj = this; - textField.type = "text"; - textField.name = "value"; - textField.value = text; - textField.style.backgroundColor = this.options.highlightcolor; - textField.className = 'editor_field'; - var size = this.options.size || this.options.cols || 0; - if (size != 0) textField.size = size; - if (this.options.submitOnBlur) - textField.onblur = this.onSubmit.bind(this); - this.editField = textField; - } else { - this.options.textarea = true; - var textArea = document.createElement("textarea"); - textArea.obj = this; - textArea.name = "value"; - textArea.value = this.convertHTMLLineBreaks(text); - textArea.rows = this.options.rows; - textArea.cols = this.options.cols || 40; - textArea.className = 'editor_field'; - if (this.options.submitOnBlur) - textArea.onblur = this.onSubmit.bind(this); - this.editField = textArea; - } - - if(this.options.loadTextURL) { - this.loadExternalText(); - } - this.form.appendChild(this.editField); - }, - getText: function() { - return this.element.innerHTML; - }, - loadExternalText: function() { - Element.addClassName(this.form, this.options.loadingClassName); - this.editField.disabled = true; - new Ajax.Request( - this.options.loadTextURL, - Object.extend({ - asynchronous: true, - onComplete: this.onLoadedExternalText.bind(this) - }, this.options.ajaxOptions) - ); - }, - onLoadedExternalText: function(transport) { - Element.removeClassName(this.form, this.options.loadingClassName); - this.editField.disabled = false; - this.editField.value = transport.responseText.stripTags(); - }, - onclickCancel: function() { - this.onComplete(); - this.leaveEditMode(); - return false; - }, - onFailure: function(transport) { - this.options.onFailure(transport); - if (this.oldInnerHTML) { - this.element.innerHTML = this.oldInnerHTML; - this.oldInnerHTML = null; - } - return false; - }, - onSubmit: function() { - // onLoading resets these so we need to save them away for the Ajax call - var form = this.form; - var value = this.editField.value; - - // do this first, sometimes the ajax call returns before we get a chance to switch on Saving... - // which means this will actually switch on Saving... *after* we've left edit mode causing Saving... - // to be displayed indefinitely - this.onLoading(); - - if (this.options.evalScripts) { - new Ajax.Request( - this.url, Object.extend({ - parameters: this.options.callback(form, value), - onComplete: this.onComplete.bind(this), - onFailure: this.onFailure.bind(this), - asynchronous:true, - evalScripts:true - }, this.options.ajaxOptions)); - } else { - new Ajax.Updater( - { success: this.element, - // don't update on failure (this could be an option) - failure: null }, - this.url, Object.extend({ - parameters: this.options.callback(form, value), - onComplete: this.onComplete.bind(this), - onFailure: this.onFailure.bind(this) - }, this.options.ajaxOptions)); - } - // stop the event to avoid a page refresh in Safari - if (arguments.length > 1) { - Event.stop(arguments[0]); - } - return false; - }, - onLoading: function() { - this.saving = true; - this.removeForm(); - this.leaveHover(); - this.showSaving(); - }, - showSaving: function() { - this.oldInnerHTML = this.element.innerHTML; - this.element.innerHTML = this.options.savingText; - Element.addClassName(this.element, this.options.savingClassName); - this.element.style.backgroundColor = this.originalBackground; - Element.show(this.element); - }, - removeForm: function() { - if(this.form) { - if (this.form.parentNode) Element.remove(this.form); - this.form = null; - } - }, - enterHover: function() { - if (this.saving) return; - this.element.style.backgroundColor = this.options.highlightcolor; - if (this.effect) { - this.effect.cancel(); - } - Element.addClassName(this.element, this.options.hoverClassName) - }, - leaveHover: function() { - if (this.options.backgroundColor) { - this.element.style.backgroundColor = this.oldBackground; - } - Element.removeClassName(this.element, this.options.hoverClassName) - if (this.saving) return; - this.effect = new Effect.Highlight(this.element, { - startcolor: this.options.highlightcolor, - endcolor: this.options.highlightendcolor, - restorecolor: this.originalBackground - }); - }, - leaveEditMode: function() { - Element.removeClassName(this.element, this.options.savingClassName); - this.removeForm(); - this.leaveHover(); - this.element.style.backgroundColor = this.originalBackground; - Element.show(this.element); - if (this.options.externalControl) { - Element.show(this.options.externalControl); - } - this.editing = false; - this.saving = false; - this.oldInnerHTML = null; - this.onLeaveEditMode(); - }, - onComplete: function(transport) { - this.leaveEditMode(); - this.options.onComplete.bind(this)(transport, this.element); - }, - onEnterEditMode: function() {}, - onLeaveEditMode: function() {}, - dispose: function() { - if (this.oldInnerHTML) { - this.element.innerHTML = this.oldInnerHTML; - } - this.leaveEditMode(); - Event.stopObserving(this.element, 'click', this.onclickListener); - Event.stopObserving(this.element, 'mouseover', this.mouseoverListener); - Event.stopObserving(this.element, 'mouseout', this.mouseoutListener); - if (this.options.externalControl) { - Event.stopObserving(this.options.externalControl, 'click', this.onclickListener); - Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener); - Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener); - } - } -}; - -Ajax.InPlaceCollectionEditor = Class.create(); -Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype); -Object.extend(Ajax.InPlaceCollectionEditor.prototype, { - createEditField: function() { - if (!this.cached_selectTag) { - var selectTag = document.createElement("select"); - var collection = this.options.collection || []; - var optionTag; - collection.each(function(e,i) { - optionTag = document.createElement("option"); - optionTag.value = (e instanceof Array) ? e[0] : e; - if(this.options.value==optionTag.value) optionTag.selected = true; - optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); - selectTag.appendChild(optionTag); - }.bind(this)); - this.cached_selectTag = selectTag; - } - - this.editField = this.cached_selectTag; - if(this.options.loadTextURL) this.loadExternalText(); - this.form.appendChild(this.editField); - this.options.callback = function(form, value) { - return "value=" + encodeURIComponent(value); - } - } -}); - -// Delayed observer, like Form.Element.Observer, -// but waits for delay after last key input -// Ideal for live-search fields - -Form.Element.DelayedObserver = Class.create(); -Form.Element.DelayedObserver.prototype = { - initialize: function(element, delay, callback) { - this.delay = delay || 0.5; - this.element = $PR(element); - this.callback = callback; - this.timer = null; - this.lastValue = $F(this.element); - Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); - }, - delayedListener: function(event) { - if(this.lastValue == $F(this.element)) return; - if(this.timer) clearTimeout(this.timer); - this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); - this.lastValue = $F(this.element); - }, - onTimerEvent: function() { - this.timer = null; - this.callback(this.element, $F(this.element)); - } -}; diff --git a/view/js/cropper/lib/dragdrop.js b/view/js/cropper/lib/dragdrop.js deleted file mode 100644 index baa607c67f..0000000000 --- a/view/js/cropper/lib/dragdrop.js +++ /dev/null @@ -1,915 +0,0 @@ -// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) -// -// See scriptaculous.js for full license. - -/*--------------------------------------------------------------------------*/ - -var Droppables = { - drops: [], - - remove: function(element) { - this.drops = this.drops.reject(function(d) { return d.element==$PR(element) }); - }, - - add: function(element) { - element = $PR(element); - var options = Object.extend({ - greedy: true, - hoverclass: null, - tree: false - }, arguments[1] || {}); - - // cache containers - if(options.containment) { - options._containers = []; - var containment = options.containment; - if((typeof containment == 'object') && - (containment.constructor == Array)) { - containment.each( function(c) { options._containers.push($PR(c)) }); - } else { - options._containers.push($PR(containment)); - } - } - - if(options.accept) options.accept = [options.accept].flatten(); - - Element.makePositioned(element); // fix IE - options.element = element; - - this.drops.push(options); - }, - - findDeepestChild: function(drops) { - deepest = drops[0]; - - for (i = 1; i < drops.length; ++i) - if (Element.isParent(drops[i].element, deepest.element)) - deepest = drops[i]; - - return deepest; - }, - - isContained: function(element, drop) { - var containmentNode; - if(drop.tree) { - containmentNode = element.treeNode; - } else { - containmentNode = element.parentNode; - } - return drop._containers.detect(function(c) { return containmentNode == c }); - }, - - isAffected: function(point, element, drop) { - return ( - (drop.element!=element) && - ((!drop._containers) || - this.isContained(element, drop)) && - ((!drop.accept) || - (Element.classNames(element).detect( - function(v) { return drop.accept.include(v) } ) )) && - Position.within(drop.element, point[0], point[1]) ); - }, - - deactivate: function(drop) { - if(drop.hoverclass) - Element.removeClassName(drop.element, drop.hoverclass); - this.last_active = null; - }, - - activate: function(drop) { - if(drop.hoverclass) - Element.addClassName(drop.element, drop.hoverclass); - this.last_active = drop; - }, - - show: function(point, element) { - if(!this.drops.length) return; - var affected = []; - - if(this.last_active) this.deactivate(this.last_active); - this.drops.each( function(drop) { - if(Droppables.isAffected(point, element, drop)) - affected.push(drop); - }); - - if(affected.length>0) { - drop = Droppables.findDeepestChild(affected); - Position.within(drop.element, point[0], point[1]); - if(drop.onHover) - drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); - - Droppables.activate(drop); - } - }, - - fire: function(event, element) { - if(!this.last_active) return; - Position.prepare(); - - if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) - if (this.last_active.onDrop) - this.last_active.onDrop(element, this.last_active.element, event); - }, - - reset: function() { - if(this.last_active) - this.deactivate(this.last_active); - } -} - -var Draggables = { - drags: [], - observers: [], - - register: function(draggable) { - if(this.drags.length == 0) { - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.updateDrag.bindAsEventListener(this); - this.eventKeypress = this.keyPress.bindAsEventListener(this); - - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - Event.observe(document, "keypress", this.eventKeypress); - } - this.drags.push(draggable); - }, - - unregister: function(draggable) { - this.drags = this.drags.reject(function(d) { return d==draggable }); - if(this.drags.length == 0) { - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - Event.stopObserving(document, "keypress", this.eventKeypress); - } - }, - - activate: function(draggable) { - window.focus(); // allows keypress events if window isn't currently focused, fails for Safari - this.activeDraggable = draggable; - }, - - deactivate: function() { - this.activeDraggable = null; - }, - - updateDrag: function(event) { - if(!this.activeDraggable) return; - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - // Mozilla-based browsers fire successive mousemove events with - // the same coordinates, prevent needless redrawing (moz bug?) - if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; - this._lastPointer = pointer; - this.activeDraggable.updateDrag(event, pointer); - }, - - endDrag: function(event) { - if(!this.activeDraggable) return; - this._lastPointer = null; - this.activeDraggable.endDrag(event); - this.activeDraggable = null; - }, - - keyPress: function(event) { - if(this.activeDraggable) - this.activeDraggable.keyPress(event); - }, - - addObserver: function(observer) { - this.observers.push(observer); - this._cacheObserverCallbacks(); - }, - - removeObserver: function(element) { // element instead of observer fixes mem leaks - this.observers = this.observers.reject( function(o) { return o.element==element }); - this._cacheObserverCallbacks(); - }, - - notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag' - if(this[eventName+'Count'] > 0) - this.observers.each( function(o) { - if(o[eventName]) o[eventName](eventName, draggable, event); - }); - }, - - _cacheObserverCallbacks: function() { - ['onStart','onEnd','onDrag'].each( function(eventName) { - Draggables[eventName+'Count'] = Draggables.observers.select( - function(o) { return o[eventName]; } - ).length; - }); - } -} - -/*--------------------------------------------------------------------------*/ - -var Draggable = Class.create(); -Draggable.prototype = { - initialize: function(element) { - var options = Object.extend({ - handle: false, - starteffect: function(element) { - element._opacity = Element.getOpacity(element); - new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); - }, - reverteffect: function(element, top_offset, left_offset) { - var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; - element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur}); - }, - endeffect: function(element) { - var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0 - new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity}); - }, - zindex: 1000, - revert: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - snap: false // false, or xy or [x,y] or function(x,y){ return [x,y] } - }, arguments[1] || {}); - - this.element = $PR(element); - - if(options.handle && (typeof options.handle == 'string')) { - var h = Element.childrenWithClassName(this.element, options.handle, true); - if(h.length>0) this.handle = h[0]; - } - if(!this.handle) this.handle = $PR(options.handle); - if(!this.handle) this.handle = this.element; - - if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) - options.scroll = $PR(options.scroll); - - Element.makePositioned(this.element); // fix IE - - this.delta = this.currentDelta(); - this.options = options; - this.dragging = false; - - this.eventMouseDown = this.initDrag.bindAsEventListener(this); - Event.observe(this.handle, "mousedown", this.eventMouseDown); - - Draggables.register(this); - }, - - destroy: function() { - Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); - Draggables.unregister(this); - }, - - currentDelta: function() { - return([ - parseInt(Element.getStyle(this.element,'left') || '0'), - parseInt(Element.getStyle(this.element,'top') || '0')]); - }, - - initDrag: function(event) { - if(Event.isLeftClick(event)) { - // abort on form elements, fixes a Firefox issue - var src = Event.element(event); - if(src.tagName && ( - src.tagName=='INPUT' || - src.tagName=='SELECT' || - src.tagName=='OPTION' || - src.tagName=='BUTTON' || - src.tagName=='TEXTAREA')) return; - - if(this.element._revert) { - this.element._revert.cancel(); - this.element._revert = null; - } - - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var pos = Position.cumulativeOffset(this.element); - this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) }); - - Draggables.activate(this); - Event.stop(event); - } - }, - - startDrag: function(event) { - this.dragging = true; - - if(this.options.zindex) { - this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0); - this.element.style.zIndex = this.options.zindex; - } - - if(this.options.ghosting) { - this._clone = this.element.cloneNode(true); - Position.absolutize(this.element); - this.element.parentNode.insertBefore(this._clone, this.element); - } - - if(this.options.scroll) { - if (this.options.scroll == window) { - var where = this._getWindowScroll(this.options.scroll); - this.originalScrollLeft = where.left; - this.originalScrollTop = where.top; - } else { - this.originalScrollLeft = this.options.scroll.scrollLeft; - this.originalScrollTop = this.options.scroll.scrollTop; - } - } - - Draggables.notify('onStart', this, event); - if(this.options.starteffect) this.options.starteffect(this.element); - }, - - updateDrag: function(event, pointer) { - if(!this.dragging) this.startDrag(event); - Position.prepare(); - Droppables.show(pointer, this.element); - Draggables.notify('onDrag', this, event); - this.draw(pointer); - if(this.options.change) this.options.change(this); - - if(this.options.scroll) { - this.stopScrolling(); - - var p; - if (this.options.scroll == window) { - with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; } - } else { - p = Position.page(this.options.scroll); - p[0] += this.options.scroll.scrollLeft; - p[1] += this.options.scroll.scrollTop; - p.push(p[0]+this.options.scroll.offsetWidth); - p.push(p[1]+this.options.scroll.offsetHeight); - } - var speed = [0,0]; - if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity); - if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity); - if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity); - if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity); - this.startScrolling(speed); - } - - // fix AppleWebKit rendering - if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); - - Event.stop(event); - }, - - finishDrag: function(event, success) { - this.dragging = false; - - if(this.options.ghosting) { - Position.relativize(this.element); - Element.remove(this._clone); - this._clone = null; - } - - if(success) Droppables.fire(event, this.element); - Draggables.notify('onEnd', this, event); - - var revert = this.options.revert; - if(revert && typeof revert == 'function') revert = revert(this.element); - - var d = this.currentDelta(); - if(revert && this.options.reverteffect) { - this.options.reverteffect(this.element, - d[1]-this.delta[1], d[0]-this.delta[0]); - } else { - this.delta = d; - } - - if(this.options.zindex) - this.element.style.zIndex = this.originalZ; - - if(this.options.endeffect) - this.options.endeffect(this.element); - - Draggables.deactivate(this); - Droppables.reset(); - }, - - keyPress: function(event) { - if(event.keyCode!=Event.KEY_ESC) return; - this.finishDrag(event, false); - Event.stop(event); - }, - - endDrag: function(event) { - if(!this.dragging) return; - this.stopScrolling(); - this.finishDrag(event, true); - Event.stop(event); - }, - - draw: function(point) { - var pos = Position.cumulativeOffset(this.element); - var d = this.currentDelta(); - pos[0] -= d[0]; pos[1] -= d[1]; - - if(this.options.scroll && (this.options.scroll != window)) { - pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft; - pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop; - } - - var p = [0,1].map(function(i){ - return (point[i]-pos[i]-this.offset[i]) - }.bind(this)); - - if(this.options.snap) { - if(typeof this.options.snap == 'function') { - p = this.options.snap(p[0],p[1],this); - } else { - if(this.options.snap instanceof Array) { - p = p.map( function(v, i) { - return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this)) - } else { - p = p.map( function(v) { - return Math.round(v/this.options.snap)*this.options.snap }.bind(this)) - } - }} - - var style = this.element.style; - if((!this.options.constraint) || (this.options.constraint=='horizontal')) - style.left = p[0] + "px"; - if((!this.options.constraint) || (this.options.constraint=='vertical')) - style.top = p[1] + "px"; - if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering - }, - - stopScrolling: function() { - if(this.scrollInterval) { - clearInterval(this.scrollInterval); - this.scrollInterval = null; - Draggables._lastScrollPointer = null; - } - }, - - startScrolling: function(speed) { - this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed]; - this.lastScrolled = new Date(); - this.scrollInterval = setInterval(this.scroll.bind(this), 10); - }, - - scroll: function() { - var current = new Date(); - var delta = current - this.lastScrolled; - this.lastScrolled = current; - if(this.options.scroll == window) { - with (this._getWindowScroll(this.options.scroll)) { - if (this.scrollSpeed[0] || this.scrollSpeed[1]) { - var d = delta / 1000; - this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] ); - } - } - } else { - this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; - this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; - } - - Position.prepare(); - Droppables.show(Draggables._lastPointer, this.element); - Draggables.notify('onDrag', this); - Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); - Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; - Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; - if (Draggables._lastScrollPointer[0] < 0) - Draggables._lastScrollPointer[0] = 0; - if (Draggables._lastScrollPointer[1] < 0) - Draggables._lastScrollPointer[1] = 0; - this.draw(Draggables._lastScrollPointer); - - if(this.options.change) this.options.change(this); - }, - - _getWindowScroll: function(w) { - var T, L, W, H; - with (w.document) { - if (w.document.documentElement && documentElement.scrollTop) { - T = documentElement.scrollTop; - L = documentElement.scrollLeft; - } else if (w.document.body) { - T = body.scrollTop; - L = body.scrollLeft; - } - if (w.innerWidth) { - W = w.innerWidth; - H = w.innerHeight; - } else if (w.document.documentElement && documentElement.clientWidth) { - W = documentElement.clientWidth; - H = documentElement.clientHeight; - } else { - W = body.offsetWidth; - H = body.offsetHeight - } - } - return { top: T, left: L, width: W, height: H }; - } -} - -/*--------------------------------------------------------------------------*/ - -var SortableObserver = Class.create(); -SortableObserver.prototype = { - initialize: function(element, observer) { - this.element = $PR(element); - this.observer = observer; - this.lastValue = Sortable.serialize(this.element); - }, - - onStart: function() { - this.lastValue = Sortable.serialize(this.element); - }, - - onEnd: function() { - Sortable.unmark(); - if(this.lastValue != Sortable.serialize(this.element)) - this.observer(this.element) - } -} - -var Sortable = { - sortables: {}, - - _findRootElement: function(element) { - while (element.tagName != "BODY") { - if(element.id && Sortable.sortables[element.id]) return element; - element = element.parentNode; - } - }, - - options: function(element) { - element = Sortable._findRootElement($PR(element)); - if(!element) return; - return Sortable.sortables[element.id]; - }, - - destroy: function(element){ - var s = Sortable.options(element); - - if(s) { - Draggables.removeObserver(s.element); - s.droppables.each(function(d){ Droppables.remove(d) }); - s.draggables.invoke('destroy'); - - delete Sortable.sortables[s.element.id]; - } - }, - - create: function(element) { - element = $PR(element); - var options = Object.extend({ - element: element, - tag: 'li', // assumes li children, override with tag: 'tagname' - dropOnEmpty: false, - tree: false, - treeTag: 'ul', - overlap: 'vertical', // one of 'vertical', 'horizontal' - constraint: 'vertical', // one of 'vertical', 'horizontal', false - containment: element, // also takes array of elements (or id's); or false - handle: false, // or a CSS class - only: false, - hoverclass: null, - ghosting: false, - scroll: false, - scrollSensitivity: 20, - scrollSpeed: 15, - format: /^[^_]*_(.*)$/, - onChange: Prototype.emptyFunction, - onUpdate: Prototype.emptyFunction - }, arguments[1] || {}); - - // clear any old sortable with same element - this.destroy(element); - - // build options for the draggables - var options_for_draggable = { - revert: true, - scroll: options.scroll, - scrollSpeed: options.scrollSpeed, - scrollSensitivity: options.scrollSensitivity, - ghosting: options.ghosting, - constraint: options.constraint, - handle: options.handle }; - - if(options.starteffect) - options_for_draggable.starteffect = options.starteffect; - - if(options.reverteffect) - options_for_draggable.reverteffect = options.reverteffect; - else - if(options.ghosting) options_for_draggable.reverteffect = function(element) { - element.style.top = 0; - element.style.left = 0; - }; - - if(options.endeffect) - options_for_draggable.endeffect = options.endeffect; - - if(options.zindex) - options_for_draggable.zindex = options.zindex; - - // build options for the droppables - var options_for_droppable = { - overlap: options.overlap, - containment: options.containment, - tree: options.tree, - hoverclass: options.hoverclass, - onHover: Sortable.onHover - //greedy: !options.dropOnEmpty - } - - var options_for_tree = { - onHover: Sortable.onEmptyHover, - overlap: options.overlap, - containment: options.containment, - hoverclass: options.hoverclass - } - - // fix for gecko engine - Element.cleanWhitespace(element); - - options.draggables = []; - options.droppables = []; - - // drop on empty handling - if(options.dropOnEmpty || options.tree) { - Droppables.add(element, options_for_tree); - options.droppables.push(element); - } - - (this.findElements(element, options) || []).each( function(e) { - // handles are per-draggable - var handle = options.handle ? - Element.childrenWithClassName(e, options.handle)[0] : e; - options.draggables.push( - new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); - Droppables.add(e, options_for_droppable); - if(options.tree) e.treeNode = element; - options.droppables.push(e); - }); - - if(options.tree) { - (Sortable.findTreeElements(element, options) || []).each( function(e) { - Droppables.add(e, options_for_tree); - e.treeNode = element; - options.droppables.push(e); - }); - } - - // keep reference - this.sortables[element.id] = options; - - // for onupdate - Draggables.addObserver(new SortableObserver(element, options.onUpdate)); - - }, - - // return all suitable-for-sortable elements in a guaranteed order - findElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.tag); - }, - - findTreeElements: function(element, options) { - return Element.findChildren( - element, options.only, options.tree ? true : false, options.treeTag); - }, - - onHover: function(element, dropon, overlap) { - if(Element.isParent(dropon, element)) return; - - if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { - return; - } else if(overlap>0.5) { - Sortable.mark(dropon, 'before'); - if(dropon.previousSibling != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, dropon); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } else { - Sortable.mark(dropon, 'after'); - var nextElement = dropon.nextSibling || null; - if(nextElement != element) { - var oldParentNode = element.parentNode; - element.style.visibility = "hidden"; // fix gecko rendering - dropon.parentNode.insertBefore(element, nextElement); - if(dropon.parentNode!=oldParentNode) - Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon.parentNode).onChange(element); - } - } - }, - - onEmptyHover: function(element, dropon, overlap) { - var oldParentNode = element.parentNode; - var droponOptions = Sortable.options(dropon); - - if(!Element.isParent(dropon, element)) { - var index; - - var children = Sortable.findElements(dropon, {tag: droponOptions.tag}); - var child = null; - - if(children) { - var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); - - for (index = 0; index < children.length; index += 1) { - if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { - offset -= Element.offsetSize (children[index], droponOptions.overlap); - } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { - child = index + 1 < children.length ? children[index + 1] : null; - break; - } else { - child = children[index]; - break; - } - } - } - - dropon.insertBefore(element, child); - - Sortable.options(oldParentNode).onChange(element); - droponOptions.onChange(element); - } - }, - - unmark: function() { - if(Sortable._marker) Element.hide(Sortable._marker); - }, - - mark: function(dropon, position) { - // mark on ghosting only - var sortable = Sortable.options(dropon.parentNode); - if(sortable && !sortable.ghosting) return; - - if(!Sortable._marker) { - Sortable._marker = $PR('dropmarker') || document.createElement('DIV'); - Element.hide(Sortable._marker); - Element.addClassName(Sortable._marker, 'dropmarker'); - Sortable._marker.style.position = 'absolute'; - document.getElementsByTagName("body").item(0).appendChild(Sortable._marker); - } - var offsets = Position.cumulativeOffset(dropon); - Sortable._marker.style.left = offsets[0] + 'px'; - Sortable._marker.style.top = offsets[1] + 'px'; - - if(position=='after') - if(sortable.overlap == 'horizontal') - Sortable._marker.style.left = (offsets[0]+dropon.clientWidth) + 'px'; - else - Sortable._marker.style.top = (offsets[1]+dropon.clientHeight) + 'px'; - - Element.show(Sortable._marker); - }, - - _tree: function(element, options, parent) { - var children = Sortable.findElements(element, options) || []; - - for (var i = 0; i < children.length; ++i) { - var match = children[i].id.match(options.format); - - if (!match) continue; - - var child = { - id: encodeURIComponent(match ? match[1] : null), - element: element, - parent: parent, - children: new Array, - position: parent.children.length, - container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase()) - } - - /* Get the element containing the children and recurse over it */ - if (child.container) - this._tree(child.container, options, child) - - parent.children.push (child); - } - - return parent; - }, - - /* Finds the first element of the given tag type within a parent element. - Used for finding the first LI[ST] within a L[IST]I[TEM].*/ - _findChildrenElement: function (element, containerTag) { - if (element && element.hasChildNodes) - for (var i = 0; i < element.childNodes.length; ++i) - if (element.childNodes[i].tagName == containerTag) - return element.childNodes[i]; - - return null; - }, - - tree: function(element) { - element = $PR(element); - var sortableOptions = this.options(element); - var options = Object.extend({ - tag: sortableOptions.tag, - treeTag: sortableOptions.treeTag, - only: sortableOptions.only, - name: element.id, - format: sortableOptions.format - }, arguments[1] || {}); - - var root = { - id: null, - parent: null, - children: new Array, - container: element, - position: 0 - } - - return Sortable._tree (element, options, root); - }, - - /* Construct a [i] index for a particular node */ - _constructIndex: function(node) { - var index = ''; - do { - if (node.id) index = '[' + node.position + ']' + index; - } while ((node = node.parent) != null); - return index; - }, - - sequence: function(element) { - element = $PR(element); - var options = Object.extend(this.options(element), arguments[1] || {}); - - return $PR(this.findElements(element, options) || []).map( function(item) { - return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; - }); - }, - - setSequence: function(element, new_sequence) { - element = $PR(element); - var options = Object.extend(this.options(element), arguments[2] || {}); - - var nodeMap = {}; - this.findElements(element, options).each( function(n) { - if (n.id.match(options.format)) - nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; - n.parentNode.removeChild(n); - }); - - new_sequence.each(function(ident) { - var n = nodeMap[ident]; - if (n) { - n[1].appendChild(n[0]); - delete nodeMap[ident]; - } - }); - }, - - serialize: function(element) { - element = $PR(element); - var options = Object.extend(Sortable.options(element), arguments[1] || {}); - var name = encodeURIComponent( - (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); - - if (options.tree) { - return Sortable.tree(element, arguments[1]).children.map( function (item) { - return [name + Sortable._constructIndex(item) + "=" + - encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); - }).flatten().join('&'); - } else { - return Sortable.sequence(element, arguments[1]).map( function(item) { - return name + "[]=" + encodeURIComponent(item); - }).join('&'); - } - } -} - -/* Returns true if child is contained within element */ -Element.isParent = function(child, element) { - if (!child.parentNode || child == element) return false; - - if (child.parentNode == element) return true; - - return Element.isParent(child.parentNode, element); -} - -Element.findChildren = function(element, only, recursive, tagName) { - if(!element.hasChildNodes()) return null; - tagName = tagName.toUpperCase(); - if(only) only = [only].flatten(); - var elements = []; - $A(element.childNodes).each( function(e) { - if(e.tagName && e.tagName.toUpperCase()==tagName && - (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) - elements.push(e); - if(recursive) { - var grandchildren = Element.findChildren(e, only, recursive, tagName); - if(grandchildren) elements.push(grandchildren); - } - }); - - return (elements.length>0 ? elements.flatten() : []); -} - -Element.offsetSize = function (element, type) { - if (type == 'vertical' || type == 'height') - return element.offsetHeight; - else - return element.offsetWidth; -} diff --git a/view/js/cropper/lib/effects.js b/view/js/cropper/lib/effects.js deleted file mode 100644 index 7e0407deb3..0000000000 --- a/view/js/cropper/lib/effects.js +++ /dev/null @@ -1,958 +0,0 @@ -// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// Contributors: -// Justin Palmer (http://encytemedia.com/) -// Mark Pilgrim (http://diveintomark.org/) -// Martin Bialasinki -// -// See scriptaculous.js for full license. - -// converts rgb() and #xxx to #xxxxxx format, -// returns self (or first argument) if not convertable -String.prototype.parseColor = function() { - var color = '#'; - if(this.slice(0,4) == 'rgb(') { - var cols = this.slice(4,this.length-1).split(','); - var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); - } else { - if(this.slice(0,1) == '#') { - if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); - if(this.length==7) color = this.toLowerCase(); - } - } - return(color.length==7 ? color : (arguments[0] || this)); -} - -/*--------------------------------------------------------------------------*/ - -Element.collectTextNodes = function(element) { - return $A($PR(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); - }).flatten().join(''); -} - -Element.collectTextNodesIgnoreClass = function(element, className) { - return $A($PR(element).childNodes).collect( function(node) { - return (node.nodeType==3 ? node.nodeValue : - ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? - Element.collectTextNodesIgnoreClass(node, className) : '')); - }).flatten().join(''); -} - -Element.setContentZoom = function(element, percent) { - element = $PR(element); - Element.setStyle(element, {fontSize: (percent/100) + 'em'}); - if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); -} - -Element.getOpacity = function(element){ - var opacity; - if (opacity = Element.getStyle(element, 'opacity')) - return parseFloat(opacity); - if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/)) - if(opacity[1]) return parseFloat(opacity[1]) / 100; - return 1.0; -} - -Element.setOpacity = function(element, value){ - element= $PR(element); - if (value == 1){ - Element.setStyle(element, { opacity: - (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? - 0.999999 : null }); - if(/MSIE/.test(navigator.userAgent)) - Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')}); - } else { - if(value < 0.00001) value = 0; - Element.setStyle(element, {opacity: value}); - if(/MSIE/.test(navigator.userAgent)) - Element.setStyle(element, - { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + - 'alpha(opacity='+value*100+')' }); - } -} - -Element.getInlineOpacity = function(element){ - return $PR(element).style.opacity || ''; -} - -Element.childrenWithClassName = function(element, className, findFirst) { - var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); - var results = $A($PR(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { - return (c.className && c.className.match(classNameRegExp)); - }); - if(!results) results = []; - return results; -} - -Element.forceRerendering = function(element) { - try { - element = $PR(element); - var n = document.createTextNode(' '); - element.appendChild(n); - element.removeChild(n); - } catch(e) { } -}; - -/*--------------------------------------------------------------------------*/ - -Array.prototype.call = function() { - var args = arguments; - this.each(function(f){ f.apply(this, args) }); -} - -/*--------------------------------------------------------------------------*/ - -var Effect = { - tagifyText: function(element) { - var tagifyStyle = 'position:relative'; - if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1'; - element = $PR(element); - $A(element.childNodes).each( function(child) { - if(child.nodeType==3) { - child.nodeValue.toArray().each( function(character) { - element.insertBefore( - Builder.node('span',{style: tagifyStyle}, - character == ' ' ? String.fromCharCode(160) : character), - child); - }); - Element.remove(child); - } - }); - }, - multiple: function(element, effect) { - var elements; - if(((typeof element == 'object') || - (typeof element == 'function')) && - (element.length)) - elements = element; - else - elements = $PR(element).childNodes; - - var options = Object.extend({ - speed: 0.1, - delay: 0.0 - }, arguments[2] || {}); - var masterDelay = options.delay; - - $A(elements).each( function(element, index) { - new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); - }); - }, - PAIRS: { - 'slide': ['SlideDown','SlideUp'], - 'blind': ['BlindDown','BlindUp'], - 'appear': ['Appear','Fade'] - }, - toggle: function(element, effect) { - element = $PR(element); - effect = (effect || 'appear').toLowerCase(); - var options = Object.extend({ - queue: { position:'end', scope:(element.id || 'global'), limit: 1 } - }, arguments[2] || {}); - Effect[element.visible() ? - Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); - } -}; - -var Effect2 = Effect; // deprecated - -/* ------------- transitions ------------- */ - -Effect.Transitions = {} - -Effect.Transitions.linear = function(pos) { - return pos; -} -Effect.Transitions.sinoidal = function(pos) { - return (-Math.cos(pos*Math.PI)/2) + 0.5; -} -Effect.Transitions.reverse = function(pos) { - return 1-pos; -} -Effect.Transitions.flicker = function(pos) { - return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; -} -Effect.Transitions.wobble = function(pos) { - return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; -} -Effect.Transitions.pulse = function(pos) { - return (Math.floor(pos*10) % 2 == 0 ? - (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10))); -} -Effect.Transitions.none = function(pos) { - return 0; -} -Effect.Transitions.full = function(pos) { - return 1; -} - -/* ------------- core effects ------------- */ - -Effect.ScopedQueue = Class.create(); -Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { - initialize: function() { - this.effects = []; - this.interval = null; - }, - _each: function(iterator) { - this.effects._each(iterator); - }, - add: function(effect) { - var timestamp = new Date().getTime(); - - var position = (typeof effect.options.queue == 'string') ? - effect.options.queue : effect.options.queue.position; - - switch(position) { - case 'front': - // move unstarted effects after this effect - this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { - e.startOn += effect.finishOn; - e.finishOn += effect.finishOn; - }); - break; - case 'end': - // start effect after last queued effect has finished - timestamp = this.effects.pluck('finishOn').max() || timestamp; - break; - } - - effect.startOn += timestamp; - effect.finishOn += timestamp; - - if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) - this.effects.push(effect); - - if(!this.interval) - this.interval = setInterval(this.loop.bind(this), 40); - }, - remove: function(effect) { - this.effects = this.effects.reject(function(e) { return e==effect }); - if(this.effects.length == 0) { - clearInterval(this.interval); - this.interval = null; - } - }, - loop: function() { - var timePos = new Date().getTime(); - this.effects.invoke('loop', timePos); - } -}); - -Effect.Queues = { - instances: $H(), - get: function(queueName) { - if(typeof queueName != 'string') return queueName; - - if(!this.instances[queueName]) - this.instances[queueName] = new Effect.ScopedQueue(); - - return this.instances[queueName]; - } -} -Effect.Queue = Effect.Queues.get('global'); - -Effect.DefaultOptions = { - transition: Effect.Transitions.sinoidal, - duration: 1.0, // seconds - fps: 25.0, // max. 25fps due to Effect.Queue implementation - sync: false, // true for combining - from: 0.0, - to: 1.0, - delay: 0.0, - queue: 'parallel' -} - -Effect.Base = function() {}; -Effect.Base.prototype = { - position: null, - start: function(options) { - this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); - this.currentFrame = 0; - this.state = 'idle'; - this.startOn = this.options.delay*1000; - this.finishOn = this.startOn + (this.options.duration*1000); - this.event('beforeStart'); - if(!this.options.sync) - Effect.Queues.get(typeof this.options.queue == 'string' ? - 'global' : this.options.queue.scope).add(this); - }, - loop: function(timePos) { - if(timePos >= this.startOn) { - if(timePos >= this.finishOn) { - this.render(1.0); - this.cancel(); - this.event('beforeFinish'); - if(this.finish) this.finish(); - this.event('afterFinish'); - return; - } - var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); - var frame = Math.round(pos * this.options.fps * this.options.duration); - if(frame > this.currentFrame) { - this.render(pos); - this.currentFrame = frame; - } - } - }, - render: function(pos) { - if(this.state == 'idle') { - this.state = 'running'; - this.event('beforeSetup'); - if(this.setup) this.setup(); - this.event('afterSetup'); - } - if(this.state == 'running') { - if(this.options.transition) pos = this.options.transition(pos); - pos *= (this.options.to-this.options.from); - pos += this.options.from; - this.position = pos; - this.event('beforeUpdate'); - if(this.update) this.update(pos); - this.event('afterUpdate'); - } - }, - cancel: function() { - if(!this.options.sync) - Effect.Queues.get(typeof this.options.queue == 'string' ? - 'global' : this.options.queue.scope).remove(this); - this.state = 'finished'; - }, - event: function(eventName) { - if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); - if(this.options[eventName]) this.options[eventName](this); - }, - inspect: function() { - return '#'; - } -} - -Effect.Parallel = Class.create(); -Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { - initialize: function(effects) { - this.effects = effects || []; - this.start(arguments[1]); - }, - update: function(position) { - this.effects.invoke('render', position); - }, - finish: function(position) { - this.effects.each( function(effect) { - effect.render(1.0); - effect.cancel(); - effect.event('beforeFinish'); - if(effect.finish) effect.finish(position); - effect.event('afterFinish'); - }); - } -}); - -Effect.Opacity = Class.create(); -Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { - initialize: function(element) { - this.element = $PR(element); - // make this work on IE on elements without 'layout' - if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) - this.element.setStyle({zoom: 1}); - var options = Object.extend({ - from: this.element.getOpacity() || 0.0, - to: 1.0 - }, arguments[1] || {}); - this.start(options); - }, - update: function(position) { - this.element.setOpacity(position); - } -}); - -Effect.Move = Class.create(); -Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { - initialize: function(element) { - this.element = $PR(element); - var options = Object.extend({ - x: 0, - y: 0, - mode: 'relative' - }, arguments[1] || {}); - this.start(options); - }, - setup: function() { - // Bug in Opera: Opera returns the "real" position of a static element or - // relative element that does not have top/left explicitly set. - // ==> Always set top and left for position relative elements in your stylesheets - // (to 0 if you do not need them) - this.element.makePositioned(); - this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); - this.originalTop = parseFloat(this.element.getStyle('top') || '0'); - if(this.options.mode == 'absolute') { - // absolute movement, so we need to calc deltaX and deltaY - this.options.x = this.options.x - this.originalLeft; - this.options.y = this.options.y - this.originalTop; - } - }, - update: function(position) { - this.element.setStyle({ - left: this.options.x * position + this.originalLeft + 'px', - top: this.options.y * position + this.originalTop + 'px' - }); - } -}); - -// for backwards compatibility -Effect.MoveBy = function(element, toTop, toLeft) { - return new Effect.Move(element, - Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); -}; - -Effect.Scale = Class.create(); -Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { - initialize: function(element, percent) { - this.element = $PR(element) - var options = Object.extend({ - scaleX: true, - scaleY: true, - scaleContent: true, - scaleFromCenter: false, - scaleMode: 'box', // 'box' or 'contents' or {} with provided values - scaleFrom: 100.0, - scaleTo: percent - }, arguments[2] || {}); - this.start(options); - }, - setup: function() { - this.restoreAfterFinish = this.options.restoreAfterFinish || false; - this.elementPositioning = this.element.getStyle('position'); - - this.originalStyle = {}; - ['top','left','width','height','fontSize'].each( function(k) { - this.originalStyle[k] = this.element.style[k]; - }.bind(this)); - - this.originalTop = this.element.offsetTop; - this.originalLeft = this.element.offsetLeft; - - var fontSize = this.element.getStyle('font-size') || '100%'; - ['em','px','%'].each( function(fontSizeType) { - if(fontSize.indexOf(fontSizeType)>0) { - this.fontSize = parseFloat(fontSize); - this.fontSizeType = fontSizeType; - } - }.bind(this)); - - this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; - - this.dims = null; - if(this.options.scaleMode=='box') - this.dims = [this.element.offsetHeight, this.element.offsetWidth]; - if(/^content/.test(this.options.scaleMode)) - this.dims = [this.element.scrollHeight, this.element.scrollWidth]; - if(!this.dims) - this.dims = [this.options.scaleMode.originalHeight, - this.options.scaleMode.originalWidth]; - }, - update: function(position) { - var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); - if(this.options.scaleContent && this.fontSize) - this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); - this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); - }, - finish: function(position) { - if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); - }, - setDimensions: function(height, width) { - var d = {}; - if(this.options.scaleX) d.width = width + 'px'; - if(this.options.scaleY) d.height = height + 'px'; - if(this.options.scaleFromCenter) { - var topd = (height - this.dims[0])/2; - var leftd = (width - this.dims[1])/2; - if(this.elementPositioning == 'absolute') { - if(this.options.scaleY) d.top = this.originalTop-topd + 'px'; - if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; - } else { - if(this.options.scaleY) d.top = -topd + 'px'; - if(this.options.scaleX) d.left = -leftd + 'px'; - } - } - this.element.setStyle(d); - } -}); - -Effect.Highlight = Class.create(); -Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { - initialize: function(element) { - this.element = $PR(element); - var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); - this.start(options); - }, - setup: function() { - // Prevent executing on elements not in the layout flow - if(this.element.getStyle('display')=='none') { this.cancel(); return; } - // Disable background image during the effect - this.oldStyle = { - backgroundImage: this.element.getStyle('background-image') }; - this.element.setStyle({backgroundImage: 'none'}); - if(!this.options.endcolor) - this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); - if(!this.options.restorecolor) - this.options.restorecolor = this.element.getStyle('background-color'); - // init color calculations - this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); - this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); - }, - update: function(position) { - this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ - return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); - }, - finish: function() { - this.element.setStyle(Object.extend(this.oldStyle, { - backgroundColor: this.options.restorecolor - })); - } -}); - -Effect.ScrollTo = Class.create(); -Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { - initialize: function(element) { - this.element = $PR(element); - this.start(arguments[1] || {}); - }, - setup: function() { - Position.prepare(); - var offsets = Position.cumulativeOffset(this.element); - if(this.options.offset) offsets[1] += this.options.offset; - var max = window.innerHeight ? - window.height - window.innerHeight : - document.body.scrollHeight - - (document.documentElement.clientHeight ? - document.documentElement.clientHeight : document.body.clientHeight); - this.scrollStart = Position.deltaY; - this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; - }, - update: function(position) { - Position.prepare(); - window.scrollTo(Position.deltaX, - this.scrollStart + (position*this.delta)); - } -}); - -/* ------------- combination effects ------------- */ - -Effect.Fade = function(element) { - element = $PR(element); - var oldOpacity = element.getInlineOpacity(); - var options = Object.extend({ - from: element.getOpacity() || 1.0, - to: 0.0, - afterFinishInternal: function(effect) { - if(effect.options.to!=0) return; - effect.element.hide(); - effect.element.setStyle({opacity: oldOpacity}); - }}, arguments[1] || {}); - return new Effect.Opacity(element,options); -} - -Effect.Appear = function(element) { - element = $PR(element); - var options = Object.extend({ - from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), - to: 1.0, - // force Safari to render floated elements properly - afterFinishInternal: function(effect) { - effect.element.forceRerendering(); - }, - beforeSetup: function(effect) { - effect.element.setOpacity(effect.options.from); - effect.element.show(); - }}, arguments[1] || {}); - return new Effect.Opacity(element,options); -} - -Effect.Puff = function(element) { - element = $PR(element); - var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position') }; - return new Effect.Parallel( - [ new Effect.Scale(element, 200, - { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], - Object.extend({ duration: 1.0, - beforeSetupInternal: function(effect) { - effect.effects[0].element.setStyle({position: 'absolute'}); }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.setStyle(oldStyle); } - }, arguments[1] || {}) - ); -} - -Effect.BlindUp = function(element) { - element = $PR(element); - element.makeClipping(); - return new Effect.Scale(element, 0, - Object.extend({ scaleContent: false, - scaleX: false, - restoreAfterFinish: true, - afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - } - }, arguments[1] || {}) - ); -} - -Effect.BlindDown = function(element) { - element = $PR(element); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, - Object.extend({ scaleContent: false, - scaleX: false, - scaleFrom: 0, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makeClipping(); - effect.element.setStyle({height: '0px'}); - effect.element.show(); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - } - }, arguments[1] || {}) - ); -} - -Effect.SwitchOff = function(element) { - element = $PR(element); - var oldOpacity = element.getInlineOpacity(); - return new Effect.Appear(element, { - duration: 0.4, - from: 0, - transition: Effect.Transitions.flicker, - afterFinishInternal: function(effect) { - new Effect.Scale(effect.element, 1, { - duration: 0.3, scaleFromCenter: true, - scaleX: false, scaleContent: false, restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makePositioned(); - effect.element.makeClipping(); - }, - afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.undoPositioned(); - effect.element.setStyle({opacity: oldOpacity}); - } - }) - } - }); -} - -Effect.DropOut = function(element) { - element = $PR(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left'), - opacity: element.getInlineOpacity() }; - return new Effect.Parallel( - [ new Effect.Move(element, {x: 0, y: 100, sync: true }), - new Effect.Opacity(element, { sync: true, to: 0.0 }) ], - Object.extend( - { duration: 0.5, - beforeSetup: function(effect) { - effect.effects[0].element.makePositioned(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); - } - }, arguments[1] || {})); -} - -Effect.Shake = function(element) { - element = $PR(element); - var oldStyle = { - top: element.getStyle('top'), - left: element.getStyle('left') }; - return new Effect.Move(element, - { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { - new Effect.Move(effect.element, - { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { - effect.element.undoPositioned(); - effect.element.setStyle(oldStyle); - }}) }}) }}) }}) }}) }}); -} - -Effect.SlideDown = function(element) { - element = $PR(element); - element.cleanWhitespace(); - // SlideDown need to have the content of the element wrapped in a container element with fixed height! - var oldInnerBottom = $PR(element.firstChild).getStyle('bottom'); - var elementDimensions = element.getDimensions(); - return new Effect.Scale(element, 100, Object.extend({ - scaleContent: false, - scaleX: false, - scaleFrom: window.opera ? 0 : 1, - scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, - restoreAfterFinish: true, - afterSetup: function(effect) { - effect.element.makePositioned(); - effect.element.firstChild.makePositioned(); - if(window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping(); - effect.element.setStyle({height: '0px'}); - effect.element.show(); }, - afterUpdateInternal: function(effect) { - effect.element.firstChild.setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); - }, - afterFinishInternal: function(effect) { - effect.element.undoClipping(); - // IE will crash if child is undoPositioned first - if(/MSIE/.test(navigator.userAgent)){ - effect.element.undoPositioned(); - effect.element.firstChild.undoPositioned(); - }else{ - effect.element.firstChild.undoPositioned(); - effect.element.undoPositioned(); - } - effect.element.firstChild.setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || {}) - ); -} - -Effect.SlideUp = function(element) { - element = $PR(element); - element.cleanWhitespace(); - var oldInnerBottom = $PR(element.firstChild).getStyle('bottom'); - return new Effect.Scale(element, window.opera ? 0 : 1, - Object.extend({ scaleContent: false, - scaleX: false, - scaleMode: 'box', - scaleFrom: 100, - restoreAfterFinish: true, - beforeStartInternal: function(effect) { - effect.element.makePositioned(); - effect.element.firstChild.makePositioned(); - if(window.opera) effect.element.setStyle({top: ''}); - effect.element.makeClipping(); - effect.element.show(); }, - afterUpdateInternal: function(effect) { - effect.element.firstChild.setStyle({bottom: - (effect.dims[0] - effect.element.clientHeight) + 'px' }); }, - afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.firstChild.undoPositioned(); - effect.element.undoPositioned(); - effect.element.setStyle({bottom: oldInnerBottom}); } - }, arguments[1] || {}) - ); -} - -// Bug in opera makes the TD containing this element expand for a instance after finish -Effect.Squish = function(element) { - return new Effect.Scale(element, window.opera ? 1 : 0, - { restoreAfterFinish: true, - beforeSetup: function(effect) { - effect.element.makeClipping(effect.element); }, - afterFinishInternal: function(effect) { - effect.element.hide(effect.element); - effect.element.undoClipping(effect.element); } - }); -} - -Effect.Grow = function(element) { - element = $PR(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.full - }, arguments[1] || {}); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var initialMoveX, initialMoveY; - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - initialMoveX = initialMoveY = moveX = moveY = 0; - break; - case 'top-right': - initialMoveX = dims.width; - initialMoveY = moveY = 0; - moveX = -dims.width; - break; - case 'bottom-left': - initialMoveX = moveX = 0; - initialMoveY = dims.height; - moveY = -dims.height; - break; - case 'bottom-right': - initialMoveX = dims.width; - initialMoveY = dims.height; - moveX = -dims.width; - moveY = -dims.height; - break; - case 'center': - initialMoveX = dims.width / 2; - initialMoveY = dims.height / 2; - moveX = -dims.width / 2; - moveY = -dims.height / 2; - break; - } - - return new Effect.Move(element, { - x: initialMoveX, - y: initialMoveY, - duration: 0.01, - beforeSetup: function(effect) { - effect.element.hide(); - effect.element.makeClipping(); - effect.element.makePositioned(); - }, - afterFinishInternal: function(effect) { - new Effect.Parallel( - [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), - new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), - new Effect.Scale(effect.element, 100, { - scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, - sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) - ], Object.extend({ - beforeSetup: function(effect) { - effect.effects[0].element.setStyle({height: '0px'}); - effect.effects[0].element.show(); - }, - afterFinishInternal: function(effect) { - effect.effects[0].element.undoClipping(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); - } - }, options) - ) - } - }); -} - -Effect.Shrink = function(element) { - element = $PR(element); - var options = Object.extend({ - direction: 'center', - moveTransition: Effect.Transitions.sinoidal, - scaleTransition: Effect.Transitions.sinoidal, - opacityTransition: Effect.Transitions.none - }, arguments[1] || {}); - var oldStyle = { - top: element.style.top, - left: element.style.left, - height: element.style.height, - width: element.style.width, - opacity: element.getInlineOpacity() }; - - var dims = element.getDimensions(); - var moveX, moveY; - - switch (options.direction) { - case 'top-left': - moveX = moveY = 0; - break; - case 'top-right': - moveX = dims.width; - moveY = 0; - break; - case 'bottom-left': - moveX = 0; - moveY = dims.height; - break; - case 'bottom-right': - moveX = dims.width; - moveY = dims.height; - break; - case 'center': - moveX = dims.width / 2; - moveY = dims.height / 2; - break; - } - - return new Effect.Parallel( - [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), - new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), - new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) - ], Object.extend({ - beforeStartInternal: function(effect) { - effect.effects[0].element.makePositioned(); - effect.effects[0].element.makeClipping(); }, - afterFinishInternal: function(effect) { - effect.effects[0].element.hide(); - effect.effects[0].element.undoClipping(); - effect.effects[0].element.undoPositioned(); - effect.effects[0].element.setStyle(oldStyle); } - }, options) - ); -} - -Effect.Pulsate = function(element) { - element = $PR(element); - var options = arguments[1] || {}; - var oldOpacity = element.getInlineOpacity(); - var transition = options.transition || Effect.Transitions.sinoidal; - var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos)) }; - reverser.bind(transition); - return new Effect.Opacity(element, - Object.extend(Object.extend({ duration: 3.0, from: 0, - afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } - }, options), {transition: reverser})); -} - -Effect.Fold = function(element) { - element = $PR(element); - var oldStyle = { - top: element.style.top, - left: element.style.left, - width: element.style.width, - height: element.style.height }; - Element.makeClipping(element); - return new Effect.Scale(element, 5, Object.extend({ - scaleContent: false, - scaleX: false, - afterFinishInternal: function(effect) { - new Effect.Scale(element, 1, { - scaleContent: false, - scaleY: false, - afterFinishInternal: function(effect) { - effect.element.hide(); - effect.element.undoClipping(); - effect.element.setStyle(oldStyle); - } }); - }}, arguments[1] || {})); -}; - -['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', - 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( - function(f) { Element.Methods[f] = Element[f]; } -); - -Element.Methods.visualEffect = function(element, effect, options) { - s = effect.gsub(/_/, '-').camelize(); - effect_class = s.charAt(0).toUpperCase() + s.substring(1); - new Effect[effect_class](element, options); - return $PR(element); -}; - -Element.addMethods(); diff --git a/view/js/cropper/lib/prototype.js b/view/js/cropper/lib/prototype.js deleted file mode 100644 index 6682065875..0000000000 --- a/view/js/cropper/lib/prototype.js +++ /dev/null @@ -1,2006 +0,0 @@ -/* Prototype JavaScript framework, version 1.5.0_rc0 - * (c) 2005 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://prototype.conio.net/ - * -/*--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.5.0_rc0', - ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', - - emptyFunction: function() {}, - K: function(x) {return x} -} - -var Class = { - create: function() { - return function() { - this.initialize.apply(this, arguments); - } - } -} - -var Abstract = new Object(); - -Object.extend = function(destination, source) { - for (var property in source) { - destination[property] = source[property]; - } - return destination; -} - -Object.inspect = function(object) { - try { - if (object == undefined) return 'undefined'; - if (object == null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } -} - -Function.prototype.bind = function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } -} - -Function.prototype.bindAsEventListener = function(object) { - var __method = this; - return function(event) { - return __method.call(object, event || window.event); - } -} - -Object.extend(Number.prototype, { - toColorPart: function() { - var digits = this.toString(16); - if (this < 16) return '0' + digits; - return digits; - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - } -}); - -var Try = { - these: function() { - var returnValue; - - for (var i = 0; i < arguments.length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) {} - } - - return returnValue; - } -} - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create(); -PeriodicalExecuter.prototype = { - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.callback(); - } finally { - this.currentlyExecuting = false; - } - } - } -} -Object.extend(String.prototype, { - gsub: function(pattern, replacement) { - var result = '', source = this, match; - replacement = arguments.callee.prepareReplacement(replacement); - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += (replacement(match) || '').toString(); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - }, - - sub: function(pattern, replacement, count) { - replacement = this.gsub.prepareReplacement(replacement); - count = count === undefined ? 1 : count; - - return this.gsub(pattern, function(match) { - if (--count < 0) return match[0]; - return replacement(match); - }); - }, - - scan: function(pattern, iterator) { - this.gsub(pattern, iterator); - return this; - }, - - truncate: function(length, truncation) { - length = length || 30; - truncation = truncation === undefined ? '...' : truncation; - return this.length > length ? - this.slice(0, length - truncation.length) + truncation : this; - }, - - strip: function() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - }, - - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(function(script) { return eval(script) }); - }, - - escapeHTML: function() { - var div = document.createElement('div'); - var text = document.createTextNode(this); - div.appendChild(text); - return div.innerHTML; - }, - - unescapeHTML: function() { - var div = document.createElement('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; - }, - - toQueryParams: function() { - var pairs = this.match(/^\??(.*)$/)[1].split('&'); - return pairs.inject({}, function(params, pairString) { - var pair = pairString.split('='); - params[pair[0]] = pair[1]; - return params; - }); - }, - - toArray: function() { - return this.split(''); - }, - - camelize: function() { - var oStringList = this.split('-'); - if (oStringList.length == 1) return oStringList[0]; - - var camelizedString = this.indexOf('-') == 0 - ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) - : oStringList[0]; - - for (var i = 1, len = oStringList.length; i < len; i++) { - var s = oStringList[i]; - camelizedString += s.charAt(0).toUpperCase() + s.substring(1); - } - - return camelizedString; - }, - - inspect: function() { - return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'"; - } -}); - -String.prototype.gsub.prepareReplacement = function(replacement) { - if (typeof replacement == 'function') return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -} - -String.prototype.parseQuery = String.prototype.toQueryParams; - -var Template = Class.create(); -Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; -Template.prototype = { - initialize: function(template, pattern) { - this.template = template.toString(); - this.pattern = pattern || Template.Pattern; - }, - - evaluate: function(object) { - return this.template.gsub(this.pattern, function(match) { - var before = match[1]; - if (before == '\\') return match[2]; - return before + (object[match[3]] || '').toString(); - }); - } -} - -var $break = new Object(); -var $continue = new Object(); - -var Enumerable = { - each: function(iterator) { - var index = 0; - try { - this._each(function(value) { - try { - iterator(value, index++); - } catch (e) { - if (e != $continue) throw e; - } - }); - } catch (e) { - if (e != $break) throw e; - } - }, - - all: function(iterator) { - var result = true; - this.each(function(value, index) { - result = result && !!(iterator || Prototype.K)(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator) { - var result = true; - this.each(function(value, index) { - if (result = !!(iterator || Prototype.K)(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator) { - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function (iterator) { - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator) { - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(pattern, iterator) { - var results = []; - this.each(function(value, index) { - var stringValue = value.toString(); - if (stringValue.match(pattern)) - results.push((iterator || Prototype.K)(value, index)); - }) - return results; - }, - - include: function(object) { - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inject: function(memo, iterator) { - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.collect(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (result == undefined || value >= result) - result = value; - }); - return result; - }, - - min: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (result == undefined || value < result) - result = value; - }); - return result; - }, - - partition: function(iterator) { - var trues = [], falses = []; - this.each(function(value, index) { - ((iterator || Prototype.K)(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value, index) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator) { - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator) { - return this.collect(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.collect(Prototype.K); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (typeof args.last() == 'function') - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - return iterator(collections.pluck(index)); - }); - }, - - inspect: function() { - return '#'; - } -} - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray -}); -var $A = Array.from = function(iterable) { - if (!iterable) return []; - if (iterable.toArray) { - return iterable.toArray(); - } else { - var results = []; - for (var i = 0; i < iterable.length; i++) - results.push(iterable[i]); - return results; - } -} - -Object.extend(Array.prototype, Enumerable); - -if (!Array.prototype._reverse) - Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0; i < this.length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != undefined || value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(value && value.constructor == Array ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - indexOf: function(object) { - for (var i = 0; i < this.length; i++) - if (this[i] == object) return i; - return -1; - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } -}); -var Hash = { - _each: function(iterator) { - for (var key in this) { - var value = this[key]; - if (typeof value == 'function') continue; - - var pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - merge: function(hash) { - return $H(hash).inject($H(this), function(mergedHash, pair) { - mergedHash[pair.key] = pair.value; - return mergedHash; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - return pair.map(encodeURIComponent).join('='); - }).join('&'); - }, - - inspect: function() { - return '#'; - } -} - -function $H(object) { - var hash = Object.extend({}, object || {}); - Object.extend(hash, Enumerable); - Object.extend(hash, Hash); - return hash; -} -ObjectRange = Class.create(); -Object.extend(ObjectRange.prototype, Enumerable); -Object.extend(ObjectRange.prototype, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - do { - iterator(value); - value = value.succ(); - } while (this.include(value)); - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new XMLHttpRequest()}, - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')} - ) || false; - }, - - activeRequestCount: 0 -} - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responderToAdd) { - if (!this.include(responderToAdd)) - this.responders.push(responderToAdd); - }, - - unregister: function(responderToRemove) { - this.responders = this.responders.without(responderToRemove); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (responder[callback] && typeof responder[callback] == 'function') { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) {} - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { - Ajax.activeRequestCount++; - }, - - onComplete: function() { - Ajax.activeRequestCount--; - } -}); - -Ajax.Base = function() {}; -Ajax.Base.prototype = { - setOptions: function(options) { - this.options = { - method: 'post', - asynchronous: true, - contentType: 'application/x-www-form-urlencoded', - parameters: '' - } - Object.extend(this.options, options || {}); - }, - - responseIsSuccess: function() { - return this.transport.status == undefined - || this.transport.status == 0 - || (this.transport.status >= 200 && this.transport.status < 300); - }, - - responseIsFailure: function() { - return !this.responseIsSuccess(); - } -} - -Ajax.Request = Class.create(); -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Request.prototype = Object.extend(new Ajax.Base(), { - initialize: function(url, options) { - this.transport = Ajax.getTransport(); - this.setOptions(options); - this.request(url); - }, - - request: function(url) { - var parameters = this.options.parameters || ''; - if (parameters.length > 0) parameters += '&_='; - - try { - this.url = url; - if (this.options.method == 'get' && parameters.length > 0) - this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; - - Ajax.Responders.dispatch('onCreate', this, this.transport); - - this.transport.open(this.options.method, this.url, - this.options.asynchronous); - - if (this.options.asynchronous) { - this.transport.onreadystatechange = this.onStateChange.bind(this); - setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); - } - - this.setRequestHeaders(); - - var body = this.options.postBody ? this.options.postBody : parameters; - this.transport.send(this.options.method == 'post' ? body : null); - - } catch (e) { - this.dispatchException(e); - } - }, - - setRequestHeaders: function() { - var requestHeaders = - ['X-Requested-With', 'XMLHttpRequest', - 'X-Prototype-Version', Prototype.Version, - 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; - - if (this.options.method == 'post') { - requestHeaders.push('Content-type', this.options.contentType); - - /* Force "Connection: close" for Mozilla browsers to work around - * a bug where XMLHttpReqeuest sends an incorrect Content-length - * header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType) - requestHeaders.push('Connection', 'close'); - } - - if (this.options.requestHeaders) - requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); - - for (var i = 0; i < requestHeaders.length; i += 2) - this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState != 1) - this.respondToReadyState(this.transport.readyState); - }, - - header: function(name) { - try { - return this.transport.getResponseHeader(name); - } catch (e) {} - }, - - evalJSON: function() { - try { - return eval('(' + this.header('X-JSON') + ')'); - } catch (e) {} - }, - - evalResponse: function() { - try { - return eval(this.transport.responseText); - } catch (e) { - this.dispatchException(e); - } - }, - - respondToReadyState: function(readyState) { - var event = Ajax.Request.Events[readyState]; - var transport = this.transport, json = this.evalJSON(); - - if (event == 'Complete') { - try { - (this.options['on' + this.transport.status] - || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(transport, json); - } catch (e) { - this.dispatchException(e); - } - - if ((this.header('Content-type') || '').match(/^text\/javascript/i)) - this.evalResponse(); - } - - try { - (this.options['on' + event] || Prototype.emptyFunction)(transport, json); - Ajax.Responders.dispatch('on' + event, this, transport, json); - } catch (e) { - this.dispatchException(e); - } - - /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ - if (event == 'Complete') - this.transport.onreadystatechange = Prototype.emptyFunction; - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Updater = Class.create(); - -Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { - initialize: function(container, url, options) { - this.containers = { - success: container.success ? $PR(container.success) : $PR(container), - failure: container.failure ? $PR(container.failure) : - (container.success ? null : $PR(container)) - } - - this.transport = Ajax.getTransport(); - this.setOptions(options); - - var onComplete = this.options.onComplete || Prototype.emptyFunction; - this.options.onComplete = (function(transport, object) { - this.updateContent(); - onComplete(transport, object); - }).bind(this); - - this.request(url); - }, - - updateContent: function() { - var receiver = this.responseIsSuccess() ? - this.containers.success : this.containers.failure; - var response = this.transport.responseText; - - if (!this.options.evalScripts) - response = response.stripScripts(); - - if (receiver) { - if (this.options.insertion) { - new this.options.insertion(receiver, response); - } else { - Element.update(receiver, response); - } - } - - if (this.responseIsSuccess()) { - if (this.onComplete) - setTimeout(this.onComplete.bind(this), 10); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(); -Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { - initialize: function(container, url, options) { - this.setOptions(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = {}; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(request) { - if (this.options.decay) { - this.decay = (request.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = request.responseText; - } - this.timer = setTimeout(this.onTimerEvent.bind(this), - this.decay * this.frequency * 1000); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -function $PR() { - var results = [], element; - for (var i = 0; i < arguments.length; i++) { - element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - results.push(Element.extend(element)); - } - return results.length < 2 ? results[0] : results; -} - -document.getElementsByClassName = function(className, parentElement) { - var children = ($PR(parentElement) || document.body).getElementsByTagName('*'); - return $A(children).inject([], function(elements, child) { - if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) - elements.push(Element.extend(child)); - return elements; - }); -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Element) - var Element = new Object(); - -Element.extend = function(element) { - if (!element) return; - if (_nativeExtensions) return element; - - if (!element._extended && element.tagName && element != window) { - var methods = Element.Methods, cache = Element.extend.cache; - for (property in methods) { - var value = methods[property]; - if (typeof value == 'function') - element[property] = cache.findOrStore(value); - } - } - - element._extended = true; - return element; -} - -Element.extend.cache = { - findOrStore: function(value) { - return this[value] = this[value] || function() { - return value.apply(null, [this].concat($A(arguments))); - } - } -} - -Element.Methods = { - visible: function(element) { - return $PR(element).style.display != 'none'; - }, - - toggle: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $PR(arguments[i]); - Element[Element.visible(element) ? 'hide' : 'show'](element); - } - }, - - hide: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $PR(arguments[i]); - element.style.display = 'none'; - } - }, - - show: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $PR(arguments[i]); - element.style.display = ''; - } - }, - - remove: function(element) { - element = $PR(element); - element.parentNode.removeChild(element); - }, - - update: function(element, html) { - $PR(element).innerHTML = html.stripScripts(); - setTimeout(function() {html.evalScripts()}, 10); - }, - - replace: function(element, html) { - element = $PR(element); - if (element.outerHTML) { - element.outerHTML = html.stripScripts(); - } else { - var range = element.ownerDocument.createRange(); - range.selectNodeContents(element); - element.parentNode.replaceChild( - range.createContextualFragment(html.stripScripts()), element); - } - setTimeout(function() {html.evalScripts()}, 10); - }, - - getHeight: function(element) { - element = $PR(element); - return element.offsetHeight; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $PR(element))) return; - return Element.classNames(element).include(className); - }, - - addClassName: function(element, className) { - if (!(element = $PR(element))) return; - return Element.classNames(element).add(className); - }, - - removeClassName: function(element, className) { - if (!(element = $PR(element))) return; - return Element.classNames(element).remove(className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $PR(element); - for (var i = 0; i < element.childNodes.length; i++) { - var node = element.childNodes[i]; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - Element.remove(node); - } - }, - - empty: function(element) { - return $PR(element).innerHTML.match(/^\s*$/); - }, - - childOf: function(element, ancestor) { - element = $PR(element), ancestor = $PR(ancestor); - while (element = element.parentNode) - if (element == ancestor) return true; - return false; - }, - - scrollTo: function(element) { - element = $PR(element); - var x = element.x ? element.x : element.offsetLeft, - y = element.y ? element.y : element.offsetTop; - window.scrollTo(x, y); - }, - - getStyle: function(element, style) { - element = $PR(element); - var value = element.style[style.camelize()]; - if (!value) { - if (document.defaultView && document.defaultView.getComputedStyle) { - var css = document.defaultView.getComputedStyle(element, null); - value = css ? css.getPropertyValue(style) : null; - } else if (element.currentStyle) { - value = element.currentStyle[style.camelize()]; - } - } - - if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) - if (Element.getStyle(element, 'position') == 'static') value = 'auto'; - - return value == 'auto' ? null : value; - }, - - setStyle: function(element, style) { - element = $PR(element); - for (var name in style) - element.style[name.camelize()] = style[name]; - }, - - getDimensions: function(element) { - element = $PR(element); - if (Element.getStyle(element, 'display') != 'none') - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = ''; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = 'none'; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $PR(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - }, - - undoPositioned: function(element) { - element = $PR(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - }, - - makeClipping: function(element) { - element = $PR(element); - if (element._overflow) return; - element._overflow = element.style.overflow; - if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') - element.style.overflow = 'hidden'; - }, - - undoClipping: function(element) { - element = $PR(element); - if (element._overflow) return; - element.style.overflow = element._overflow; - element._overflow = undefined; - } -} - -Object.extend(Element, Element.Methods); - -var _nativeExtensions = false; - -if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - var HTMLElement = {} - HTMLElement.prototype = document.createElement('div').__proto__; -} - -Element.addMethods = function(methods) { - Object.extend(Element.Methods, methods || {}); - - if(typeof HTMLElement != 'undefined') { - var methods = Element.Methods, cache = Element.extend.cache; - for (property in methods) { - var value = methods[property]; - if (typeof value == 'function') - HTMLElement.prototype[property] = cache.findOrStore(value); - } - _nativeExtensions = true; - } -} - -Element.addMethods(); - -var Toggle = new Object(); -Toggle.display = Element.toggle; - -/*--------------------------------------------------------------------------*/ - -Abstract.Insertion = function(adjacency) { - this.adjacency = adjacency; -} - -Abstract.Insertion.prototype = { - initialize: function(element, content) { - this.element = $PR(element); - this.content = content.stripScripts(); - - if (this.adjacency && this.element.insertAdjacentHTML) { - try { - this.element.insertAdjacentHTML(this.adjacency, this.content); - } catch (e) { - var tagName = this.element.tagName.toLowerCase(); - if (tagName == 'tbody' || tagName == 'tr') { - this.insertContent(this.contentFromAnonymousTable()); - } else { - throw e; - } - } - } else { - this.range = this.element.ownerDocument.createRange(); - if (this.initializeRange) this.initializeRange(); - this.insertContent([this.range.createContextualFragment(this.content)]); - } - - setTimeout(function() {content.evalScripts()}, 10); - }, - - contentFromAnonymousTable: function() { - var div = document.createElement('div'); - div.innerHTML = '' + this.content + '
    '; - return $A(div.childNodes[0].childNodes[0].childNodes); - } -} - -var Insertion = new Object(); - -Insertion.Before = Class.create(); -Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { - initializeRange: function() { - this.range.setStartBefore(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, this.element); - }).bind(this)); - } -}); - -Insertion.Top = Class.create(); -Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(true); - }, - - insertContent: function(fragments) { - fragments.reverse(false).each((function(fragment) { - this.element.insertBefore(fragment, this.element.firstChild); - }).bind(this)); - } -}); - -Insertion.Bottom = Class.create(); -Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.appendChild(fragment); - }).bind(this)); - } -}); - -Insertion.After = Class.create(); -Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { - initializeRange: function() { - this.range.setStartAfter(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, - this.element.nextSibling); - }).bind(this)); - } -}); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $PR(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set(this.toArray().concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set(this.select(function(className) { - return className != classNameToRemove; - }).join(' ')); - }, - - toString: function() { - return this.toArray().join(' '); - } -} - -Object.extend(Element.ClassNames.prototype, Enumerable); -var Selector = Class.create(); -Selector.prototype = { - initialize: function(expression) { - this.params = {classNames: []}; - this.expression = expression.toString().strip(); - this.parseExpression(); - this.compileMatcher(); - }, - - parseExpression: function() { - function abort(message) { throw 'Parse error in selector: ' + message; } - - if (this.expression == '') abort('empty expression'); - - var params = this.params, expr = this.expression, match, modifier, clause, rest; - while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { - params.attributes = params.attributes || []; - params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); - expr = match[1]; - } - - if (expr == '*') return this.params.wildcard = true; - - while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { - modifier = match[1], clause = match[2], rest = match[3]; - switch (modifier) { - case '#': params.id = clause; break; - case '.': params.classNames.push(clause); break; - case '': - case undefined: params.tagName = clause.toUpperCase(); break; - default: abort(expr.inspect()); - } - expr = rest; - } - - if (expr.length > 0) abort(expr.inspect()); - }, - - buildMatchExpression: function() { - var params = this.params, conditions = [], clause; - - if (params.wildcard) - conditions.push('true'); - if (clause = params.id) - conditions.push('element.id == ' + clause.inspect()); - if (clause = params.tagName) - conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); - if ((clause = params.classNames).length > 0) - for (var i = 0; i < clause.length; i++) - conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')'); - if (clause = params.attributes) { - clause.each(function(attribute) { - var value = 'element.getAttribute(' + attribute.name.inspect() + ')'; - var splitValueBy = function(delimiter) { - return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; - } - - switch (attribute.operator) { - case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; - case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; - case '|=': conditions.push( - splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() - ); break; - case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; - case '': - case undefined: conditions.push(value + ' != null'); break; - default: throw 'Unknown operator ' + attribute.operator + ' in selector'; - } - }); - } - - return conditions.join(' && '); - }, - - compileMatcher: function() { - this.match = new Function('element', 'if (!element.tagName) return false; \ - return ' + this.buildMatchExpression()); - }, - - findElements: function(scope) { - var element; - - if (element = $PR(this.params.id)) - if (this.match(element)) - if (!scope || Element.childOf(element, scope)) - return [element]; - - scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); - - var results = []; - for (var i = 0; i < scope.length; i++) - if (this.match(element = scope[i])) - results.push(Element.extend(element)); - - return results; - }, - - toString: function() { - return this.expression; - } -} - -function $$() { - return $A(arguments).map(function(expression) { - return expression.strip().split(/\s+/).inject([null], function(results, expr) { - var selector = new Selector(expr); - return results.map(selector.findElements.bind(selector)).flatten(); - }); - }).flatten(); -} -var Field = { - clear: function() { - for (var i = 0; i < arguments.length; i++) - $PR(arguments[i]).value = ''; - }, - - focus: function(element) { - $PR(element).focus(); - }, - - present: function() { - for (var i = 0; i < arguments.length; i++) - if ($PR(arguments[i]).value == '') return false; - return true; - }, - - select: function(element) { - $PR(element).select(); - }, - - activate: function(element) { - element = $PR(element); - element.focus(); - if (element.select) - element.select(); - } -} - -/*--------------------------------------------------------------------------*/ - -var Form = { - serialize: function(form) { - var elements = Form.getElements($PR(form)); - var queryComponents = new Array(); - - for (var i = 0; i < elements.length; i++) { - var queryComponent = Form.Element.serialize(elements[i]); - if (queryComponent) - queryComponents.push(queryComponent); - } - - return queryComponents.join('&'); - }, - - getElements: function(form) { - form = $PR(form); - var elements = new Array(); - - for (var tagName in Form.Element.Serializers) { - var tagElements = form.getElementsByTagName(tagName); - for (var j = 0; j < tagElements.length; j++) - elements.push(tagElements[j]); - } - return elements; - }, - - getInputs: function(form, typeName, name) { - form = $PR(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) - return inputs; - - var matchingInputs = new Array(); - for (var i = 0; i < inputs.length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || - (name && input.name != name)) - continue; - matchingInputs.push(input); - } - - return matchingInputs; - }, - - disable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.blur(); - element.disabled = 'true'; - } - }, - - enable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.disabled = ''; - } - }, - - findFirstElement: function(form) { - return Form.getElements(form).find(function(element) { - return element.type != 'hidden' && !element.disabled && - ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - Field.activate(Form.findFirstElement(form)); - }, - - reset: function(form) { - $PR(form).reset(); - } -} - -Form.Element = { - serialize: function(element) { - element = $PR(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) { - var key = encodeURIComponent(parameter[0]); - if (key.length == 0) return; - - if (parameter[1].constructor != Array) - parameter[1] = [parameter[1]]; - - return parameter[1].map(function(value) { - return key + '=' + encodeURIComponent(value); - }).join('&'); - } - }, - - getValue: function(element) { - element = $PR(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) - return parameter[1]; - } -} - -Form.Element.Serializers = { - input: function(element) { - switch (element.type.toLowerCase()) { - case 'submit': - case 'hidden': - case 'password': - case 'text': - return Form.Element.Serializers.textarea(element); - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element); - } - return false; - }, - - inputSelector: function(element) { - if (element.checked) - return [element.name, element.value]; - }, - - textarea: function(element) { - return [element.name, element.value]; - }, - - select: function(element) { - return Form.Element.Serializers[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - }, - - selectOne: function(element) { - var value = '', opt, index = element.selectedIndex; - if (index >= 0) { - opt = element.options[index]; - value = opt.value || opt.text; - } - return [element.name, value]; - }, - - selectMany: function(element) { - var value = []; - for (var i = 0; i < element.length; i++) { - var opt = element.options[i]; - if (opt.selected) - value.push(opt.value || opt.text); - } - return [element.name, value]; - } -} - -/*--------------------------------------------------------------------------*/ - -var $F = Form.Element.getValue; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = function() {} -Abstract.TimedObserver.prototype = { - initialize: function(element, frequency, callback) { - this.frequency = frequency; - this.element = $PR(element); - this.callback = callback; - - this.lastValue = this.getValue(); - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - } -} - -Form.Element.Observer = Class.create(); -Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(); -Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = function() {} -Abstract.EventObserver.prototype = { - initialize: function(element, callback) { - this.element = $PR(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - var elements = Form.getElements(this.element); - for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - case 'password': - case 'text': - case 'textarea': - case 'select-one': - case 'select-multiple': - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -} - -Form.Element.EventObserver = Class.create(); -Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(); -Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) { - var Event = new Object(); -} - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - - element: function(event) { - return event.target || event.srcElement; - }, - - isLeftClick: function(event) { - return (((event.which) && (event.which == 1)) || - ((event.button) && (event.button == 1))); - }, - - pointerX: function(event) { - return event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)); - }, - - pointerY: function(event) { - return event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)); - }, - - stop: function(event) { - if (event.preventDefault) { - event.preventDefault(); - event.stopPropagation(); - } else { - event.returnValue = false; - event.cancelBubble = true; - } - }, - - // find the first node with the given tagName, starting from the - // node the event was triggered on; traverses the DOM upwards - findElement: function(event, tagName) { - var element = Event.element(event); - while (element.parentNode && (!element.tagName || - (element.tagName.toUpperCase() != tagName.toUpperCase()))) - element = element.parentNode; - return element; - }, - - observers: false, - - _observeAndCache: function(element, name, observer, useCapture) { - if (!this.observers) this.observers = []; - if (element.addEventListener) { - this.observers.push([element, name, observer, useCapture]); - element.addEventListener(name, observer, useCapture); - } else if (element.attachEvent) { - this.observers.push([element, name, observer, useCapture]); - element.attachEvent('on' + name, observer); - } - }, - - unloadCache: function() { - if (!Event.observers) return; - for (var i = 0; i < Event.observers.length; i++) { - Event.stopObserving.apply(this, Event.observers[i]); - Event.observers[i][0] = null; - } - Event.observers = false; - }, - - observe: function(element, name, observer, useCapture) { - var element = $PR(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) - name = 'keydown'; - - this._observeAndCache(element, name, observer, useCapture); - }, - - stopObserving: function(element, name, observer, useCapture) { - var element = $PR(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.detachEvent)) - name = 'keydown'; - - if (element.removeEventListener) { - element.removeEventListener(name, observer, useCapture); - } else if (element.detachEvent) { - element.detachEvent('on' + name, observer); - } - } -}); - -/* prevent memory leaks in IE */ -if (navigator.appVersion.match(/\bMSIE\b/)) - Event.observe(window, 'unload', Event.unloadCache, false); -var Position = { - // set to true if needed, warning: firefox performance problems - // NOT neeeded for page scrolling, only if draggable contained in - // scrollable elements - includeScrollOffsets: false, - - // must be called before calling withinIncludingScrolloffset, every time the - // page is scrolled - prepare: function() { - this.deltaX = window.pageXOffset - || document.documentElement.scrollLeft - || document.body.scrollLeft - || 0; - this.deltaY = window.pageYOffset - || document.documentElement.scrollTop - || document.body.scrollTop - || 0; - }, - - realOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return [valueL, valueT]; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return [valueL, valueT]; - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; - } - } while (element); - return [valueL, valueT]; - }, - - offsetParent: function(element) { - if (element.offsetParent) return element.offsetParent; - if (element == document.body) return element; - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return element; - - return document.body; - }, - - // caches x/y coordinate pair to use with overlap - within: function(element, x, y) { - if (this.includeScrollOffsets) - return this.withinIncludingScrolloffsets(element, x, y); - this.xcomp = x; - this.ycomp = y; - this.offset = this.cumulativeOffset(element); - - return (y >= this.offset[1] && - y < this.offset[1] + element.offsetHeight && - x >= this.offset[0] && - x < this.offset[0] + element.offsetWidth); - }, - - withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = this.realOffset(element); - - this.xcomp = x + offsetcache[0] - this.deltaX; - this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = this.cumulativeOffset(element); - - return (this.ycomp >= this.offset[1] && - this.ycomp < this.offset[1] + element.offsetHeight && - this.xcomp >= this.offset[0] && - this.xcomp < this.offset[0] + element.offsetWidth); - }, - - // within must be called directly before - overlap: function(mode, element) { - if (!mode) return 0; - if (mode == 'vertical') - return ((this.offset[1] + element.offsetHeight) - this.ycomp) / - element.offsetHeight; - if (mode == 'horizontal') - return ((this.offset[0] + element.offsetWidth) - this.xcomp) / - element.offsetWidth; - }, - - clone: function(source, target) { - source = $PR(source); - target = $PR(target); - target.style.position = 'absolute'; - var offsets = this.cumulativeOffset(source); - target.style.top = offsets[1] + 'px'; - target.style.left = offsets[0] + 'px'; - target.style.width = source.offsetWidth + 'px'; - target.style.height = source.offsetHeight + 'px'; - }, - - page: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent==document.body) - if (Element.getStyle(element,'position')=='absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } while (element = element.parentNode); - - return [valueL, valueT]; - }, - - clone: function(source, target) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || {}) - - // find page position of source - source = $PR(source); - var p = Position.page(source); - - // find coordinate system to use - target = $PR(target); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(target,'position') == 'absolute') { - parent = Position.offsetParent(target); - delta = Position.page(parent); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if(options.setWidth) target.style.width = source.offsetWidth + 'px'; - if(options.setHeight) target.style.height = source.offsetHeight + 'px'; - }, - - absolutize: function(element) { - element = $PR(element); - if (element.style.position == 'absolute') return; - Position.prepare(); - - var offsets = Position.positionedOffset(element); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px';; - element.style.left = left + 'px';; - element.style.width = width + 'px';; - element.style.height = height + 'px';; - }, - - relativize: function(element) { - element = $PR(element); - if (element.style.position == 'relative') return; - Position.prepare(); - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - } -} - -// Safari returns margins on body which is incorrect if the child is absolutely -// positioned. For performance reasons, redefine Position.cumulativeOffset for -// KHTML/WebKit only. -if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - Position.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return [valueL, valueT]; - } -} diff --git a/view/js/cropper/lib/scriptaculous.js b/view/js/cropper/lib/scriptaculous.js deleted file mode 100644 index f61fc57f74..0000000000 --- a/view/js/cropper/lib/scriptaculous.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// -// 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. - -var Scriptaculous = { - Version: '1.6.1', - require: function(libraryName) { - // inserting via DOM fails in Safari 2.0, so brute force approach - document.write(''); - }, - load: function() { - if((typeof Prototype=='undefined') || - (typeof Element == 'undefined') || - (typeof Element.Methods=='undefined') || - parseFloat(Prototype.Version.split(".")[0] + "." + - Prototype.Version.split(".")[1]) < 1.5) - throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0"); - - $A(document.getElementsByTagName("script")).findAll( function(s) { - return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/)) - }).each( function(s) { - var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,''); - var includes = s.src.match(/\?.*load=([a-z,]*)/); - (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each( - function(include) { Scriptaculous.require(path+include+'.js') }); - }); - } -} - -Scriptaculous.load(); \ No newline at end of file diff --git a/view/js/cropper/lib/slider.js b/view/js/cropper/lib/slider.js deleted file mode 100644 index cd16b692d6..0000000000 --- a/view/js/cropper/lib/slider.js +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright (c) 2005 Marty Haught, Thomas Fuchs -// -// See http://script.aculo.us for more info -// -// 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. - -if(!Control) var Control = {}; -Control.Slider = Class.create(); - -// options: -// axis: 'vertical', or 'horizontal' (default) -// -// callbacks: -// onChange(value) -// onSlide(value) -Control.Slider.prototype = { - initialize: function(handle, track, options) { - var slider = this; - - if(handle instanceof Array) { - this.handles = handle.collect( function(e) { return $PR(e) }); - } else { - this.handles = [$PR(handle)]; - } - - this.track = $PR(track); - this.options = options || {}; - - this.axis = this.options.axis || 'horizontal'; - this.increment = this.options.increment || 1; - this.step = parseInt(this.options.step || '1'); - this.range = this.options.range || $R(0,1); - - this.value = 0; // assure backwards compat - this.values = this.handles.map( function() { return 0 }); - this.spans = this.options.spans ? this.options.spans.map(function(s){ return $PR(s) }) : false; - this.options.startSpan = $PR(this.options.startSpan || null); - this.options.endSpan = $PR(this.options.endSpan || null); - - this.restricted = this.options.restricted || false; - - this.maximum = this.options.maximum || this.range.end; - this.minimum = this.options.minimum || this.range.start; - - // Will be used to align the handle onto the track, if necessary - this.alignX = parseInt(this.options.alignX || '0'); - this.alignY = parseInt(this.options.alignY || '0'); - - this.trackLength = this.maximumOffset() - this.minimumOffset(); - this.handleLength = this.isVertical() ? this.handles[0].offsetHeight : this.handles[0].offsetWidth; - - this.active = false; - this.dragging = false; - this.disabled = false; - - if(this.options.disabled) this.setDisabled(); - - // Allowed values array - this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false; - if(this.allowedValues) { - this.minimum = this.allowedValues.min(); - this.maximum = this.allowedValues.max(); - } - - this.eventMouseDown = this.startDrag.bindAsEventListener(this); - this.eventMouseUp = this.endDrag.bindAsEventListener(this); - this.eventMouseMove = this.update.bindAsEventListener(this); - - // Initialize handles in reverse (make sure first handle is active) - this.handles.each( function(h,i) { - i = slider.handles.length-1-i; - slider.setValue(parseFloat( - (slider.options.sliderValue instanceof Array ? - slider.options.sliderValue[i] : slider.options.sliderValue) || - slider.range.start), i); - Element.makePositioned(h); // fix IE - Event.observe(h, "mousedown", slider.eventMouseDown); - }); - - Event.observe(this.track, "mousedown", this.eventMouseDown); - Event.observe(document, "mouseup", this.eventMouseUp); - Event.observe(document, "mousemove", this.eventMouseMove); - - this.initialized = true; - }, - dispose: function() { - var slider = this; - Event.stopObserving(this.track, "mousedown", this.eventMouseDown); - Event.stopObserving(document, "mouseup", this.eventMouseUp); - Event.stopObserving(document, "mousemove", this.eventMouseMove); - this.handles.each( function(h) { - Event.stopObserving(h, "mousedown", slider.eventMouseDown); - }); - }, - setDisabled: function(){ - this.disabled = true; - }, - setEnabled: function(){ - this.disabled = false; - }, - getNearestValue: function(value){ - if(this.allowedValues){ - if(value >= this.allowedValues.max()) return(this.allowedValues.max()); - if(value <= this.allowedValues.min()) return(this.allowedValues.min()); - - var offset = Math.abs(this.allowedValues[0] - value); - var newValue = this.allowedValues[0]; - this.allowedValues.each( function(v) { - var currentOffset = Math.abs(v - value); - if(currentOffset <= offset){ - newValue = v; - offset = currentOffset; - } - }); - return newValue; - } - if(value > this.range.end) return this.range.end; - if(value < this.range.start) return this.range.start; - return value; - }, - setValue: function(sliderValue, handleIdx){ - if(!this.active) { - this.activeHandle = this.handles[handleIdx]; - this.activeHandleIdx = handleIdx; - this.updateStyles(); - } - handleIdx = handleIdx || this.activeHandleIdx || 0; - if(this.initialized && this.restricted) { - if((handleIdx>0) && (sliderValuethis.values[handleIdx+1])) - sliderValue = this.values[handleIdx+1]; - } - sliderValue = this.getNearestValue(sliderValue); - this.values[handleIdx] = sliderValue; - this.value = this.values[0]; // assure backwards compat - - this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = - this.translateToPx(sliderValue); - - this.drawSpans(); - if(!this.dragging || !this.event) this.updateFinished(); - }, - setValueBy: function(delta, handleIdx) { - this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, - handleIdx || this.activeHandleIdx || 0); - }, - translateToPx: function(value) { - return Math.round( - ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) * - (value - this.range.start)) + "px"; - }, - translateToValue: function(offset) { - return ((offset/(this.trackLength-this.handleLength) * - (this.range.end-this.range.start)) + this.range.start); - }, - getRange: function(range) { - var v = this.values.sortBy(Prototype.K); - range = range || 0; - return $R(v[range],v[range+1]); - }, - minimumOffset: function(){ - return(this.isVertical() ? this.alignY : this.alignX); - }, - maximumOffset: function(){ - return(this.isVertical() ? - this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX); - }, - isVertical: function(){ - return (this.axis == 'vertical'); - }, - drawSpans: function() { - var slider = this; - if(this.spans) - $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) }); - if(this.options.startSpan) - this.setSpan(this.options.startSpan, - $R(0, this.values.length>1 ? this.getRange(0).min() : this.value )); - if(this.options.endSpan) - this.setSpan(this.options.endSpan, - $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum)); - }, - setSpan: function(span, range) { - if(this.isVertical()) { - span.style.top = this.translateToPx(range.start); - span.style.height = this.translateToPx(range.end - range.start + this.range.start); - } else { - span.style.left = this.translateToPx(range.start); - span.style.width = this.translateToPx(range.end - range.start + this.range.start); - } - }, - updateStyles: function() { - this.handles.each( function(h){ Element.removeClassName(h, 'selected') }); - Element.addClassName(this.activeHandle, 'selected'); - }, - startDrag: function(event) { - if(Event.isLeftClick(event)) { - if(!this.disabled){ - this.active = true; - - var handle = Event.element(event); - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - if(handle==this.track) { - var offsets = Position.cumulativeOffset(this.track); - this.event = event; - this.setValue(this.translateToValue( - (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2) - )); - var offsets = Position.cumulativeOffset(this.activeHandle); - this.offsetX = (pointer[0] - offsets[0]); - this.offsetY = (pointer[1] - offsets[1]); - } else { - // find the handle (prevents issues with Safari) - while((this.handles.indexOf(handle) == -1) && handle.parentNode) - handle = handle.parentNode; - - this.activeHandle = handle; - this.activeHandleIdx = this.handles.indexOf(this.activeHandle); - this.updateStyles(); - - var offsets = Position.cumulativeOffset(this.activeHandle); - this.offsetX = (pointer[0] - offsets[0]); - this.offsetY = (pointer[1] - offsets[1]); - } - } - Event.stop(event); - } - }, - update: function(event) { - if(this.active) { - if(!this.dragging) this.dragging = true; - this.draw(event); - // fix AppleWebKit rendering - if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); - Event.stop(event); - } - }, - draw: function(event) { - var pointer = [Event.pointerX(event), Event.pointerY(event)]; - var offsets = Position.cumulativeOffset(this.track); - pointer[0] -= this.offsetX + offsets[0]; - pointer[1] -= this.offsetY + offsets[1]; - this.event = event; - this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] )); - if(this.initialized && this.options.onSlide) - this.options.onSlide(this.values.length>1 ? this.values : this.value, this); - }, - endDrag: function(event) { - if(this.active && this.dragging) { - this.finishDrag(event, true); - Event.stop(event); - } - this.active = false; - this.dragging = false; - }, - finishDrag: function(event, success) { - this.active = false; - this.dragging = false; - this.updateFinished(); - }, - updateFinished: function() { - if(this.initialized && this.options.onChange) - this.options.onChange(this.values.length>1 ? this.values : this.value, this); - this.event = null; - } -} diff --git a/view/js/cropper/lib/unittest.js b/view/js/cropper/lib/unittest.js deleted file mode 100644 index be0d252273..0000000000 --- a/view/js/cropper/lib/unittest.js +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) -// (c) 2005 Jon Tirsen (http://www.tirsen.com) -// (c) 2005 Michael Schuerig (http://www.schuerig.de/michael/) -// -// 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. - - -// experimental, Firefox-only -Event.simulateMouse = function(element, eventName) { - var options = Object.extend({ - pointerX: 0, - pointerY: 0, - buttons: 0 - }, arguments[2] || {}); - var oEvent = document.createEvent("MouseEvents"); - oEvent.initMouseEvent(eventName, true, true, document.defaultView, - options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY, - false, false, false, false, 0, $PR(element)); - - if(this.mark) Element.remove(this.mark); - this.mark = document.createElement('div'); - this.mark.appendChild(document.createTextNode(" ")); - document.body.appendChild(this.mark); - this.mark.style.position = 'absolute'; - this.mark.style.top = options.pointerY + "px"; - this.mark.style.left = options.pointerX + "px"; - this.mark.style.width = "5px"; - this.mark.style.height = "5px;"; - this.mark.style.borderTop = "1px solid red;" - this.mark.style.borderLeft = "1px solid red;" - - if(this.step) - alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options)); - - $PR(element).dispatchEvent(oEvent); -}; - -// Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2. -// You need to downgrade to 1.0.4 for now to get this working -// See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much -Event.simulateKey = function(element, eventName) { - var options = Object.extend({ - ctrlKey: false, - altKey: false, - shiftKey: false, - metaKey: false, - keyCode: 0, - charCode: 0 - }, arguments[2] || {}); - - var oEvent = document.createEvent("KeyEvents"); - oEvent.initKeyEvent(eventName, true, true, window, - options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, - options.keyCode, options.charCode ); - $PR(element).dispatchEvent(oEvent); -}; - -Event.simulateKeys = function(element, command) { - for(var i=0; i' + - '' + - '' + - '' + - '
    StatusTestMessage
    '; - this.logsummary = $PR('logsummary') - this.loglines = $PR('loglines'); - }, - _toHTML: function(txt) { - return txt.escapeHTML().replace(/\n/g,"
    "); - } -} - -Test.Unit.Runner = Class.create(); -Test.Unit.Runner.prototype = { - initialize: function(testcases) { - this.options = Object.extend({ - testLog: 'testlog' - }, arguments[1] || {}); - this.options.resultsURL = this.parseResultsURLQueryParameter(); - if (this.options.testLog) { - this.options.testLog = $PR(this.options.testLog) || null; - } - if(this.options.tests) { - this.tests = []; - for(var i = 0; i < this.options.tests.length; i++) { - if(/^test/.test(this.options.tests[i])) { - this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"])); - } - } - } else { - if (this.options.test) { - this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])]; - } else { - this.tests = []; - for(var testcase in testcases) { - if(/^test/.test(testcase)) { - this.tests.push(new Test.Unit.Testcase(testcase, testcases[testcase], testcases["setup"], testcases["teardown"])); - } - } - } - } - this.currentTest = 0; - this.logger = new Test.Unit.Logger(this.options.testLog); - setTimeout(this.runTests.bind(this), 1000); - }, - parseResultsURLQueryParameter: function() { - return window.location.search.parseQuery()["resultsURL"]; - }, - // Returns: - // "ERROR" if there was an error, - // "FAILURE" if there was a failure, or - // "SUCCESS" if there was neither - getResult: function() { - var hasFailure = false; - for(var i=0;i 0) { - return "ERROR"; - } - if (this.tests[i].failures > 0) { - hasFailure = true; - } - } - if (hasFailure) { - return "FAILURE"; - } else { - return "SUCCESS"; - } - }, - postResults: function() { - if (this.options.resultsURL) { - new Ajax.Request(this.options.resultsURL, - { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false }); - } - }, - runTests: function() { - var test = this.tests[this.currentTest]; - if (!test) { - // finished! - this.postResults(); - this.logger.summary(this.summary()); - return; - } - if(!test.isWaiting) { - this.logger.start(test.name); - } - test.run(); - if(test.isWaiting) { - this.logger.message("Waiting for " + test.timeToWait + "ms"); - setTimeout(this.runTests.bind(this), test.timeToWait || 1000); - } else { - this.logger.finish(test.status(), test.summary()); - this.currentTest++; - // tail recursive, hopefully the browser will skip the stackframe - this.runTests(); - } - }, - summary: function() { - var assertions = 0; - var failures = 0; - var errors = 0; - var messages = []; - for(var i=0;i 0) return 'failed'; - if (this.errors > 0) return 'error'; - return 'passed'; - }, - assert: function(expression) { - var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"'; - try { expression ? this.pass() : - this.fail(message); } - catch(e) { this.error(e); } - }, - assertEqual: function(expected, actual) { - var message = arguments[2] || "assertEqual"; - try { (expected == actual) ? this.pass() : - this.fail(message + ': expected "' + Test.Unit.inspect(expected) + - '", actual "' + Test.Unit.inspect(actual) + '"'); } - catch(e) { this.error(e); } - }, - assertEnumEqual: function(expected, actual) { - var message = arguments[2] || "assertEnumEqual"; - try { $A(expected).length == $A(actual).length && - expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ? - this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) + - ', actual ' + Test.Unit.inspect(actual)); } - catch(e) { this.error(e); } - }, - assertNotEqual: function(expected, actual) { - var message = arguments[2] || "assertNotEqual"; - try { (expected != actual) ? this.pass() : - this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); } - catch(e) { this.error(e); } - }, - assertNull: function(obj) { - var message = arguments[1] || 'assertNull' - try { (obj==null) ? this.pass() : - this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); } - catch(e) { this.error(e); } - }, - assertHidden: function(element) { - var message = arguments[1] || 'assertHidden'; - this.assertEqual("none", element.style.display, message); - }, - assertNotNull: function(object) { - var message = arguments[1] || 'assertNotNull'; - this.assert(object != null, message); - }, - assertInstanceOf: function(expected, actual) { - var message = arguments[2] || 'assertInstanceOf'; - try { - (actual instanceof expected) ? this.pass() : - this.fail(message + ": object was not an instance of the expected type"); } - catch(e) { this.error(e); } - }, - assertNotInstanceOf: function(expected, actual) { - var message = arguments[2] || 'assertNotInstanceOf'; - try { - !(actual instanceof expected) ? this.pass() : - this.fail(message + ": object was an instance of the not expected type"); } - catch(e) { this.error(e); } - }, - _isVisible: function(element) { - element = $PR(element); - if(!element.parentNode) return true; - this.assertNotNull(element); - if(element.style && Element.getStyle(element, 'display') == 'none') - return false; - - return this._isVisible(element.parentNode); - }, - assertNotVisible: function(element) { - this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1])); - }, - assertVisible: function(element) { - this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1])); - }, - benchmark: function(operation, iterations) { - var startAt = new Date(); - (iterations || 1).times(operation); - var timeTaken = ((new Date())-startAt); - this.info((arguments[2] || 'Operation') + ' finished ' + - iterations + ' iterations in ' + (timeTaken/1000)+'s' ); - return timeTaken; - } -} - -Test.Unit.Testcase = Class.create(); -Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), { - initialize: function(name, test, setup, teardown) { - Test.Unit.Assertions.prototype.initialize.bind(this)(); - this.name = name; - this.test = test || function() {}; - this.setup = setup || function() {}; - this.teardown = teardown || function() {}; - this.isWaiting = false; - this.timeToWait = 1000; - }, - wait: function(time, nextPart) { - this.isWaiting = true; - this.test = nextPart; - this.timeToWait = time; - }, - run: function() { - try { - try { - if (!this.isWaiting) this.setup.bind(this)(); - this.isWaiting = false; - this.test.bind(this)(); - } finally { - if(!this.isWaiting) { - this.teardown.bind(this)(); - } - } - } - catch(e) { this.error(e); } - } -}); diff --git a/view/js/cropper/licence.txt b/view/js/cropper/licence.txt deleted file mode 100644 index b59e029176..0000000000 --- a/view/js/cropper/licence.txt +++ /dev/null @@ -1,12 +0,0 @@ -Copyright (c) 2006, David Spurr (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 \ No newline at end of file diff --git a/view/js/cropper/marqueeHoriz.gif b/view/js/cropper/marqueeHoriz.gif deleted file mode 100644 index 25317e5738bfcce43707ec0a0640533f69eb8fff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1125 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 PPffC!10NW#8L$7@U6jV2 diff --git a/view/js/cropper/tests/castleMed.jpg b/view/js/cropper/tests/castleMed.jpg deleted file mode 100644 index c35a6f554a21eb62f3c3e3580e616a4feee8748c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50584 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%0Dl3VwBB+R7y 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 RJ3V^U{{ZIRKl@F8|Jg7^TQ~p! diff --git a/view/js/cropper/tests/example-Basic.htm b/view/js/cropper/tests/example-Basic.htm deleted file mode 100644 index 2a55eca5ab..0000000000 --- a/view/js/cropper/tests/example-Basic.htm +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - Basic cropper test - - - - - - - - - - -

    Basic cropper test

    -

    - Some test content before the image -

    - -
    - test image -
    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - - - - - diff --git a/view/js/cropper/tests/example-CSS-Absolute.htm b/view/js/cropper/tests/example-CSS-Absolute.htm deleted file mode 100644 index b605fd344d..0000000000 --- a/view/js/cropper/tests/example-CSS-Absolute.htm +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - CSS - Absolute positioned (and draggable) test - - - - - - - - - - -

    CSS - Absolute positioned (and draggable) test

    -

    - Some test content before the image -

    -

    - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque consequat risus cursus ipsum. Etiam libero. Integer vel mauris. Donec vulputate. In ut augue vitae nibh lobortis tempor. Aliquam hendrerit quam. Phasellus sed orci. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut sed urna. Donec nunc urna, porttitor a, feugiat pellentesque, varius id, justo. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla facilisi. Sed sollicitudin. Integer enim. Aenean sollicitudin. -

    -

    - Integer lorem turpis, dapibus sed, vulputate nec, volutpat a, sem. Sed malesuada laoreet lorem. Duis mauris ipsum, fringilla nec, tristique vel, imperdiet vel, neque. Nulla vel purus. Fusce non lectus. Mauris pulvinar. Curabitur eget eros. Nunc ultrices, risus vitae adipiscing scelerisque, quam mi auctor lacus, non pellentesque augue sapien a magna. Etiam rutrum posuere tortor. Mauris rhoncus sagittis dolor. Donec sed quam. Vivamus vel diam id massa adipiscing bibendum. Suspendisse potenti. Integer arcu est, adipiscing sit amet, convallis eu, sollicitudin tincidunt, quam. -

    -

    - Etiam ligula lorem, imperdiet ac, luctus eget, ultrices at, odio. Vivamus malesuada, justo eu adipiscing semper, nisi dui tempus magna, quis ultrices nunc tellus id massa. Nullam lobortis auctor sapien. Quisque non nulla. Donec lobortis pellentesque nisl. Sed lacus sapien, viverra vitae, blandit ut, fermentum quis, leo. Morbi augue turpis, hendrerit non, feugiat vel, laoreet sed, est. Nunc velit. Praesent lobortis. Integer enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur faucibus lacus ac ante. Donec odio odio, tincidunt a, egestas nec, scelerisque nec, dui. Cras sollicitudin. Donec lacus enim, mollis sit amet, interdum quis, euismod et, nulla. Nunc sit amet dui eu magna dapibus mollis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla facilisi. -

    -

    - In hac habitasse platea dictumst. Nunc neque urna, dapibus ut, tristique ut, bibendum ac, felis. Donec dictum est ut dolor. Etiam accumsan, velit sit amet blandit vestibulum, turpis quam hendrerit risus, vel interdum eros orci in nunc. Curabitur tellus sapien, rutrum ac, euismod ac, malesuada nec, pede. Proin sit amet ipsum. Praesent quam nisl, adipiscing nec, tristique eget, fermentum sed, est. Praesent ac est sit amet orci facilisis placerat. Sed consequat, est sit amet consectetuer viverra, risus urna porttitor tellus, ut convallis nibh libero in lectus. Pellentesque molestie, erat non vehicula pretium, turpis nisi eleifend eros, sed scelerisque tortor odio non tellus. Nunc leo tellus, faucibus vitae, placerat a, accumsan vel, arcu. In et orci. Ut tristique euismod nibh. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Sed nulla nunc, placerat vitae, pellentesque non, interdum non, sapien. Quisque faucibus, eros sed venenatis sagittis, leo risus rhoncus risus, in pretium sem purus a lacus. Aliquam aliquam leo et diam. - -

    -

    - Nulla sagittis diam. Phasellus vitae enim tristique libero molestie tristique. Nam mauris sem, elementum nec, cursus in, fringilla ac, neque. Nunc metus nisi, dictum vel, vulputate quis, porttitor bibendum, tortor. Vestibulum vehicula. Nulla facilisi. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla ac magna sed purus ultricies euismod. Aliquam dictum. Sed mauris. Suspendisse justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi purus lorem, auctor non, porta ac, vehicula vel, orci. Morbi pharetra massa nec leo. Maecenas et mauris. Aliquam porttitor tincidunt nulla. Vestibulum pede. -

    -

    - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque consequat risus cursus ipsum. Etiam libero. Integer vel mauris. Donec vulputate. In ut augue vitae nibh lobortis tempor. Aliquam hendrerit quam. Phasellus sed orci. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut sed urna. Donec nunc urna, porttitor a, feugiat pellentesque, varius id, justo. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla facilisi. Sed sollicitudin. Integer enim. Aenean sollicitudin. -

    -

    - Integer lorem turpis, dapibus sed, vulputate nec, volutpat a, sem. Sed malesuada laoreet lorem. Duis mauris ipsum, fringilla nec, tristique vel, imperdiet vel, neque. Nulla vel purus. Fusce non lectus. Mauris pulvinar. Curabitur eget eros. Nunc ultrices, risus vitae adipiscing scelerisque, quam mi auctor lacus, non pellentesque augue sapien a magna. Etiam rutrum posuere tortor. Mauris rhoncus sagittis dolor. Donec sed quam. Vivamus vel diam id massa adipiscing bibendum. Suspendisse potenti. Integer arcu est, adipiscing sit amet, convallis eu, sollicitudin tincidunt, quam. -

    -

    - Etiam ligula lorem, imperdiet ac, luctus eget, ultrices at, odio. Vivamus malesuada, justo eu adipiscing semper, nisi dui tempus magna, quis ultrices nunc tellus id massa. Nullam lobortis auctor sapien. Quisque non nulla. Donec lobortis pellentesque nisl. Sed lacus sapien, viverra vitae, blandit ut, fermentum quis, leo. Morbi augue turpis, hendrerit non, feugiat vel, laoreet sed, est. Nunc velit. Praesent lobortis. Integer enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur faucibus lacus ac ante. Donec odio odio, tincidunt a, egestas nec, scelerisque nec, dui. Cras sollicitudin. Donec lacus enim, mollis sit amet, interdum quis, euismod et, nulla. Nunc sit amet dui eu magna dapibus mollis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla facilisi. -

    -

    - In hac habitasse platea dictumst. Nunc neque urna, dapibus ut, tristique ut, bibendum ac, felis. Donec dictum est ut dolor. Etiam accumsan, velit sit amet blandit vestibulum, turpis quam hendrerit risus, vel interdum eros orci in nunc. Curabitur tellus sapien, rutrum ac, euismod ac, malesuada nec, pede. Proin sit amet ipsum. Praesent quam nisl, adipiscing nec, tristique eget, fermentum sed, est. Praesent ac est sit amet orci facilisis placerat. Sed consequat, est sit amet consectetuer viverra, risus urna porttitor tellus, ut convallis nibh libero in lectus. Pellentesque molestie, erat non vehicula pretium, turpis nisi eleifend eros, sed scelerisque tortor odio non tellus. Nunc leo tellus, faucibus vitae, placerat a, accumsan vel, arcu. In et orci. Ut tristique euismod nibh. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Sed nulla nunc, placerat vitae, pellentesque non, interdum non, sapien. Quisque faucibus, eros sed venenatis sagittis, leo risus rhoncus risus, in pretium sem purus a lacus. Aliquam aliquam leo et diam. - -

    -

    - Nulla sagittis diam. Phasellus vitae enim tristique libero molestie tristique. Nam mauris sem, elementum nec, cursus in, fringilla ac, neque. Nunc metus nisi, dictum vel, vulputate quis, porttitor bibendum, tortor. Vestibulum vehicula. Nulla facilisi. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla ac magna sed purus ultricies euismod. Aliquam dictum. Sed mauris. Suspendisse justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi purus lorem, auctor non, porta ac, vehicula vel, orci. Morbi pharetra massa nec leo. Maecenas et mauris. Aliquam porttitor tincidunt nulla. Vestibulum pede. -

    -

    - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque consequat risus cursus ipsum. Etiam libero. Integer vel mauris. Donec vulputate. In ut augue vitae nibh lobortis tempor. Aliquam hendrerit quam. Phasellus sed orci. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut sed urna. Donec nunc urna, porttitor a, feugiat pellentesque, varius id, justo. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla facilisi. Sed sollicitudin. Integer enim. Aenean sollicitudin. -

    -

    - Integer lorem turpis, dapibus sed, vulputate nec, volutpat a, sem. Sed malesuada laoreet lorem. Duis mauris ipsum, fringilla nec, tristique vel, imperdiet vel, neque. Nulla vel purus. Fusce non lectus. Mauris pulvinar. Curabitur eget eros. Nunc ultrices, risus vitae adipiscing scelerisque, quam mi auctor lacus, non pellentesque augue sapien a magna. Etiam rutrum posuere tortor. Mauris rhoncus sagittis dolor. Donec sed quam. Vivamus vel diam id massa adipiscing bibendum. Suspendisse potenti. Integer arcu est, adipiscing sit amet, convallis eu, sollicitudin tincidunt, quam. -

    -

    - Etiam ligula lorem, imperdiet ac, luctus eget, ultrices at, odio. Vivamus malesuada, justo eu adipiscing semper, nisi dui tempus magna, quis ultrices nunc tellus id massa. Nullam lobortis auctor sapien. Quisque non nulla. Donec lobortis pellentesque nisl. Sed lacus sapien, viverra vitae, blandit ut, fermentum quis, leo. Morbi augue turpis, hendrerit non, feugiat vel, laoreet sed, est. Nunc velit. Praesent lobortis. Integer enim. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Curabitur faucibus lacus ac ante. Donec odio odio, tincidunt a, egestas nec, scelerisque nec, dui. Cras sollicitudin. Donec lacus enim, mollis sit amet, interdum quis, euismod et, nulla. Nunc sit amet dui eu magna dapibus mollis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla facilisi. -

    -

    - In hac habitasse platea dictumst. Nunc neque urna, dapibus ut, tristique ut, bibendum ac, felis. Donec dictum est ut dolor. Etiam accumsan, velit sit amet blandit vestibulum, turpis quam hendrerit risus, vel interdum eros orci in nunc. Curabitur tellus sapien, rutrum ac, euismod ac, malesuada nec, pede. Proin sit amet ipsum. Praesent quam nisl, adipiscing nec, tristique eget, fermentum sed, est. Praesent ac est sit amet orci facilisis placerat. Sed consequat, est sit amet consectetuer viverra, risus urna porttitor tellus, ut convallis nibh libero in lectus. Pellentesque molestie, erat non vehicula pretium, turpis nisi eleifend eros, sed scelerisque tortor odio non tellus. Nunc leo tellus, faucibus vitae, placerat a, accumsan vel, arcu. In et orci. Ut tristique euismod nibh. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Sed nulla nunc, placerat vitae, pellentesque non, interdum non, sapien. Quisque faucibus, eros sed venenatis sagittis, leo risus rhoncus risus, in pretium sem purus a lacus. Aliquam aliquam leo et diam. - -

    -

    - Nulla sagittis diam. Phasellus vitae enim tristique libero molestie tristique. Nam mauris sem, elementum nec, cursus in, fringilla ac, neque. Nunc metus nisi, dictum vel, vulputate quis, porttitor bibendum, tortor. Vestibulum vehicula. Nulla facilisi. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla ac magna sed purus ultricies euismod. Aliquam dictum. Sed mauris. Suspendisse justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi purus lorem, auctor non, porta ac, vehicula vel, orci. Morbi pharetra massa nec leo. Maecenas et mauris. Aliquam porttitor tincidunt nulla. Vestibulum pede. -

    - - -
    -

    Absolute test

    -
    - test image -
    - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -
    - - - - - diff --git a/view/js/cropper/tests/example-CSS-Float.htm b/view/js/cropper/tests/example-CSS-Float.htm deleted file mode 100644 index 3dbeeab4b1..0000000000 --- a/view/js/cropper/tests/example-CSS-Float.htm +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - CSS - Float test - - - - - - - - - - -

    Test page with floating wrapper

    -

    - Some test content before the image -

    - -
    -

    Float test

    -
    - test image -
    - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -
    - - - - - diff --git a/view/js/cropper/tests/example-CSS-Relative.htm b/view/js/cropper/tests/example-CSS-Relative.htm deleted file mode 100644 index ecad1341a6..0000000000 --- a/view/js/cropper/tests/example-CSS-Relative.htm +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - CSS - Relative test - - - - - - - - - - -

    Test page with relatively positioned wrapper

    -

    - Some test content before the image -

    - -
    -

    Relative test

    -
    - test image -
    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -
    - - - - - diff --git a/view/js/cropper/tests/example-CoordsOnLoad.htm b/view/js/cropper/tests/example-CoordsOnLoad.htm deleted file mode 100644 index c14289c2de..0000000000 --- a/view/js/cropper/tests/example-CoordsOnLoad.htm +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - Loading & displaying co-ordinates of crop area on attachment test - - - - - - - - - - -

    Loading & displaying co-ordinates of crop area on attachment test

    -

    - Some test content before the image -

    - -
    - test image -
    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - - - - - diff --git a/view/js/cropper/tests/example-CoordsOnLoadWithRatio.htm b/view/js/cropper/tests/example-CoordsOnLoadWithRatio.htm deleted file mode 100644 index 9ba02da111..0000000000 --- a/view/js/cropper/tests/example-CoordsOnLoadWithRatio.htm +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - Loading & displaying co-ordinates (with ratio) of crop area on attachment test< - - - - - - - - - - -

    Loading & displaying co-ordinates (with ratio) of crop area on attachment test

    -

    - Some test content before the image -

    - -
    - test image -
    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - - - - - diff --git a/view/js/cropper/tests/example-Dimensions.htm b/view/js/cropper/tests/example-Dimensions.htm deleted file mode 100644 index 10e5ba26ca..0000000000 --- a/view/js/cropper/tests/example-Dimensions.htm +++ /dev/null @@ -1,225 +0,0 @@ - - - - - - Different dimensions test - - - - - - - - - - -

    Multiple dimensions tests

    -

    - Test of applying different dimension restrictions to the cropper -

    - -
    -
    - Set the cropper with the following dimension restrictions: -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - -
    -
    - -
    - test image -
    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - - - - - diff --git a/view/js/cropper/tests/example-DynamicImage.htm b/view/js/cropper/tests/example-DynamicImage.htm deleted file mode 100644 index 08240bb63d..0000000000 --- a/view/js/cropper/tests/example-DynamicImage.htm +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - Dynamic image test - - - - - - - - - - -

    Dynamic image test

    -

    - Test of dynamically changing images or removing & re-applying the cropper -

    - -
    - test image -
    - -

    - - -

    - -

    - - -

    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - - - - - diff --git a/view/js/cropper/tests/example-FixedRatio.htm b/view/js/cropper/tests/example-FixedRatio.htm deleted file mode 100644 index 8d196c15c2..0000000000 --- a/view/js/cropper/tests/example-FixedRatio.htm +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - Fixed ratio test - - - - - - - - - - -

    Fixed ratio test

    -

    - Test of applying a fixed ratio to the cropper -

    -
    - -
    - test image -
    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - - - - - diff --git a/view/js/cropper/tests/example-MinimumDimensions.htm b/view/js/cropper/tests/example-MinimumDimensions.htm deleted file mode 100644 index e6d96b3937..0000000000 --- a/view/js/cropper/tests/example-MinimumDimensions.htm +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - Min dimensions test - - - - - - - - - - -

    Minimum (both axes ) dimension test

    -

    - Test of applying a minimum dimension to both axes to the cropper -

    -
    - -
    - test image -
    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - - - - - diff --git a/view/js/cropper/tests/example-MinimumWidth.htm b/view/js/cropper/tests/example-MinimumWidth.htm deleted file mode 100644 index ec5d696671..0000000000 --- a/view/js/cropper/tests/example-MinimumWidth.htm +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - Min (single axis) dimensions test - - - - - - - - - - -

    Minimum (single axis) dimension test

    -

    - Test of applying a minimum dimension to only one axis (width in this case) to the cropper -

    -
    -

    - -
    - test image -
    - - -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    - - - - - diff --git a/view/js/cropper/tests/example-Preview.htm b/view/js/cropper/tests/example-Preview.htm deleted file mode 100644 index 51bf260d3c..0000000000 --- a/view/js/cropper/tests/example-Preview.htm +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - -

    - -
    - test image -
    - -
    - -
    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -

    - - -

    -
    - - - - - diff --git a/view/js/cropper/tests/poppy.jpg b/view/js/cropper/tests/poppy.jpg deleted file mode 100644 index 1f6498584473b632b707c83ec751499878266915..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18338 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 diff --git a/view/js/cropper/tests/staticHTMLStructure.htm b/view/js/cropper/tests/staticHTMLStructure.htm deleted file mode 100644 index ddb99278e2..0000000000 --- a/view/js/cropper/tests/staticHTMLStructure.htm +++ /dev/null @@ -1,236 +0,0 @@ - - - - - - - - - - - -

    - - -

    - test image -
    -
    -
    - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -

    Preview:

    -
    - test image -
    -
    - - - - diff --git a/view/templates/cropbody.tpl b/view/templates/cropbody.tpl index 4cf030bc9d..5fedfd0df4 100644 --- a/view/templates/cropbody.tpl +++ b/view/templates/cropbody.tpl @@ -1,58 +1,54 @@

    {{$title}}

    -{{$desc}} + {{$desc}}

    +
    -{{$title}} + {{$title}}
    +
    -
    +
    - - - - - - - - - - - -
    - -
    + + + + + + + + + + + +
    + +
    diff --git a/view/templates/crophead.tpl b/view/templates/crophead.tpl index 033f2e4101..d6fc845673 100644 --- a/view/templates/crophead.tpl +++ b/view/templates/crophead.tpl @@ -1,4 +1,2 @@ - - - - + + diff --git a/view/theme/duepuntozero/style.css b/view/theme/duepuntozero/style.css index 728a55b9ca..84ea6db94b 100644 --- a/view/theme/duepuntozero/style.css +++ b/view/theme/duepuntozero/style.css @@ -726,6 +726,9 @@ input#dfrn-url { height:175px; padding: 12px; } +#profile-photo-wrapper.crop-preview img { + padding: 0; +} #profile-edit-profile-name-label, #profile-edit-name-label, diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 99fde33099..312bee263e 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1087,6 +1087,9 @@ color: rgba(255,255,255,.85); aside .vcard #profile-photo-wrapper:hover .tool .action { opacity: 1; } +aside .vcard #profile-photo-wrapper.crop-preview { + padding: 0; +} aside .vcard .profile-header { margin-bottom: 20px; } -- 2.39.5