alchemy_cms 7.3.5 → 7.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +56 -0
  3. data/Gemfile +3 -3
  4. data/README.md +2 -2
  5. data/alchemy_cms.gemspec +1 -4
  6. data/app/assets/builds/alchemy/admin.css +9 -1
  7. data/app/assets/builds/alchemy/admin.css.map +1 -1
  8. data/app/assets/builds/alchemy/custom-properties.css +1 -1
  9. data/app/assets/builds/alchemy/custom-properties.css.map +1 -1
  10. data/app/assets/builds/alchemy/preview.min.js +1 -0
  11. data/app/assets/builds/alchemy/welcome.css +1 -1
  12. data/app/assets/builds/alchemy/welcome.css.map +1 -1
  13. data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -1
  14. data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css.map +1 -1
  15. data/app/assets/config/alchemy_manifest.js +0 -4
  16. data/app/assets/javascripts/alchemy/admin.js +8 -6
  17. data/app/assets/stylesheets/alchemy/admin/elements.scss +43 -7
  18. data/app/assets/stylesheets/alchemy/admin/forms.scss +4 -0
  19. data/app/assets/stylesheets/alchemy/admin/navigation.scss +9 -1
  20. data/app/assets/stylesheets/alchemy/admin/preview_window.scss +22 -17
  21. data/app/assets/stylesheets/alchemy/admin.scss +1 -1
  22. data/app/assets/stylesheets/alchemy/custom-properties.css +2 -1
  23. data/app/components/alchemy/ingredients/link_view.rb +7 -1
  24. data/app/components/alchemy/ingredients/picture_view.rb +5 -2
  25. data/app/components/alchemy/ingredients/text_view.rb +4 -1
  26. data/app/components/concerns/alchemy/ingredients/link_target.rb +18 -0
  27. data/app/controllers/alchemy/admin/base_controller.rb +8 -3
  28. data/app/controllers/alchemy/admin/elements_controller.rb +2 -2
  29. data/app/controllers/alchemy/admin/layoutpages_controller.rb +1 -0
  30. data/app/controllers/alchemy/admin/pages_controller.rb +5 -1
  31. data/app/controllers/alchemy/elements_controller.rb +3 -0
  32. data/app/helpers/alchemy/admin/form_helper.rb +1 -1
  33. data/app/helpers/alchemy/admin/navigation_helper.rb +22 -1
  34. data/app/javascript/alchemy_admin/components/action.js +2 -1
  35. data/app/javascript/alchemy_admin/components/dialog_link.js +3 -18
  36. data/app/javascript/alchemy_admin/components/element_editor.js +9 -0
  37. data/app/javascript/alchemy_admin/components/elements_window.js +34 -0
  38. data/app/javascript/alchemy_admin/components/elements_window_handle.js +65 -0
  39. data/app/javascript/alchemy_admin/components/icon.js +2 -2
  40. data/app/javascript/alchemy_admin/components/index.js +1 -0
  41. data/app/javascript/alchemy_admin/components/preview_window.js +5 -5
  42. data/app/javascript/alchemy_admin/components/uploader/file_upload.js +1 -1
  43. data/app/javascript/alchemy_admin/confirm_dialog.js +9 -11
  44. data/app/javascript/alchemy_admin/dialog.js +329 -0
  45. data/app/javascript/alchemy_admin/hotkeys.js +3 -2
  46. data/app/javascript/alchemy_admin/image_cropper.js +57 -40
  47. data/app/javascript/alchemy_admin/image_overlay.js +73 -0
  48. data/app/javascript/alchemy_admin/initializer.js +51 -2
  49. data/app/javascript/alchemy_admin/link_dialog.js +2 -1
  50. data/app/javascript/alchemy_admin/node_tree.js +3 -1
  51. data/app/javascript/alchemy_admin/page_sorter.js +1 -1
  52. data/app/javascript/alchemy_admin/picture_selector.js +2 -1
  53. data/app/javascript/alchemy_admin/shoelace_theme.js +2 -2
  54. data/app/javascript/alchemy_admin/templates/compiled.js +1 -0
  55. data/app/javascript/alchemy_admin.js +10 -6
  56. data/app/javascript/preview.js +117 -0
  57. data/app/models/alchemy/image_cropper_settings.rb +3 -4
  58. data/app/views/alchemy/_preview_mode_code.html.erb +1 -1
  59. data/app/views/alchemy/admin/crop.html.erb +19 -16
  60. data/app/views/alchemy/admin/dashboard/info.html.erb +1 -1
  61. data/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb +9 -8
  62. data/app/views/alchemy/admin/elements/_clipboard_button.html.erb +14 -0
  63. data/app/views/alchemy/admin/elements/_element.html.erb +2 -0
  64. data/app/views/alchemy/admin/elements/_form.html.erb +15 -13
  65. data/app/views/alchemy/admin/elements/create.turbo_stream.erb +34 -0
  66. data/app/views/alchemy/admin/elements/index.html.erb +3 -15
  67. data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +1 -1
  68. data/app/views/alchemy/admin/layoutpages/edit.html.erb +7 -5
  69. data/app/views/alchemy/admin/nodes/_form.html.erb +1 -1
  70. data/app/views/alchemy/admin/pages/_current_page.html.erb +1 -1
  71. data/app/views/alchemy/admin/pages/_form.html.erb +43 -40
  72. data/app/views/alchemy/admin/pages/_locked_page.html.erb +1 -1
  73. data/app/views/alchemy/admin/pages/_page_layout_filter.html.erb +1 -1
  74. data/app/views/alchemy/admin/pages/_sitemap.html.erb +1 -1
  75. data/app/views/alchemy/admin/pages/_table.html.erb +2 -2
  76. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  77. data/app/views/alchemy/admin/pages/update.turbo_stream.erb +39 -0
  78. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +3 -4
  79. data/app/views/alchemy/admin/pictures/_picture_description_field.html.erb +7 -5
  80. data/app/views/alchemy/admin/pictures/index.html.erb +13 -9
  81. data/app/views/alchemy/admin/resources/_filter_bar.html.erb +1 -1
  82. data/app/views/layouts/alchemy/admin.html.erb +8 -4
  83. data/bun.lockb +0 -0
  84. data/bundles/tinymce.js +2 -0
  85. data/config/alchemy/config.yml +3 -3
  86. data/config/alchemy/modules.yml +7 -6
  87. data/config/importmap.rb +4 -0
  88. data/config/routes.rb +1 -1
  89. data/lib/alchemy/engine.rb +6 -0
  90. data/lib/alchemy/modules.rb +0 -27
  91. data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +10 -10
  92. data/lib/alchemy/tinymce.rb +2 -1
  93. data/lib/alchemy/upgrader/seven_point_four.rb +26 -0
  94. data/lib/alchemy/version.rb +1 -1
  95. data/lib/alchemy.rb +14 -0
  96. data/lib/alchemy_cms.rb +0 -2
  97. data/lib/generators/alchemy/ingredient/ingredient_generator.rb +5 -0
  98. data/lib/generators/alchemy/ingredient/templates/view.html.erb +1 -1
  99. data/lib/generators/alchemy/ingredient/templates/view_component.rb.tt +10 -0
  100. data/lib/generators/alchemy/install/install_generator.rb +0 -1
  101. data/lib/generators/alchemy/install/templates/elements.yml.tt +1 -1
  102. data/lib/tasks/alchemy/upgrade.rake +19 -20
  103. data/rollup.config.mjs +44 -1
  104. data/vendor/javascript/cropperjs.min.js +10 -0
  105. data/vendor/javascript/handlebars.min.js +29 -0
  106. data/vendor/javascript/jquery.min.js +2 -0
  107. data/vendor/javascript/select2.min.js +23 -0
  108. data/vendor/javascript/tinymce.min.js +1 -1
  109. metadata +39 -91
  110. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +0 -271
  111. data/app/assets/javascripts/alchemy/alchemy.image_overlay.coffee +0 -54
  112. data/app/assets/javascripts/alchemy/alchemy.preview.js.coffee +0 -97
  113. data/app/assets/javascripts/alchemy/preview.js +0 -1
  114. data/app/assets/javascripts/alchemy/templates/index.js +0 -2
  115. data/app/javascript/alchemy_admin/gui.js +0 -12
  116. data/app/views/alchemy/admin/elements/create.js.erb +0 -35
  117. data/app/views/alchemy/admin/pages/update.js.erb +0 -43
  118. data/lib/alchemy/upgrader/seven_point_zero.rb +0 -36
  119. data/vendor/assets/images/Jcrop.gif +0 -0
  120. data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +0 -7
  121. data/vendor/assets/javascripts/jquery_plugins/select2.js +0 -3729
  122. data/vendor/assets/stylesheets/jquery.Jcrop.min.css +0 -2
  123. data/vendor/assets/stylesheets/tinymce/skins/content/default/content.min.css +0 -1
  124. /data/app/{assets/javascripts/alchemy → javascript/alchemy_admin}/templates/node_folder.hbs +0 -0
  125. /data/app/{assets/javascripts/alchemy → javascript/alchemy_admin}/templates/page_folder.hbs +0 -0
  126. /data/app/{assets/javascripts/tinymce/icons/remixicons/icons.js → javascript/tinymce/icons/remixicons/index.js} +0 -0
  127. /data/app/{assets/javascripts/tinymce/plugins/alchemy_link/plugin.min.js → javascript/tinymce/plugins/alchemy_link/index.js} +0 -0
  128. /data/vendor/assets/{fonts → images}/remixicon.symbol.svg +0 -0
@@ -1,97 +0,0 @@
1
- window.Alchemy = Alchemy || {}
2
-
3
- Alchemy.initAlchemyPreviewMode = ->
4
-
5
- # The Alchemy JavaScript Object contains all Functions
6
- Object.assign Alchemy,
7
-
8
- ElementSelector:
9
-
10
- styles:
11
- reset:
12
- outline: ""
13
- "outline-offset": ""
14
- cursor: ""
15
- hover:
16
- outline: "2px dashed #f0b437"
17
- "outline-offset": "4px"
18
- cursor: "pointer"
19
- selected:
20
- outline: "2px dashed #90b9d0"
21
- "outline-offset": "4px"
22
-
23
- init: ->
24
- window.addEventListener "message", (event) =>
25
- switch event.data.message
26
- when "Alchemy.blurElements" then @blurElements()
27
- when "Alchemy.focusElement" then @focusElement(event.data)
28
- else console.info("Received unknown message!", event.data)
29
- return
30
- @elements = Array.from document.querySelectorAll("[data-alchemy-element]")
31
- @elements.forEach (element) =>
32
- element.addEventListener 'mouseover', =>
33
- unless element.classList.contains('selected')
34
- Object.assign element.style, @getStyle('hover')
35
- return
36
- element.addEventListener 'mouseout', =>
37
- unless element.classList.contains('selected')
38
- Object.assign element.style, @getStyle('reset')
39
- return
40
- element.addEventListener 'click', (e) =>
41
- e.stopPropagation()
42
- e.preventDefault()
43
- @selectElement(element)
44
- @focusElementEditor(element)
45
- return
46
- return
47
- return
48
-
49
- # Mark element in preview frame as selected and scrolls to it.
50
- selectElement: (element) ->
51
- @blurElements(element)
52
- element.classList.add('selected')
53
- Object.assign element.style, @getStyle('selected')
54
- element.scrollIntoView
55
- behavior: 'smooth'
56
- block: 'start'
57
- return
58
-
59
- # Blur all elements in preview frame.
60
- blurElements: (selectedElement) ->
61
- @elements.forEach (element) =>
62
- if element != selectedElement
63
- element.classList.remove('selected')
64
- Object.assign element.style, @getStyle('reset')
65
- return
66
- return
67
-
68
- # Focus the element in the Alchemy preview window.
69
- focusElement: (data) ->
70
- element = @getElement(data.element_id)
71
- if element
72
- @selectElement(element)
73
- else
74
- console.warn('Could not focus element with id', data.element_id)
75
-
76
- getElement: (element_id) ->
77
- @elements.find (element) ->
78
- element.dataset.alchemyElement == element_id.toString()
79
-
80
- # Focus the element editor in the Alchemy element window.
81
- focusElementEditor: (element) ->
82
- element_id = element.getAttribute('data-alchemy-element')
83
- window.parent.postMessage
84
- message: 'Alchemy.focusElementEditor'
85
- element_id: element_id
86
- , window.location.origin
87
- return
88
-
89
- getStyle: (state) ->
90
- if state == "reset"
91
- @styles["reset"]
92
- else
93
- @styles[state]
94
-
95
- Alchemy.ElementSelector.init()
96
-
97
- Alchemy.initAlchemyPreviewMode()
@@ -1 +0,0 @@
1
- //= require alchemy/alchemy.preview
@@ -1,2 +0,0 @@
1
- //= require alchemy/templates/node_folder
2
- //= require alchemy/templates/page_folder
@@ -1,12 +0,0 @@
1
- import Hotkeys from "alchemy_admin/hotkeys"
2
-
3
- function init(scope) {
4
- if (!scope) {
5
- Alchemy.watchForDialogs()
6
- }
7
- Hotkeys(scope)
8
- }
9
-
10
- export default {
11
- init
12
- }
@@ -1,35 +0,0 @@
1
- (function() {
2
- var $element_area;
3
- var element_html = '<%= j render(Alchemy::ElementEditor.new(@element)) %>';
4
-
5
- <%- if @cut_element_id -%>
6
- $('.element-editor[data-element-id="<%= @cut_element_id %>"]').remove();
7
- <%- end -%>
8
-
9
- <% if @element.fixed? %>
10
- Alchemy.FixedElements.createTab('<%= @element.id %>', '<%= @element.display_name %>');
11
- $element_area = $('[name="fixed-element-<%= @element.id %>"]');
12
- <% elsif @element.parent_element %>
13
- $element_area = $('#element_<%= @element.parent_element_id %> > .nestable-elements > .nested-elements');
14
- <% else %>
15
- $element_area = $('#main-content-elements');
16
- <% end %>
17
-
18
- <%- if @insert_at_top -%>
19
- $element_area.prepend(element_html);
20
- <%- else -%>
21
- $element_area.append(element_html);
22
- <%- end -%>
23
-
24
- Alchemy.growl('<%= Alchemy.t(:successfully_added_element) %>');
25
- Alchemy.closeCurrentDialog();
26
- Alchemy.reloadPreview();
27
-
28
- el = document.querySelector('#element_<%= @element.id %>');
29
- el.focusElement();
30
- el.focusElementPreview();
31
-
32
- <%- if @clipboard.blank? -%>
33
- $('#clipboard_button .icon.clipboard').removeClass('full');
34
- <%- end -%>
35
- })();
@@ -1,43 +0,0 @@
1
- (function() {
2
- var page = document.querySelector('#page_<%= @page.id %>');
3
-
4
- <% if @while_page_edit -%>
5
-
6
- Alchemy.reloadPreview();
7
- document.querySelector('#page_<%= @page.id %>_status').outerHTML = '<%= j render("current_page", current_page: @page) %>';
8
- Alchemy.growl("<%= j @notice %>");
9
- Alchemy.closeCurrentDialog();
10
-
11
- <% elsif @page.parent_id != @old_parent_id -%>
12
-
13
- Alchemy.closeCurrentDialog(function() {
14
- Alchemy.growl("<%= j @notice %>");
15
- Alchemy.currentSitemap.load(<%= @page.get_language_root.id %>);
16
- });
17
-
18
- <% else -%>
19
-
20
- if (page) {
21
-
22
- <% if @page.layoutpage %>
23
- page.outerHTML = "<%= j render('alchemy/admin/layoutpages/layoutpage', layoutpage: @page) %>"
24
- <% else %>
25
- const page_html = "<%= j render('page', page: @page) %>".replace(/__ID__/g, "<%= @page.id %>");
26
- const compiler = Handlebars.compile(page_html);
27
- const tree = <%== @tree.to_json %>;
28
- page.outerHTML = compiler(tree.pages[0]);
29
- <% end %>
30
-
31
- Alchemy.growl("<%= j @notice %>");
32
- Alchemy.closeCurrentDialog();
33
- } else {
34
- document.addEventListener('turbo:load', function () {
35
- Alchemy.growl("<%= j @notice %>");
36
- }, { once: true })
37
- Alchemy.closeCurrentDialog(function() {
38
- Turbo.visit(location.toString(), { action: "replace" });
39
- });
40
- }
41
-
42
- <% end -%>
43
- })()
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "thor"
4
-
5
- module Alchemy
6
- class Upgrader::SevenPointZero < Upgrader
7
- include Thor::Base
8
- include Thor::Actions
9
-
10
- class << self
11
- def remove_admin_entrypoint
12
- FileUtils.rm_rf "app/assets/builds/alchemy_admin.*"
13
- FileUtils.rm_rf "app/javascript/packs/alchemy/admin.js"
14
- FileUtils.rm_rf "app/javascript/packs/alchemy_admin.js"
15
- FileUtils.rm_rf "app/javascript/packs/alchemy"
16
- FileUtils.rm_rf "app/javascript/packs/alchemy"
17
- task.run "yarn remove @alchemy_cms/admin"
18
- if task.ask("Do you want to remove webpacker as well? (y/N)", default: "N") == "y"
19
- task.run "bundle remove webpacker"
20
- task.run "yarn remove @rails/webpacker webpack webpack-cli webpack-dev-server"
21
- FileUtils.rm_rf "app/javascript/packs"
22
- FileUtils.rm_rf "config/webpack"
23
- FileUtils.rm_f "config/webpacker.yml"
24
- FileUtils.rm_f "bin/webpack"
25
- FileUtils.rm_f "bin/webpack-dev-server"
26
- end
27
- end
28
-
29
- private
30
-
31
- def task
32
- @_task || new
33
- end
34
- end
35
- end
36
- end
Binary file
@@ -1,7 +0,0 @@
1
- /**
2
- * jquery.Jcrop.min.js v0.9.15 (build:20180819)
3
- * jQuery Image Cropping Plugin - released under MIT License
4
- * Copyright (c) 2008-2018 Tapmodo Interactive LLC
5
- * https://github.com/tapmodo/Jcrop
6
- */
7
- !function($){$.Jcrop=function(obj,opt){function px(n){return Math.round(n)+"px"}function cssClass(cl){return options.baseClass+"-"+cl}function supportsColorFade(){return $.fx.step.hasOwnProperty("backgroundColor")}function getPos(obj){var pos=$(obj).offset();return[pos.left,pos.top]}function mouseAbs(e){return[e.pageX-docOffset[0],e.pageY-docOffset[1]]}function setOptions(opt){"object"!=typeof opt&&(opt={}),options=$.extend(options,opt),$.each(["onChange","onSelect","onRelease","onDblClick"],function(i,e){"function"!=typeof options[e]&&(options[e]=function(){})})}function startDragMode(mode,pos,touch){if(docOffset=getPos($img),Tracker.setCursor("move"===mode?mode:mode+"-resize"),"move"===mode)return Tracker.activateHandlers(createMover(pos),doneSelect,touch);var fc=Coords.getFixed(),opp=oppLockCorner(mode),opc=Coords.getCorner(oppLockCorner(opp));Coords.setPressed(Coords.getCorner(opp)),Coords.setCurrent(opc),Tracker.activateHandlers(dragmodeHandler(mode,fc),doneSelect,touch)}function dragmodeHandler(mode,f){return function(pos){if(options.aspectRatio)switch(mode){case"e":pos[1]=f.y+1;break;case"w":pos[1]=f.y+1;break;case"n":pos[0]=f.x+1;break;case"s":pos[0]=f.x+1}else switch(mode){case"e":pos[1]=f.y2;break;case"w":pos[1]=f.y2;break;case"n":pos[0]=f.x2;break;case"s":pos[0]=f.x2}Coords.setCurrent(pos),Selection.update()}}function createMover(pos){var lloc=pos;return KeyManager.watchKeys(),function(pos){Coords.moveOffset([pos[0]-lloc[0],pos[1]-lloc[1]]),lloc=pos,Selection.update()}}function oppLockCorner(ord){switch(ord){case"n":return"sw";case"s":return"nw";case"e":return"nw";case"w":return"ne";case"ne":return"sw";case"nw":return"se";case"se":return"nw";case"sw":return"ne"}}function createDragger(ord){return function(e){return options.disabled?!1:"move"!==ord||options.allowMove?(docOffset=getPos($img),btndown=!0,startDragMode(ord,mouseAbs(e)),e.stopPropagation(),e.preventDefault(),!1):!1}}function presize($obj,w,h){var nw=$obj.width(),nh=$obj.height();nw>w&&w>0&&(nw=w,nh=w/$obj.width()*$obj.height()),nh>h&&h>0&&(nh=h,nw=h/$obj.height()*$obj.width()),xscale=$obj.width()/nw,yscale=$obj.height()/nh,$obj.width(nw).height(nh)}function unscale(c){return{x:c.x*xscale,y:c.y*yscale,x2:c.x2*xscale,y2:c.y2*yscale,w:c.w*xscale,h:c.h*yscale}}function doneSelect(){var c=Coords.getFixed();c.w>options.minSelect[0]&&c.h>options.minSelect[1]?(Selection.enableHandles(),Selection.done()):Selection.release(),Tracker.setCursor(options.allowSelect?"crosshair":"default")}function newSelection(e){if(!options.disabled&&options.allowSelect){btndown=!0,docOffset=getPos($img),Selection.disableHandles(),Tracker.setCursor("crosshair");var pos=mouseAbs(e);return Coords.setPressed(pos),Selection.update(),Tracker.activateHandlers(selectDrag,doneSelect,"touch"===e.type.substring(0,5)),KeyManager.watchKeys(),e.stopPropagation(),e.preventDefault(),!1}}function selectDrag(pos){Coords.setCurrent(pos),Selection.update()}function newTracker(){var trk=$("<div></div>").addClass(cssClass("tracker"));return is_msie&&trk.css({opacity:0,backgroundColor:"white"}),trk}function setClass(cname){$div.removeClass().addClass(cssClass("holder")).addClass(cname)}function animateTo(a,callback){function queueAnimator(){window.setTimeout(animator,interv)}var x1=a[0]/xscale,y1=a[1]/yscale,x2=a[2]/xscale,y2=a[3]/yscale;if(!animating){var animto=Coords.flipCoords(x1,y1,x2,y2),c=Coords.getFixed(),initcr=[c.x,c.y,c.x2,c.y2],animat=initcr,interv=options.animationDelay,ix1=animto[0]-initcr[0],iy1=animto[1]-initcr[1],ix2=animto[2]-initcr[2],iy2=animto[3]-initcr[3],pcent=0,velocity=options.swingSpeed;x1=animat[0],y1=animat[1],x2=animat[2],y2=animat[3],Selection.animMode(!0);var animator=function(){return function(){pcent+=(100-pcent)/velocity,animat[0]=Math.round(x1+pcent/100*ix1),animat[1]=Math.round(y1+pcent/100*iy1),animat[2]=Math.round(x2+pcent/100*ix2),animat[3]=Math.round(y2+pcent/100*iy2),pcent>=99.8&&(pcent=100),100>pcent?(setSelectRaw(animat),queueAnimator()):(Selection.done(),Selection.animMode(!1),"function"==typeof callback&&callback.call(api))}}();queueAnimator()}}function setSelect(rect){setSelectRaw([rect[0]/xscale,rect[1]/yscale,rect[2]/xscale,rect[3]/yscale]),options.onSelect.call(api,unscale(Coords.getFixed())),Selection.enableHandles()}function setSelectRaw(l){Coords.setPressed([l[0],l[1]]),Coords.setCurrent([l[2],l[3]]),Selection.update()}function tellSelect(){return unscale(Coords.getFixed())}function tellScaled(){return Coords.getFixed()}function setOptionsNew(opt){setOptions(opt),interfaceUpdate()}function disableCrop(){options.disabled=!0,Selection.disableHandles(),Selection.setCursor("default"),Tracker.setCursor("default")}function enableCrop(){options.disabled=!1,interfaceUpdate()}function cancelCrop(){Selection.done(),Tracker.activateHandlers(null,null)}function destroy(){$div.remove(),$origimg.show(),$origimg.css("visibility","visible"),$(obj).removeData("Jcrop")}function setImage(src,callback){Selection.release(),disableCrop();var img=new Image;img.onload=function(){var iw=img.width,ih=img.height,bw=options.boxWidth,bh=options.boxHeight;$img.width(iw).height(ih),$img.attr("src",src),$img2.attr("src",src),presize($img,bw,bh),boundx=$img.width(),boundy=$img.height(),$img2.width(boundx).height(boundy),$trk.width(boundx+2*bound).height(boundy+2*bound),$div.width(boundx).height(boundy),Shade.resize(boundx,boundy),enableCrop(),"function"==typeof callback&&callback.call(api)},img.src=src}function colorChangeMacro($obj,color,now){var mycolor=color||options.bgColor;options.bgFade&&supportsColorFade()&&options.fadeTime&&!now?$obj.animate({backgroundColor:mycolor},{queue:!1,duration:options.fadeTime}):$obj.css("backgroundColor",mycolor)}function interfaceUpdate(alt){options.allowResize?alt?Selection.enableOnly():Selection.enableHandles():Selection.disableHandles(),Tracker.setCursor(options.allowSelect?"crosshair":"default"),Selection.setCursor(options.allowMove?"move":"default"),options.hasOwnProperty("trueSize")&&(xscale=options.trueSize[0]/boundx,yscale=options.trueSize[1]/boundy),options.hasOwnProperty("setSelect")&&(setSelect(options.setSelect),Selection.done(),delete options.setSelect),Shade.refresh(),options.bgColor!=bgcolor&&(colorChangeMacro(options.shade?Shade.getShades():$div,options.shade?options.shadeColor||options.bgColor:options.bgColor),bgcolor=options.bgColor),bgopacity!=options.bgOpacity&&(bgopacity=options.bgOpacity,options.shade?Shade.refresh():Selection.setBgOpacity(bgopacity)),xlimit=options.maxSize[0]||0,ylimit=options.maxSize[1]||0,xmin=options.minSize[0]||0,ymin=options.minSize[1]||0,options.hasOwnProperty("outerImage")&&($img.attr("src",options.outerImage),delete options.outerImage),Selection.refresh()}var docOffset,options=$.extend({},$.Jcrop.defaults),_ua=navigator.userAgent.toLowerCase(),is_msie=/msie/.test(_ua),ie6mode=/msie [1-6]\./.test(_ua);"object"!=typeof obj&&(obj=$(obj)[0]),"object"!=typeof opt&&(opt={}),setOptions(opt);var img_css={border:"none",visibility:"visible",margin:0,padding:0,position:"absolute",top:0,left:0},$origimg=$(obj),img_mode=!0;if("IMG"==obj.tagName){if(0!=$origimg[0].width&&0!=$origimg[0].height)$origimg.width($origimg[0].width),$origimg.height($origimg[0].height);else{var tempImage=new Image;tempImage.src=$origimg[0].src,$origimg.width(tempImage.width),$origimg.height(tempImage.height)}var $img=$origimg.clone().removeAttr("id").css(img_css).show();$img.width($origimg.width()),$img.height($origimg.height()),$origimg.after($img).hide()}else $img=$origimg.css(img_css).show(),img_mode=!1,null===options.shade&&(options.shade=!0);presize($img,options.boxWidth,options.boxHeight);var boundx=$img.width(),boundy=$img.height(),$div=$("<div />").width(boundx).height(boundy).addClass(cssClass("holder")).css({position:"relative",backgroundColor:options.bgColor}).insertAfter($origimg).append($img);options.addClass&&$div.addClass(options.addClass);var $img2=$("<div />"),$img_holder=$("<div />").width("100%").height("100%").css({zIndex:310,position:"absolute",overflow:"hidden"}),$hdl_holder=$("<div />").width("100%").height("100%").css("zIndex",320),$sel=$("<div />").css({position:"absolute",zIndex:600}).dblclick(function(){var c=Coords.getFixed();options.onDblClick.call(api,c)}).insertBefore($img).append($img_holder,$hdl_holder);img_mode&&($img2=$("<img />").attr("src",$img.attr("src")).css(img_css).width(boundx).height(boundy),$img_holder.append($img2)),ie6mode&&$sel.css({overflowY:"hidden"});var xlimit,ylimit,xmin,ymin,xscale,yscale,btndown,animating,shift_down,bound=options.boundary,$trk=newTracker().width(boundx+2*bound).height(boundy+2*bound).css({position:"absolute",top:px(-bound),left:px(-bound),zIndex:290}).mousedown(newSelection),bgcolor=options.bgColor,bgopacity=options.bgOpacity;docOffset=getPos($img);var Touch=function(){function hasTouchSupport(){var i,support={},events=["touchstart","touchmove","touchend"],el=document.createElement("div");try{for(i=0;i<events.length;i++){var eventName=events[i];eventName="on"+eventName;var isSupported=eventName in el;isSupported||(el.setAttribute(eventName,"return;"),isSupported="function"==typeof el[eventName]),support[events[i]]=isSupported}return support.touchstart&&support.touchend&&support.touchmove}catch(err){return!1}}function detectSupport(){return options.touchSupport===!0||options.touchSupport===!1?options.touchSupport:hasTouchSupport()}return{createDragger:function(ord){return function(e){return options.disabled?!1:"move"!==ord||options.allowMove?(docOffset=getPos($img),btndown=!0,startDragMode(ord,mouseAbs(Touch.cfilter(e)),!0),e.stopPropagation(),e.preventDefault(),!1):!1}},newSelection:function(e){return newSelection(Touch.cfilter(e))},cfilter:function(e){return e.pageX=e.originalEvent.changedTouches[0].pageX,e.pageY=e.originalEvent.changedTouches[0].pageY,e},isSupported:hasTouchSupport,support:detectSupport()}}(),Coords=function(){function setPressed(pos){pos=rebound(pos),x2=x1=pos[0],y2=y1=pos[1]}function setCurrent(pos){pos=rebound(pos),ox=pos[0]-x2,oy=pos[1]-y2,x2=pos[0],y2=pos[1]}function getOffset(){return[ox,oy]}function moveOffset(offset){var ox=offset[0],oy=offset[1];0>x1+ox&&(ox-=ox+x1),0>y1+oy&&(oy-=oy+y1),y2+oy>boundy&&(oy+=boundy-(y2+oy)),x2+ox>boundx&&(ox+=boundx-(x2+ox)),x1+=ox,x2+=ox,y1+=oy,y2+=oy}function getCorner(ord){var c=getFixed();switch(ord){case"ne":return[c.x2,c.y];case"nw":return[c.x,c.y];case"se":return[c.x2,c.y2];case"sw":return[c.x,c.y2]}}function getFixed(){if(!options.aspectRatio)return getRect();var xx,yy,w,h,aspect=options.aspectRatio,min_x=options.minSize[0]/xscale,max_x=options.maxSize[0]/xscale,max_y=options.maxSize[1]/yscale,rw=x2-x1,rh=y2-y1,rwa=Math.abs(rw),rha=Math.abs(rh),real_ratio=rwa/rha;return 0===max_x&&(max_x=10*boundx),0===max_y&&(max_y=10*boundy),aspect>real_ratio?(yy=y2,w=rha*aspect,xx=0>rw?x1-w:w+x1,0>xx?(xx=0,h=Math.abs((xx-x1)/aspect),yy=0>rh?y1-h:h+y1):xx>boundx&&(xx=boundx,h=Math.abs((xx-x1)/aspect),yy=0>rh?y1-h:h+y1)):(xx=x2,h=rwa/aspect,yy=0>rh?y1-h:y1+h,0>yy?(yy=0,w=Math.abs((yy-y1)*aspect),xx=0>rw?x1-w:w+x1):yy>boundy&&(yy=boundy,w=Math.abs(yy-y1)*aspect,xx=0>rw?x1-w:w+x1)),xx>x1?(min_x>xx-x1?xx=x1+min_x:xx-x1>max_x&&(xx=x1+max_x),yy=yy>y1?y1+(xx-x1)/aspect:y1-(xx-x1)/aspect):x1>xx&&(min_x>x1-xx?xx=x1-min_x:x1-xx>max_x&&(xx=x1-max_x),yy=yy>y1?y1+(x1-xx)/aspect:y1-(x1-xx)/aspect),0>xx?(x1-=xx,xx=0):xx>boundx&&(x1-=xx-boundx,xx=boundx),0>yy?(y1-=yy,yy=0):yy>boundy&&(y1-=yy-boundy,yy=boundy),makeObj(flipCoords(x1,y1,xx,yy))}function rebound(p){return p[0]<0&&(p[0]=0),p[1]<0&&(p[1]=0),p[0]>boundx&&(p[0]=boundx),p[1]>boundy&&(p[1]=boundy),[Math.round(p[0]),Math.round(p[1])]}function flipCoords(x1,y1,x2,y2){var xa=x1,xb=x2,ya=y1,yb=y2;return x1>x2&&(xa=x2,xb=x1),y1>y2&&(ya=y2,yb=y1),[xa,ya,xb,yb]}function getRect(){var delta,xsize=x2-x1,ysize=y2-y1;return xlimit&&Math.abs(xsize)>xlimit&&(x2=xsize>0?x1+xlimit:x1-xlimit),ylimit&&Math.abs(ysize)>ylimit&&(y2=ysize>0?y1+ylimit:y1-ylimit),ymin/yscale&&Math.abs(ysize)<ymin/yscale&&(y2=ysize>0?y1+ymin/yscale:y1-ymin/yscale),xmin/xscale&&Math.abs(xsize)<xmin/xscale&&(x2=xsize>0?x1+xmin/xscale:x1-xmin/xscale),0>x1&&(x2-=x1,x1-=x1),0>y1&&(y2-=y1,y1-=y1),0>x2&&(x1-=x2,x2-=x2),0>y2&&(y1-=y2,y2-=y2),x2>boundx&&(delta=x2-boundx,x1-=delta,x2-=delta),y2>boundy&&(delta=y2-boundy,y1-=delta,y2-=delta),x1>boundx&&(delta=x1-boundy,y2-=delta,y1-=delta),y1>boundy&&(delta=y1-boundy,y2-=delta,y1-=delta),makeObj(flipCoords(x1,y1,x2,y2))}function makeObj(a){return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]}}var ox,oy,x1=0,y1=0,x2=0,y2=0;return{flipCoords:flipCoords,setPressed:setPressed,setCurrent:setCurrent,getOffset:getOffset,moveOffset:moveOffset,getCorner:getCorner,getFixed:getFixed}}(),Shade=function(){function resizeShades(w,h){shades.left.css({height:px(h)}),shades.right.css({height:px(h)})}function updateAuto(){return updateShade(Coords.getFixed())}function updateShade(c){shades.top.css({left:px(c.x),width:px(c.w),height:px(c.y)}),shades.bottom.css({top:px(c.y2),left:px(c.x),width:px(c.w),height:px(boundy-c.y2)}),shades.right.css({left:px(c.x2),width:px(boundx-c.x2)}),shades.left.css({width:px(c.x)})}function createShade(){return $("<div />").css({position:"absolute",backgroundColor:options.shadeColor||options.bgColor}).appendTo(holder)}function enableShade(){enabled||(enabled=!0,holder.insertBefore($img),updateAuto(),Selection.setBgOpacity(1,0,1),$img2.hide(),setBgColor(options.shadeColor||options.bgColor,1),Selection.isAwake()?setOpacity(options.bgOpacity,1):setOpacity(1,1))}function setBgColor(color,now){colorChangeMacro(getShades(),color,now)}function disableShade(){enabled&&(holder.remove(),$img2.show(),enabled=!1,Selection.isAwake()?Selection.setBgOpacity(options.bgOpacity,1,1):(Selection.setBgOpacity(1,1,1),Selection.disableHandles()),colorChangeMacro($div,0,1))}function setOpacity(opacity,now){enabled&&(options.bgFade&&!now?holder.animate({opacity:1-opacity},{queue:!1,duration:options.fadeTime}):holder.css({opacity:1-opacity}))}function refreshAll(){options.shade?enableShade():disableShade(),Selection.isAwake()&&setOpacity(options.bgOpacity)}function getShades(){return holder.children()}var enabled=!1,holder=$("<div />").css({position:"absolute",zIndex:240,opacity:0}),shades={top:createShade(),left:createShade().height(boundy),right:createShade().height(boundy),bottom:createShade()};return{update:updateAuto,updateRaw:updateShade,getShades:getShades,setBgColor:setBgColor,enable:enableShade,disable:disableShade,resize:resizeShades,refresh:refreshAll,opacity:setOpacity}}(),Selection=function(){function insertBorder(type){var jq=$("<div />").css({position:"absolute",opacity:options.borderOpacity}).addClass(cssClass(type));return $img_holder.append(jq),jq}function dragDiv(ord,zi){var jq=$("<div />").mousedown(createDragger(ord)).css({cursor:ord+"-resize",position:"absolute",zIndex:zi}).addClass("ord-"+ord);return Touch.support&&jq.bind("touchstart.jcrop",Touch.createDragger(ord)),$hdl_holder.append(jq),jq}function insertHandle(ord){var hs=options.handleSize,div=dragDiv(ord,hdep++).css({opacity:options.handleOpacity}).addClass(cssClass("handle"));return hs&&div.width(hs).height(hs),div}function insertDragbar(ord){return dragDiv(ord,hdep++).addClass("jcrop-dragbar")}function createDragbars(li){var i;for(i=0;i<li.length;i++)dragbar[li[i]]=insertDragbar(li[i])}function createBorders(li){var cl,i;for(i=0;i<li.length;i++){switch(li[i]){case"n":cl="hline";break;case"s":cl="hline bottom";break;case"e":cl="vline right";break;case"w":cl="vline"}borders[li[i]]=insertBorder(cl)}}function createHandles(li){var i;for(i=0;i<li.length;i++)handle[li[i]]=insertHandle(li[i])}function moveto(x,y){options.shade||$img2.css({top:px(-y),left:px(-x)}),$sel.css({top:px(y),left:px(x)})}function resize(w,h){$sel.width(Math.round(w)).height(Math.round(h))}function refresh(){var c=Coords.getFixed();Coords.setPressed([c.x,c.y]),Coords.setCurrent([c.x2,c.y2]),updateVisible()}function updateVisible(select){return awake?update(select):void 0}function update(select){var c=Coords.getFixed();resize(c.w,c.h),moveto(c.x,c.y),options.shade&&Shade.updateRaw(c),awake||show(),select?options.onSelect.call(api,unscale(c)):options.onChange.call(api,unscale(c))}function setBgOpacity(opacity,force,now){(awake||force)&&(options.bgFade&&!now?$img.animate({opacity:opacity},{queue:!1,duration:options.fadeTime}):$img.css("opacity",opacity))}function show(){$sel.show(),options.shade?Shade.opacity(bgopacity):setBgOpacity(bgopacity,!0),awake=!0}function release(){disableHandles(),$sel.hide(),options.shade?Shade.opacity(1):setBgOpacity(1),awake=!1,options.onRelease.call(api)}function showHandles(){seehandles&&$hdl_holder.show()}function enableHandles(){return seehandles=!0,options.allowResize?($hdl_holder.show(),!0):void 0}function disableHandles(){seehandles=!1,$hdl_holder.hide()}function animMode(v){v?(animating=!0,disableHandles()):(animating=!1,enableHandles())}function done(){animMode(!1),refresh()}var awake,hdep=370,borders={},handle={},dragbar={},seehandles=!1;options.dragEdges&&$.isArray(options.createDragbars)&&createDragbars(options.createDragbars),$.isArray(options.createHandles)&&createHandles(options.createHandles),options.drawBorders&&$.isArray(options.createBorders)&&createBorders(options.createBorders),$(document).bind("touchstart.jcrop-ios",function(e){$(e.currentTarget).hasClass("jcrop-tracker")&&e.stopPropagation()});var $track=newTracker().mousedown(createDragger("move")).css({cursor:"move",position:"absolute",zIndex:360});return Touch.support&&$track.bind("touchstart.jcrop",Touch.createDragger("move")),$img_holder.append($track),disableHandles(),{updateVisible:updateVisible,update:update,release:release,refresh:refresh,isAwake:function(){return awake},setCursor:function(cursor){$track.css("cursor",cursor)},enableHandles:enableHandles,enableOnly:function(){seehandles=!0},showHandles:showHandles,disableHandles:disableHandles,animMode:animMode,setBgOpacity:setBgOpacity,done:done}}(),Tracker=function(){function toFront(touch){$trk.css({zIndex:450}),touch?$(document).bind("touchmove.jcrop",trackTouchMove).bind("touchend.jcrop",trackTouchEnd):trackDoc&&$(document).bind("mousemove.jcrop",trackMove).bind("mouseup.jcrop",trackUp)}function toBack(){$trk.css({zIndex:290}),$(document).unbind(".jcrop")}function trackMove(e){return onMove(mouseAbs(e)),!1}function trackUp(e){return e.preventDefault(),e.stopPropagation(),btndown&&(btndown=!1,onDone(mouseAbs(e)),Selection.isAwake()&&options.onSelect.call(api,unscale(Coords.getFixed())),toBack(),onMove=function(){},onDone=function(){}),!1}function activateHandlers(move,done,touch){return btndown=!0,onMove=move,onDone=done,toFront(touch),!1}function trackTouchMove(e){return onMove(mouseAbs(Touch.cfilter(e))),!1}function trackTouchEnd(e){return trackUp(Touch.cfilter(e))}function setCursor(t){$trk.css("cursor",t)}var onMove=function(){},onDone=function(){},trackDoc=options.trackDocument;return trackDoc||$trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp),$img.before($trk),{activateHandlers:activateHandlers,setCursor:setCursor}}(),KeyManager=function(){function watchKeys(){options.keySupport&&($keymgr.show(),$keymgr.focus())}function onBlur(){$keymgr.hide()}function doNudge(e,x,y){options.allowMove&&(Coords.moveOffset([x,y]),Selection.updateVisible(!0)),e.preventDefault(),e.stopPropagation()}function parseKey(e){if(e.ctrlKey||e.metaKey)return!0;shift_down=e.shiftKey?!0:!1;var nudge=shift_down?10:1;switch(e.keyCode){case 37:doNudge(e,-nudge,0);break;case 39:doNudge(e,nudge,0);break;case 38:doNudge(e,0,-nudge);break;case 40:doNudge(e,0,nudge);break;case 27:options.allowSelect&&Selection.release();break;case 9:return!0}return!1}var $keymgr=$('<input type="radio" />').css({position:"fixed",left:"-120px",width:"12px"}).addClass("jcrop-keymgr"),$keywrap=$("<div />").css({position:"absolute",overflow:"hidden"}).append($keymgr);return options.keySupport&&($keymgr.keydown(parseKey).blur(onBlur),ie6mode||!options.fixedSupport?($keymgr.css({position:"absolute",left:"-20px"}),$keywrap.append($keymgr).insertBefore($img)):$keymgr.insertBefore($img)),{watchKeys:watchKeys}}();Touch.support&&$trk.bind("touchstart.jcrop",Touch.newSelection),$hdl_holder.hide(),interfaceUpdate(!0);var api={setImage:setImage,animateTo:animateTo,setSelect:setSelect,setOptions:setOptionsNew,tellSelect:tellSelect,tellScaled:tellScaled,setClass:setClass,disable:disableCrop,enable:enableCrop,cancel:cancelCrop,release:Selection.release,destroy:destroy,focus:KeyManager.watchKeys,getBounds:function(){return[boundx*xscale,boundy*yscale]},getWidgetSize:function(){return[boundx,boundy]},getScaleFactor:function(){return[xscale,yscale]},getOptions:function(){return options},ui:{holder:$div,selection:$sel}};return is_msie&&$div.bind("selectstart",function(){return!1}),$origimg.data("Jcrop",api),api},$.fn.Jcrop=function(options,callback){var api;return this.each(function(){if($(this).data("Jcrop")){if("api"===options)return $(this).data("Jcrop");$(this).data("Jcrop").setOptions(options)}else"IMG"==this.tagName?$.Jcrop.Loader(this,function(){$(this).css({display:"block",visibility:"hidden"}),api=$.Jcrop(this,options),$.isFunction(callback)&&callback.call(api)}):($(this).css({display:"block",visibility:"hidden"}),api=$.Jcrop(this,options),$.isFunction(callback)&&callback.call(api))}),this},$.Jcrop.Loader=function(imgobj,success,error){function completeCheck(){img.complete?($img.unbind(".jcloader"),$.isFunction(success)&&success.call(img)):window.setTimeout(completeCheck,50)}var $img=$(imgobj),img=$img[0];$img.bind("load.jcloader",completeCheck).bind("error.jcloader",function(){$img.unbind(".jcloader"),$.isFunction(error)&&error.call(img)}),img.complete&&$.isFunction(success)&&($img.unbind(".jcloader"),success.call(img))},$.Jcrop.defaults={allowSelect:!0,allowMove:!0,allowResize:!0,trackDocument:!0,baseClass:"jcrop",addClass:null,bgColor:"black",bgOpacity:.6,bgFade:!1,borderOpacity:.4,handleOpacity:.5,handleSize:null,aspectRatio:0,keySupport:!0,createHandles:["n","s","e","w","nw","ne","se","sw"],createDragbars:["n","s","e","w"],createBorders:["n","s","e","w"],drawBorders:!0,dragEdges:!0,fixedSupport:!0,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}}}(jQuery);