method_draw 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +148 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/javascripts/method_draw.js +9 -0
  6. data/app/assets/javascripts/method_draw/base64.js +95 -0
  7. data/app/assets/javascripts/method_draw_embed.js +76 -0
  8. data/app/assets/stylesheets/sketchily.css +6 -0
  9. data/app/helpers/method_draw_helper.rb +35 -0
  10. data/app/views/method_draw/_embed.html.erb +51 -0
  11. data/app/views/method_draw/_method_draw.html.erb +19 -0
  12. data/app/views/method_draw/_method_draw_tag.html.erb +14 -0
  13. data/lib/method_draw.rb +16 -0
  14. data/lib/method_draw/engine.rb +4 -0
  15. data/lib/method_draw/method_draw.rb +37 -0
  16. data/lib/method_draw/method_draw_tag.rb +20 -0
  17. data/lib/method_draw/version.rb +3 -0
  18. data/spec/app/helpers/method_draw_helper_spec.rb +8 -0
  19. data/spec/dummy/README.md +3 -0
  20. data/spec/dummy/Rakefile +7 -0
  21. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  22. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  23. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  24. data/spec/dummy/app/controllers/drawings_controller.rb +18 -0
  25. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  26. data/spec/dummy/app/models/drawing.rb +2 -0
  27. data/spec/dummy/app/views/drawings/method_draw.html.erb +3 -0
  28. data/spec/dummy/app/views/drawings/method_draw_tag.html.erb +3 -0
  29. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  30. data/spec/dummy/config.ru +4 -0
  31. data/spec/dummy/config/application.rb +27 -0
  32. data/spec/dummy/config/boot.rb +5 -0
  33. data/spec/dummy/config/database.yml +25 -0
  34. data/spec/dummy/config/environment.rb +5 -0
  35. data/spec/dummy/config/environments/development.rb +29 -0
  36. data/spec/dummy/config/environments/production.rb +80 -0
  37. data/spec/dummy/config/environments/test.rb +36 -0
  38. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  39. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  40. data/spec/dummy/config/initializers/inflections.rb +16 -0
  41. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  42. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  43. data/spec/dummy/config/initializers/session_store.rb +3 -0
  44. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  45. data/spec/dummy/config/locales/en.yml +23 -0
  46. data/spec/dummy/config/routes.rb +8 -0
  47. data/spec/dummy/db/development.sqlite3 +0 -0
  48. data/spec/dummy/db/migrate/0_create_drawings.rb +7 -0
  49. data/spec/dummy/db/schema.rb +20 -0
  50. data/spec/dummy/db/test.sqlite3 +0 -0
  51. data/spec/dummy/log/development.log +922 -0
  52. data/spec/dummy/log/test.log +181 -0
  53. data/spec/dummy/public/404.html +26 -0
  54. data/spec/dummy/public/422.html +26 -0
  55. data/spec/dummy/public/500.html +25 -0
  56. data/spec/dummy/public/favicon.ico +0 -0
  57. data/spec/dummy/script/rails +6 -0
  58. data/spec/dummy/tmp/cache/assets/development/sprockets/01e63791dcd008779246d1eeeace9408 +0 -0
  59. data/spec/dummy/tmp/cache/assets/development/sprockets/061f36c32f08daef6eca93b74eaf74fd +0 -0
  60. data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  61. data/spec/dummy/tmp/cache/assets/development/sprockets/1dbfe77fba798ba3dc24571c3b6d7eed +0 -0
  62. data/spec/dummy/tmp/cache/assets/development/sprockets/1fd7477d83ec1798c2bc740be42bd6b2 +0 -0
  63. data/spec/dummy/tmp/cache/assets/development/sprockets/203471220004cb0cc667b886fb87dc46 +0 -0
  64. data/spec/dummy/tmp/cache/assets/development/sprockets/213e12fc648032455ca0b118e987cca6 +0 -0
  65. data/spec/dummy/tmp/cache/assets/development/sprockets/296bbe63b0505bc5be472fc1c8a1a5fd +0 -0
  66. data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  67. data/spec/dummy/tmp/cache/assets/development/sprockets/3239b44c026d7c1646c17a10c72905bf +0 -0
  68. data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  69. data/spec/dummy/tmp/cache/assets/development/sprockets/38c8fbf05056bbe66399b6923521dc20 +0 -0
  70. data/spec/dummy/tmp/cache/assets/development/sprockets/3e30c8cfdf7deeda4607e4a8298f09a5 +0 -0
  71. data/spec/dummy/tmp/cache/assets/development/sprockets/4bdd61ba53e8d9b7c19afea13c6e8985 +0 -0
  72. data/spec/dummy/tmp/cache/assets/development/sprockets/52b0b11efea48f1fe5e46eeb4aa20193 +0 -0
  73. data/spec/dummy/tmp/cache/assets/development/sprockets/5ef314d6f1af1570631d60b7f9a96d6c +0 -0
  74. data/spec/dummy/tmp/cache/assets/development/sprockets/6215f00c593e1789ef865a545b17fc14 +0 -0
  75. data/spec/dummy/tmp/cache/assets/development/sprockets/624fdd5478edd235a86af4b6168d0f75 +0 -0
  76. data/spec/dummy/tmp/cache/assets/development/sprockets/6299190ac3952cf7eee042e60c9aee89 +0 -0
  77. data/spec/dummy/tmp/cache/assets/development/sprockets/62a95a2d67ec78570de6d0b31436206a +0 -0
  78. data/spec/dummy/tmp/cache/assets/development/sprockets/65ed942dea29700b739c2292791eb65e +0 -0
  79. data/spec/dummy/tmp/cache/assets/development/sprockets/66eb709561f77a29885af4423a3eb193 +0 -0
  80. data/spec/dummy/tmp/cache/assets/development/sprockets/6f8f2c21bc49ae5ebad6e8a96cea4fe6 +0 -0
  81. data/spec/dummy/tmp/cache/assets/development/sprockets/85dab60ed9ec9625b7ee22d4342fe26c +0 -0
  82. data/spec/dummy/tmp/cache/assets/development/sprockets/86358bce0bfd5de6ac8afb1bfa9d675b +0 -0
  83. data/spec/dummy/tmp/cache/assets/development/sprockets/8b835ce894c1218dea1e7c83a9109d2d +0 -0
  84. data/spec/dummy/tmp/cache/assets/development/sprockets/8e177cc7106653a1e053bb2444bb43a5 +0 -0
  85. data/spec/dummy/tmp/cache/assets/development/sprockets/8f41435d82ae4df55ae7dfdc1e99b0bb +0 -0
  86. data/spec/dummy/tmp/cache/assets/development/sprockets/94be0a0bca76437d0766c265a9cdecda +0 -0
  87. data/spec/dummy/tmp/cache/assets/development/sprockets/9a093e6973aa150a0a4388167364593d +0 -0
  88. data/spec/dummy/tmp/cache/assets/development/sprockets/a280ac195f56a87267d2ec5d3e22ebcd +0 -0
  89. data/spec/dummy/tmp/cache/assets/development/sprockets/b13cddebc9106da6cfaf949ab3856d1f +0 -0
  90. data/spec/dummy/tmp/cache/assets/development/sprockets/b29ac216cb03ce2f30655a0d9bed77d4 +0 -0
  91. data/spec/dummy/tmp/cache/assets/development/sprockets/c39d32e3ef6cc89f9c522212e65c49e1 +0 -0
  92. data/spec/dummy/tmp/cache/assets/development/sprockets/c9910a0652952be02900dc71594d4384 +0 -0
  93. data/spec/dummy/tmp/cache/assets/development/sprockets/cb14e22baac3ab2cc947628f283e117b +0 -0
  94. data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  95. data/spec/dummy/tmp/cache/assets/development/sprockets/d1475c156face9f06092c9cf89905372 +0 -0
  96. data/spec/dummy/tmp/cache/assets/development/sprockets/d22aa5a4d864d00cced2437352fe8fe4 +0 -0
  97. data/spec/dummy/tmp/cache/assets/development/sprockets/d46cc5e60d1b2a20d622cdf9bab35fad +0 -0
  98. data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  99. data/spec/dummy/tmp/cache/assets/development/sprockets/d7f27a7f35278e87c69668a65683360a +0 -0
  100. data/spec/dummy/tmp/cache/assets/development/sprockets/e0080336bb31d78e9efab59b234e0d85 +0 -0
  101. data/spec/dummy/tmp/cache/assets/development/sprockets/e06104d99b055e792effca7bd66ad384 +0 -0
  102. data/spec/dummy/tmp/cache/assets/development/sprockets/e095df19da361d5f53d90f6749a38ea6 +0 -0
  103. data/spec/dummy/tmp/cache/assets/development/sprockets/e5fb97d39fdd2e383e61115ef06079fd +0 -0
  104. data/spec/dummy/tmp/cache/assets/development/sprockets/e6d1ec9817258cfda7c68499a841a9d2 +0 -0
  105. data/spec/dummy/tmp/cache/assets/development/sprockets/edec019e8f1d7e758eb45524a913fd47 +0 -0
  106. data/spec/dummy/tmp/cache/assets/development/sprockets/f37cf330dccb15bee2a195f643f3ba29 +0 -0
  107. data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  108. data/spec/dummy/tmp/cache/assets/development/sprockets/fc84011813992cacde5880c6b21701de +0 -0
  109. data/spec/dummy/tmp/cache/assets/test/sprockets/061f36c32f08daef6eca93b74eaf74fd +0 -0
  110. data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  111. data/spec/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  112. data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  113. data/spec/dummy/tmp/cache/assets/test/sprockets/38c8fbf05056bbe66399b6923521dc20 +0 -0
  114. data/spec/dummy/tmp/cache/assets/test/sprockets/3e30c8cfdf7deeda4607e4a8298f09a5 +0 -0
  115. data/spec/dummy/tmp/cache/assets/test/sprockets/52b0b11efea48f1fe5e46eeb4aa20193 +0 -0
  116. data/spec/dummy/tmp/cache/assets/test/sprockets/5ef314d6f1af1570631d60b7f9a96d6c +0 -0
  117. data/spec/dummy/tmp/cache/assets/test/sprockets/6299190ac3952cf7eee042e60c9aee89 +0 -0
  118. data/spec/dummy/tmp/cache/assets/test/sprockets/62a95a2d67ec78570de6d0b31436206a +0 -0
  119. data/spec/dummy/tmp/cache/assets/test/sprockets/65ed942dea29700b739c2292791eb65e +0 -0
  120. data/spec/dummy/tmp/cache/assets/test/sprockets/85dab60ed9ec9625b7ee22d4342fe26c +0 -0
  121. data/spec/dummy/tmp/cache/assets/test/sprockets/a280ac195f56a87267d2ec5d3e22ebcd +0 -0
  122. data/spec/dummy/tmp/cache/assets/test/sprockets/cb14e22baac3ab2cc947628f283e117b +0 -0
  123. data/spec/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  124. data/spec/dummy/tmp/cache/assets/test/sprockets/d1475c156face9f06092c9cf89905372 +0 -0
  125. data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  126. data/spec/dummy/tmp/cache/assets/test/sprockets/e0080336bb31d78e9efab59b234e0d85 +0 -0
  127. data/spec/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  128. data/spec/dummy/tmp/pids/server.pid +1 -0
  129. data/spec/features/method_draw_spec.rb +10 -0
  130. data/spec/features/method_draw_tag_spec.rb +11 -0
  131. data/spec/lib/method_draw/method_draw_spec.rb +27 -0
  132. data/spec/lib/method_draw/method_draw_tag_spec.rb +19 -0
  133. data/spec/lib/method_draw_spec.rb +11 -0
  134. data/spec/test_helper.rb +24 -0
  135. data/vendor/assets/javascripts/method-draw-js/browser-not-supported.html +27 -0
  136. data/vendor/assets/javascripts/method-draw-js/css/font-files/Anivers-webfont.eot +0 -0
  137. data/vendor/assets/javascripts/method-draw-js/css/font-files/Anivers-webfont.ttf +0 -0
  138. data/vendor/assets/javascripts/method-draw-js/css/font-files/Anivers-webfont.woff +0 -0
  139. data/vendor/assets/javascripts/method-draw-js/css/font-files/Arvo-Regular-webfont.svg +145 -0
  140. data/vendor/assets/javascripts/method-draw-js/css/font-files/Arvo-Regular-webfont.ttf +0 -0
  141. data/vendor/assets/javascripts/method-draw-js/css/font-files/Junction-webfont.eot +0 -0
  142. data/vendor/assets/javascripts/method-draw-js/css/font-files/Junction-webfont.svg +133 -0
  143. data/vendor/assets/javascripts/method-draw-js/css/font-files/Junction-webfont.ttf +0 -0
  144. data/vendor/assets/javascripts/method-draw-js/css/font-files/Junction-webfont.woff +0 -0
  145. data/vendor/assets/javascripts/method-draw-js/css/font-files/League_Gothic-webfont.eot +0 -0
  146. data/vendor/assets/javascripts/method-draw-js/css/font-files/League_Gothic-webfont.svg +235 -0
  147. data/vendor/assets/javascripts/method-draw-js/css/font-files/League_Gothic-webfont.ttf +0 -0
  148. data/vendor/assets/javascripts/method-draw-js/css/font-files/League_Gothic-webfont.woff +0 -0
  149. data/vendor/assets/javascripts/method-draw-js/css/font-files/Museo_Slab-webfont.eot +0 -0
  150. data/vendor/assets/javascripts/method-draw-js/css/font-files/Museo_Slab-webfont.ttf +0 -0
  151. data/vendor/assets/javascripts/method-draw-js/css/font-files/Museo_Slab-webfont.woff +0 -0
  152. data/vendor/assets/javascripts/method-draw-js/css/font-files/Museo_Slab_Italic-webfont.eot +0 -0
  153. data/vendor/assets/javascripts/method-draw-js/css/font-files/Museo_Slab_Italic-webfont.ttf +0 -0
  154. data/vendor/assets/javascripts/method-draw-js/css/font-files/Museo_Slab_Italic-webfont.woff +0 -0
  155. data/vendor/assets/javascripts/method-draw-js/css/font-files/arvo-bold-webfont.woff +0 -0
  156. data/vendor/assets/javascripts/method-draw-js/css/font-files/arvo-bolditalic-webfont.woff +0 -0
  157. data/vendor/assets/javascripts/method-draw-js/css/font-files/arvo-italic-webfont.woff +0 -0
  158. data/vendor/assets/javascripts/method-draw-js/css/font-files/arvo-regular-webfont.woff +0 -0
  159. data/vendor/assets/javascripts/method-draw-js/css/font-files/euphoriascript-regular-webfont.woff +0 -0
  160. data/vendor/assets/javascripts/method-draw-js/css/font-files/fanwood-webfont.eot +0 -0
  161. data/vendor/assets/javascripts/method-draw-js/css/font-files/fanwood-webfont.svg +939 -0
  162. data/vendor/assets/javascripts/method-draw-js/css/font-files/fanwood-webfont.ttf +0 -0
  163. data/vendor/assets/javascripts/method-draw-js/css/font-files/fanwood-webfont.woff +0 -0
  164. data/vendor/assets/javascripts/method-draw-js/css/font-files/fanwood_italic-webfont.eot +0 -0
  165. data/vendor/assets/javascripts/method-draw-js/css/font-files/fanwood_italic-webfont.svg +682 -0
  166. data/vendor/assets/javascripts/method-draw-js/css/font-files/fanwood_italic-webfont.ttf +0 -0
  167. data/vendor/assets/javascripts/method-draw-js/css/font-files/fanwood_italic-webfont.woff +0 -0
  168. data/vendor/assets/javascripts/method-draw-js/css/font-files/fertigo-webfont.eot +0 -0
  169. data/vendor/assets/javascripts/method-draw-js/css/font-files/fertigo-webfont.ttf +0 -0
  170. data/vendor/assets/javascripts/method-draw-js/css/font-files/fertigo-webfont.woff +0 -0
  171. data/vendor/assets/javascripts/method-draw-js/css/font-files/oswald-bold-webfont.woff +0 -0
  172. data/vendor/assets/javascripts/method-draw-js/css/font-files/oswald-light-webfont.woff +0 -0
  173. data/vendor/assets/javascripts/method-draw-js/css/font-files/shadowsintolight-webfont.woff +0 -0
  174. data/vendor/assets/javascripts/method-draw-js/css/font-files/simonetta-black-webfont.woff +0 -0
  175. data/vendor/assets/javascripts/method-draw-js/css/font-files/simonetta-blackitalic-webfont.woff +0 -0
  176. data/vendor/assets/javascripts/method-draw-js/css/font-files/simonetta-italic-webfont.ttf +0 -0
  177. data/vendor/assets/javascripts/method-draw-js/css/font-files/simonetta-regular-webfont.woff +0 -0
  178. data/vendor/assets/javascripts/method-draw-js/css/font-files/test.html +62 -0
  179. data/vendor/assets/javascripts/method-draw-js/css/font-files/test.svg +15 -0
  180. data/vendor/assets/javascripts/method-draw-js/css/font-files/test_ff.svg +16 -0
  181. data/vendor/assets/javascripts/method-draw-js/css/font-files/test_ffsvg.svg +13 -0
  182. data/vendor/assets/javascripts/method-draw-js/css/fonts.css +72 -0
  183. data/vendor/assets/javascripts/method-draw-js/css/method-draw.compiled.css +417 -0
  184. data/vendor/assets/javascripts/method-draw-js/css/method-draw.css +2083 -0
  185. data/vendor/assets/javascripts/method-draw-js/embedapi.html +56 -0
  186. data/vendor/assets/javascripts/method-draw-js/extensions/closepath_icons.svg +41 -0
  187. data/vendor/assets/javascripts/method-draw-js/extensions/ext-arrows.js +298 -0
  188. data/vendor/assets/javascripts/method-draw-js/extensions/ext-closepath.js +92 -0
  189. data/vendor/assets/javascripts/method-draw-js/extensions/ext-connector.js +587 -0
  190. data/vendor/assets/javascripts/method-draw-js/extensions/ext-eyedropper.js +135 -0
  191. data/vendor/assets/javascripts/method-draw-js/extensions/ext-foreignobject.js +277 -0
  192. data/vendor/assets/javascripts/method-draw-js/extensions/ext-grid.js +186 -0
  193. data/vendor/assets/javascripts/method-draw-js/extensions/ext-helloworld.js +78 -0
  194. data/vendor/assets/javascripts/method-draw-js/extensions/ext-imagelib.js +444 -0
  195. data/vendor/assets/javascripts/method-draw-js/extensions/ext-imagelib.xml +14 -0
  196. data/vendor/assets/javascripts/method-draw-js/extensions/ext-markers.js +576 -0
  197. data/vendor/assets/javascripts/method-draw-js/extensions/ext-server_moinsave.js +56 -0
  198. data/vendor/assets/javascripts/method-draw-js/extensions/ext-server_opensave.js +180 -0
  199. data/vendor/assets/javascripts/method-draw-js/extensions/ext-shapes.js +358 -0
  200. data/vendor/assets/javascripts/method-draw-js/extensions/ext-shapes.png +0 -0
  201. data/vendor/assets/javascripts/method-draw-js/extensions/ext-shapes.xml +8 -0
  202. data/vendor/assets/javascripts/method-draw-js/extensions/eyedropper-icon.xml +17 -0
  203. data/vendor/assets/javascripts/method-draw-js/extensions/eyedropper.png +0 -0
  204. data/vendor/assets/javascripts/method-draw-js/extensions/eyedropper.svg +15 -0
  205. data/vendor/assets/javascripts/method-draw-js/extensions/fileopen.php +31 -0
  206. data/vendor/assets/javascripts/method-draw-js/extensions/filesave.php +44 -0
  207. data/vendor/assets/javascripts/method-draw-js/extensions/foreignobject-icons.xml +96 -0
  208. data/vendor/assets/javascripts/method-draw-js/extensions/grid-icon.xml +30 -0
  209. data/vendor/assets/javascripts/method-draw-js/extensions/helloworld-icon.xml +21 -0
  210. data/vendor/assets/javascripts/method-draw-js/extensions/imagelib/index.html +64 -0
  211. data/vendor/assets/javascripts/method-draw-js/extensions/imagelib/smiley.svg +12 -0
  212. data/vendor/assets/javascripts/method-draw-js/extensions/markers-icons.xml +115 -0
  213. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib.png +0 -0
  214. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib.svg +10 -0
  215. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/arrow.json +40 -0
  216. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/dialog_balloon.json +14 -0
  217. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/flowchart.json +20 -0
  218. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/game.json +13 -0
  219. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/math.json +8 -0
  220. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/misc.json +6 -0
  221. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/music.json +21 -0
  222. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/nature.json +36 -0
  223. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/object.json +30 -0
  224. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/raphael.txt +12 -0
  225. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/raphael_1.json +7 -0
  226. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/social.json +21 -0
  227. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/symbol.json +35 -0
  228. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/ui.json +57 -0
  229. data/vendor/assets/javascripts/method-draw-js/extensions/shapelib/weather.json +26 -0
  230. data/vendor/assets/javascripts/method-draw-js/icons/jquery.svgicons.js +471 -0
  231. data/vendor/assets/javascripts/method-draw-js/images/AlphaBar.png +0 -0
  232. data/vendor/assets/javascripts/method-draw-js/images/Bars.png +0 -0
  233. data/vendor/assets/javascripts/method-draw-js/images/Maps.png +0 -0
  234. data/vendor/assets/javascripts/method-draw-js/images/NoColor.png +0 -0
  235. data/vendor/assets/javascripts/method-draw-js/images/README.txt +61 -0
  236. data/vendor/assets/javascripts/method-draw-js/images/align-bottom.png +0 -0
  237. data/vendor/assets/javascripts/method-draw-js/images/align-bottom.svg +1 -0
  238. data/vendor/assets/javascripts/method-draw-js/images/align-center.png +0 -0
  239. data/vendor/assets/javascripts/method-draw-js/images/align-center.svg +1 -0
  240. data/vendor/assets/javascripts/method-draw-js/images/align-left.png +0 -0
  241. data/vendor/assets/javascripts/method-draw-js/images/align-left.svg +1 -0
  242. data/vendor/assets/javascripts/method-draw-js/images/align-middle.png +0 -0
  243. data/vendor/assets/javascripts/method-draw-js/images/align-middle.svg +1 -0
  244. data/vendor/assets/javascripts/method-draw-js/images/align-right.png +0 -0
  245. data/vendor/assets/javascripts/method-draw-js/images/align-right.svg +1 -0
  246. data/vendor/assets/javascripts/method-draw-js/images/align-top.png +0 -0
  247. data/vendor/assets/javascripts/method-draw-js/images/align-top.svg +1 -0
  248. data/vendor/assets/javascripts/method-draw-js/images/bar-opacity.png +0 -0
  249. data/vendor/assets/javascripts/method-draw-js/images/bold.png +0 -0
  250. data/vendor/assets/javascripts/method-draw-js/images/cancel.png +0 -0
  251. data/vendor/assets/javascripts/method-draw-js/images/circle.png +0 -0
  252. data/vendor/assets/javascripts/method-draw-js/images/clear.png +0 -0
  253. data/vendor/assets/javascripts/method-draw-js/images/clone.png +0 -0
  254. data/vendor/assets/javascripts/method-draw-js/images/conn.svg +29 -0
  255. data/vendor/assets/javascripts/method-draw-js/images/copy.png +0 -0
  256. data/vendor/assets/javascripts/method-draw-js/images/cross.png +0 -0
  257. data/vendor/assets/javascripts/method-draw-js/images/cut.png +0 -0
  258. data/vendor/assets/javascripts/method-draw-js/images/delete.png +0 -0
  259. data/vendor/assets/javascripts/method-draw-js/images/document-properties.png +0 -0
  260. data/vendor/assets/javascripts/method-draw-js/images/drag.png +0 -0
  261. data/vendor/assets/javascripts/method-draw-js/images/dragging.png +0 -0
  262. data/vendor/assets/javascripts/method-draw-js/images/dropdown.gif +0 -0
  263. data/vendor/assets/javascripts/method-draw-js/images/ellipse.png +0 -0
  264. data/vendor/assets/javascripts/method-draw-js/images/ellipse.svg +8 -0
  265. data/vendor/assets/javascripts/method-draw-js/images/eye.png +0 -0
  266. data/vendor/assets/javascripts/method-draw-js/images/eye.svg +1 -0
  267. data/vendor/assets/javascripts/method-draw-js/images/eyedropper.png +0 -0
  268. data/vendor/assets/javascripts/method-draw-js/images/eyedropper_tool.png +0 -0
  269. data/vendor/assets/javascripts/method-draw-js/images/fhpath.png +0 -0
  270. data/vendor/assets/javascripts/method-draw-js/images/flyouth.png +0 -0
  271. data/vendor/assets/javascripts/method-draw-js/images/flyup.gif +0 -0
  272. data/vendor/assets/javascripts/method-draw-js/images/freehand-circle.png +0 -0
  273. data/vendor/assets/javascripts/method-draw-js/images/freehand-square.png +0 -0
  274. data/vendor/assets/javascripts/method-draw-js/images/go-down.png +0 -0
  275. data/vendor/assets/javascripts/method-draw-js/images/go-up.png +0 -0
  276. data/vendor/assets/javascripts/method-draw-js/images/image.png +0 -0
  277. data/vendor/assets/javascripts/method-draw-js/images/image.svg +12 -0
  278. data/vendor/assets/javascripts/method-draw-js/images/italic.png +0 -0
  279. data/vendor/assets/javascripts/method-draw-js/images/italic.svg +1 -0
  280. data/vendor/assets/javascripts/method-draw-js/images/line.png +0 -0
  281. data/vendor/assets/javascripts/method-draw-js/images/link_controls.png +0 -0
  282. data/vendor/assets/javascripts/method-draw-js/images/logo.png +0 -0
  283. data/vendor/assets/javascripts/method-draw-js/images/map-opacity.png +0 -0
  284. data/vendor/assets/javascripts/method-draw-js/images/mappoint.gif +0 -0
  285. data/vendor/assets/javascripts/method-draw-js/images/mappoint_c.png +0 -0
  286. data/vendor/assets/javascripts/method-draw-js/images/mappoint_f.png +0 -0
  287. data/vendor/assets/javascripts/method-draw-js/images/move_bottom.png +0 -0
  288. data/vendor/assets/javascripts/method-draw-js/images/move_top.png +0 -0
  289. data/vendor/assets/javascripts/method-draw-js/images/node_clone.png +0 -0
  290. data/vendor/assets/javascripts/method-draw-js/images/node_delete.png +0 -0
  291. data/vendor/assets/javascripts/method-draw-js/images/none.png +0 -0
  292. data/vendor/assets/javascripts/method-draw-js/images/open.png +0 -0
  293. data/vendor/assets/javascripts/method-draw-js/images/paste.png +0 -0
  294. data/vendor/assets/javascripts/method-draw-js/images/path.png +0 -0
  295. data/vendor/assets/javascripts/method-draw-js/images/path.svg +10 -0
  296. data/vendor/assets/javascripts/method-draw-js/images/pencil.png +0 -0
  297. data/vendor/assets/javascripts/method-draw-js/images/pencil.svg +11 -0
  298. data/vendor/assets/javascripts/method-draw-js/images/pencil_cursor.png +0 -0
  299. data/vendor/assets/javascripts/method-draw-js/images/picker.gif +0 -0
  300. data/vendor/assets/javascripts/method-draw-js/images/placeholder.svg +10 -0
  301. data/vendor/assets/javascripts/method-draw-js/images/polygon.png +0 -0
  302. data/vendor/assets/javascripts/method-draw-js/images/polygon.svg +1 -0
  303. data/vendor/assets/javascripts/method-draw-js/images/preview-opacity.png +0 -0
  304. data/vendor/assets/javascripts/method-draw-js/images/rangearrows.gif +0 -0
  305. data/vendor/assets/javascripts/method-draw-js/images/rangearrows2.gif +0 -0
  306. data/vendor/assets/javascripts/method-draw-js/images/rect.png +0 -0
  307. data/vendor/assets/javascripts/method-draw-js/images/redo.png +0 -0
  308. data/vendor/assets/javascripts/method-draw-js/images/reorient.png +0 -0
  309. data/vendor/assets/javascripts/method-draw-js/images/rotate.png +0 -0
  310. data/vendor/assets/javascripts/method-draw-js/images/save.png +0 -0
  311. data/vendor/assets/javascripts/method-draw-js/images/select.png +0 -0
  312. data/vendor/assets/javascripts/method-draw-js/images/select.svg +10 -0
  313. data/vendor/assets/javascripts/method-draw-js/images/select_node.png +0 -0
  314. data/vendor/assets/javascripts/method-draw-js/images/sep.png +0 -0
  315. data/vendor/assets/javascripts/method-draw-js/images/shape_group.png +0 -0
  316. data/vendor/assets/javascripts/method-draw-js/images/shape_ungroup.png +0 -0
  317. data/vendor/assets/javascripts/method-draw-js/images/source.png +0 -0
  318. data/vendor/assets/javascripts/method-draw-js/images/spinbtn_updn_big.png +0 -0
  319. data/vendor/assets/javascripts/method-draw-js/images/square.png +0 -0
  320. data/vendor/assets/javascripts/method-draw-js/images/svg_edit_icons.svg +455 -0
  321. data/vendor/assets/javascripts/method-draw-js/images/svg_edit_icons.svgz +0 -0
  322. data/vendor/assets/javascripts/method-draw-js/images/text.png +0 -0
  323. data/vendor/assets/javascripts/method-draw-js/images/text.svg +10 -0
  324. data/vendor/assets/javascripts/method-draw-js/images/to_path.png +0 -0
  325. data/vendor/assets/javascripts/method-draw-js/images/undo.png +0 -0
  326. data/vendor/assets/javascripts/method-draw-js/images/view-refresh.png +0 -0
  327. data/vendor/assets/javascripts/method-draw-js/images/wave.png +0 -0
  328. data/vendor/assets/javascripts/method-draw-js/images/wireframe.png +0 -0
  329. data/vendor/assets/javascripts/method-draw-js/images/zoom.png +0 -0
  330. data/vendor/assets/javascripts/method-draw-js/images/zoom.svg +12 -0
  331. data/vendor/assets/javascripts/method-draw-js/index.html +631 -0
  332. data/vendor/assets/javascripts/method-draw-js/lib/canvg/canvg.js +2620 -0
  333. data/vendor/assets/javascripts/method-draw-js/lib/canvg/rgbcolor.js +287 -0
  334. data/vendor/assets/javascripts/method-draw-js/lib/contextmenu.js +68 -0
  335. data/vendor/assets/javascripts/method-draw-js/lib/contextmenu/jquery.contextMenu.js +223 -0
  336. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/LICENSE +202 -0
  337. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/README +3 -0
  338. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/css/jPicker.css +250 -0
  339. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/css/jgraduate.css +332 -0
  340. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/AlphaBar.png +0 -0
  341. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/Bars.png +0 -0
  342. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/Maps.png +0 -0
  343. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/NoColor.png +0 -0
  344. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/bar-opacity.png +0 -0
  345. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/eyedropper.png +0 -0
  346. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/map-opacity.png +0 -0
  347. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/mappoint.gif +0 -0
  348. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/mappoint_c.png +0 -0
  349. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/mappoint_f.png +0 -0
  350. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/picker.gif +0 -0
  351. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/preview-opacity.png +0 -0
  352. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/rangearrows.gif +0 -0
  353. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/images/rangearrows2.gif +0 -0
  354. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/jpicker.min.js +2087 -0
  355. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/jquery.jgraduate.js +1175 -0
  356. data/vendor/assets/javascripts/method-draw-js/lib/jgraduate/jquery.jgraduate.min.js +37 -0
  357. data/vendor/assets/javascripts/method-draw-js/lib/jquery-draginput.js +181 -0
  358. data/vendor/assets/javascripts/method-draw-js/lib/jquery-ui/jquery-ui-1.8.17.custom.min.js +54 -0
  359. data/vendor/assets/javascripts/method-draw-js/lib/jquery-ui/jquery-ui-1.8.custom.min.js +84 -0
  360. data/vendor/assets/javascripts/method-draw-js/lib/jquery.js +2 -0
  361. data/vendor/assets/javascripts/method-draw-js/lib/jquerybbq/jquery.bbq.min.js +18 -0
  362. data/vendor/assets/javascripts/method-draw-js/lib/js-hotkeys/README.md +45 -0
  363. data/vendor/assets/javascripts/method-draw-js/lib/js-hotkeys/jquery.hotkeys.min.js +15 -0
  364. data/vendor/assets/javascripts/method-draw-js/lib/mousewheel.js +84 -0
  365. data/vendor/assets/javascripts/method-draw-js/lib/requestanimationframe.js +24 -0
  366. data/vendor/assets/javascripts/method-draw-js/lib/taphold.js +136 -0
  367. data/vendor/assets/javascripts/method-draw-js/lib/touch.js +28 -0
  368. data/vendor/assets/javascripts/method-draw-js/method-draw.compiled.css +417 -0
  369. data/vendor/assets/javascripts/method-draw-js/method-draw.compiled.js +692 -0
  370. data/vendor/assets/javascripts/method-draw-js/method-draw.manifest +121 -0
  371. data/vendor/assets/javascripts/method-draw-js/src/browser.js +181 -0
  372. data/vendor/assets/javascripts/method-draw-js/src/dialog.js +49 -0
  373. data/vendor/assets/javascripts/method-draw-js/src/dragupload.js +11 -0
  374. data/vendor/assets/javascripts/method-draw-js/src/draw.js +533 -0
  375. data/vendor/assets/javascripts/method-draw-js/src/embedapi.js +173 -0
  376. data/vendor/assets/javascripts/method-draw-js/src/history.js +601 -0
  377. data/vendor/assets/javascripts/method-draw-js/src/math.js +247 -0
  378. data/vendor/assets/javascripts/method-draw-js/src/method-draw.js +4140 -0
  379. data/vendor/assets/javascripts/method-draw-js/src/path.js +979 -0
  380. data/vendor/assets/javascripts/method-draw-js/src/sanitize.js +273 -0
  381. data/vendor/assets/javascripts/method-draw-js/src/select.js +608 -0
  382. data/vendor/assets/javascripts/method-draw-js/src/svgcanvas.js +9047 -0
  383. data/vendor/assets/javascripts/method-draw-js/src/svgtransformlist.js +291 -0
  384. data/vendor/assets/javascripts/method-draw-js/src/svgutils.js +648 -0
  385. data/vendor/assets/javascripts/method-draw-js/src/units.js +281 -0
  386. data/vendor/assets/javascripts/method-draw-js/svgedit.compiled.css +417 -0
  387. data/vendor/assets/javascripts/method-draw-js/svgedit.compiled.js +691 -0
  388. data/vendor/assets/javascripts/method-draw-js/temp.css +2665 -0
  389. metadata +619 -0
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Package: svedit.math
3
+ *
4
+ * Licensed under the Apache License, Version 2
5
+ *
6
+ * Copyright(c) 2010 Alexis Deveria
7
+ * Copyright(c) 2010 Jeff Schiller
8
+ */
9
+
10
+ // Dependencies:
11
+ // None.
12
+
13
+ var svgedit = svgedit || {};
14
+
15
+ (function() {
16
+
17
+ if (!svgedit.math) {
18
+ svgedit.math = {};
19
+ }
20
+
21
+ // Constants
22
+ var NEAR_ZERO = 1e-14;
23
+
24
+ // Throw away SVGSVGElement used for creating matrices/transforms.
25
+ var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
26
+
27
+ // Function: svgedit.math.transformPoint
28
+ // A (hopefully) quicker function to transform a point by a matrix
29
+ // (this function avoids any DOM calls and just does the math)
30
+ //
31
+ // Parameters:
32
+ // x - Float representing the x coordinate
33
+ // y - Float representing the y coordinate
34
+ // m - Matrix object to transform the point with
35
+ // Returns a x,y object representing the transformed point
36
+ svgedit.math.transformPoint = function(x, y, m) {
37
+ return { x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f};
38
+ };
39
+
40
+
41
+ // Function: svgedit.math.isIdentity
42
+ // Helper function to check if the matrix performs no actual transform
43
+ // (i.e. exists for identity purposes)
44
+ //
45
+ // Parameters:
46
+ // m - The matrix object to check
47
+ //
48
+ // Returns:
49
+ // Boolean indicating whether or not the matrix is 1,0,0,1,0,0
50
+ svgedit.math.isIdentity = function(m) {
51
+ return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0);
52
+ };
53
+
54
+
55
+ // Function: svgedit.math.matrixMultiply
56
+ // This function tries to return a SVGMatrix that is the multiplication m1*m2.
57
+ // We also round to zero when it's near zero
58
+ //
59
+ // Parameters:
60
+ // >= 2 Matrix objects to multiply
61
+ //
62
+ // Returns:
63
+ // The matrix object resulting from the calculation
64
+ svgedit.math.matrixMultiply = function() {
65
+ var args = arguments, i = args.length, m = args[i-1];
66
+
67
+ while(i-- > 1) {
68
+ var m1 = args[i-1];
69
+ m = m1.multiply(m);
70
+ }
71
+ if (Math.abs(m.a) < NEAR_ZERO) m.a = 0;
72
+ if (Math.abs(m.b) < NEAR_ZERO) m.b = 0;
73
+ if (Math.abs(m.c) < NEAR_ZERO) m.c = 0;
74
+ if (Math.abs(m.d) < NEAR_ZERO) m.d = 0;
75
+ if (Math.abs(m.e) < NEAR_ZERO) m.e = 0;
76
+ if (Math.abs(m.f) < NEAR_ZERO) m.f = 0;
77
+
78
+ return m;
79
+ };
80
+
81
+ // Function: svgedit.math.hasMatrixTransform
82
+ // See if the given transformlist includes a non-indentity matrix transform
83
+ //
84
+ // Parameters:
85
+ // tlist - The transformlist to check
86
+ //
87
+ // Returns:
88
+ // Boolean on whether or not a matrix transform was found
89
+ svgedit.math.hasMatrixTransform = function(tlist) {
90
+ if(!tlist) return false;
91
+ var num = tlist.numberOfItems;
92
+ while (num--) {
93
+ var xform = tlist.getItem(num);
94
+ if (xform.type == 1 && !svgedit.math.isIdentity(xform.matrix)) return true;
95
+ }
96
+ return false;
97
+ };
98
+
99
+ // Function: svgedit.math.transformBox
100
+ // Transforms a rectangle based on the given matrix
101
+ //
102
+ // Parameters:
103
+ // l - Float with the box's left coordinate
104
+ // t - Float with the box's top coordinate
105
+ // w - Float with the box width
106
+ // h - Float with the box height
107
+ // m - Matrix object to transform the box by
108
+ //
109
+ // Returns:
110
+ // An object with the following values:
111
+ // * tl - The top left coordinate (x,y object)
112
+ // * tr - The top right coordinate (x,y object)
113
+ // * bl - The bottom left coordinate (x,y object)
114
+ // * br - The bottom right coordinate (x,y object)
115
+ // * aabox - Object with the following values:
116
+ // * Float with the axis-aligned x coordinate
117
+ // * Float with the axis-aligned y coordinate
118
+ // * Float with the axis-aligned width coordinate
119
+ // * Float with the axis-aligned height coordinate
120
+ svgedit.math.transformBox = function(l, t, w, h, m) {
121
+ var topleft = {x:l,y:t},
122
+ topright = {x:(l+w),y:t},
123
+ botright = {x:(l+w),y:(t+h)},
124
+ botleft = {x:l,y:(t+h)};
125
+ var transformPoint = svgedit.math.transformPoint;
126
+ topleft = transformPoint( topleft.x, topleft.y, m );
127
+ var minx = topleft.x,
128
+ maxx = topleft.x,
129
+ miny = topleft.y,
130
+ maxy = topleft.y;
131
+ topright = transformPoint( topright.x, topright.y, m );
132
+ minx = Math.min(minx, topright.x);
133
+ maxx = Math.max(maxx, topright.x);
134
+ miny = Math.min(miny, topright.y);
135
+ maxy = Math.max(maxy, topright.y);
136
+ botleft = transformPoint( botleft.x, botleft.y, m);
137
+ minx = Math.min(minx, botleft.x);
138
+ maxx = Math.max(maxx, botleft.x);
139
+ miny = Math.min(miny, botleft.y);
140
+ maxy = Math.max(maxy, botleft.y);
141
+ botright = transformPoint( botright.x, botright.y, m );
142
+ minx = Math.min(minx, botright.x);
143
+ maxx = Math.max(maxx, botright.x);
144
+ miny = Math.min(miny, botright.y);
145
+ maxy = Math.max(maxy, botright.y);
146
+
147
+ return {tl:topleft, tr:topright, bl:botleft, br:botright,
148
+ aabox: {x:minx, y:miny, width:(maxx-minx), height:(maxy-miny)} };
149
+ };
150
+
151
+ // Function: svgedit.math.transformListToTransform
152
+ // This returns a single matrix Transform for a given Transform List
153
+ // (this is the equivalent of SVGTransformList.consolidate() but unlike
154
+ // that method, this one does not modify the actual SVGTransformList)
155
+ // This function is very liberal with its min,max arguments
156
+ //
157
+ // Parameters:
158
+ // tlist - The transformlist object
159
+ // min - Optional integer indicating start transform position
160
+ // max - Optional integer indicating end transform position
161
+ //
162
+ // Returns:
163
+ // A single matrix transform object
164
+ svgedit.math.transformListToTransform = function(tlist, min, max) {
165
+ if(tlist == null) {
166
+ // Or should tlist = null have been prevented before this?
167
+ return svg.createSVGTransformFromMatrix(svg.createSVGMatrix());
168
+ }
169
+ var min = min == undefined ? 0 : min;
170
+ var max = max == undefined ? (tlist.numberOfItems-1) : max;
171
+ min = parseInt(min);
172
+ max = parseInt(max);
173
+ if (min > max) { var temp = max; max = min; min = temp; }
174
+ var m = svg.createSVGMatrix();
175
+ for (var i = min; i <= max; ++i) {
176
+ // if our indices are out of range, just use a harmless identity matrix
177
+ var mtom = (i >= 0 && i < tlist.numberOfItems ?
178
+ tlist.getItem(i).matrix :
179
+ svg.createSVGMatrix());
180
+ m = svgedit.math.matrixMultiply(m, mtom);
181
+ }
182
+ return svg.createSVGTransformFromMatrix(m);
183
+ };
184
+
185
+
186
+ // Function: svgedit.math.getMatrix
187
+ // Get the matrix object for a given element
188
+ //
189
+ // Parameters:
190
+ // elem - The DOM element to check
191
+ //
192
+ // Returns:
193
+ // The matrix object associated with the element's transformlist
194
+ svgedit.math.getMatrix = function(elem) {
195
+ var tlist = svgedit.transformlist.getTransformList(elem);
196
+ return svgedit.math.transformListToTransform(tlist).matrix;
197
+ };
198
+
199
+
200
+ // Function: svgedit.math.snapToAngle
201
+ // Returns a 45 degree angle coordinate associated with the two given
202
+ // coordinates
203
+ //
204
+ // Parameters:
205
+ // x1 - First coordinate's x value
206
+ // x2 - Second coordinate's x value
207
+ // y1 - First coordinate's y value
208
+ // y2 - Second coordinate's y value
209
+ //
210
+ // Returns:
211
+ // Object with the following values:
212
+ // x - The angle-snapped x value
213
+ // y - The angle-snapped y value
214
+ // snapangle - The angle at which to snap
215
+ svgedit.math.snapToAngle = function(x1,y1,x2,y2) {
216
+ var snap = Math.PI/4; // 45 degrees
217
+ var dx = x2 - x1;
218
+ var dy = y2 - y1;
219
+ var angle = Math.atan2(dy,dx);
220
+ var dist = Math.sqrt(dx * dx + dy * dy);
221
+ var snapangle= Math.round(angle/snap)*snap;
222
+ var x = x1 + dist*Math.cos(snapangle);
223
+ var y = y1 + dist*Math.sin(snapangle);
224
+ //console.log(x1,y1,x2,y2,x,y,angle)
225
+ return {x:x, y:y, a:snapangle};
226
+ };
227
+
228
+
229
+ // Function: rectsIntersect
230
+ // Check if two rectangles (BBoxes objects) intersect each other
231
+ //
232
+ // Paramaters:
233
+ // r1 - The first BBox-like object
234
+ // r2 - The second BBox-like object
235
+ //
236
+ // Returns:
237
+ // Boolean that's true if rectangles intersect
238
+ svgedit.math.rectsIntersect = function(r1, r2) {
239
+ if (!r1 || !r2) return false;
240
+ return r2.x < (r1.x+r1.width) &&
241
+ (r2.x+r2.width) > r1.x &&
242
+ r2.y < (r1.y+r1.height) &&
243
+ (r2.y+r2.height) > r1.y;
244
+ };
245
+
246
+
247
+ })();
@@ -0,0 +1,4140 @@
1
+ /*
2
+ * svg-editor.js
3
+ *
4
+ * Licensed under the MIT License
5
+ *
6
+ * Copyright(c) 2010 Alexis Deveria
7
+ * Copyright(c) 2010 Pavol Rusnak
8
+ * Copyright(c) 2010 Jeff Schiller
9
+ * Copyright(c) 2010 Narendra Sisodiya
10
+ * Copyright(c) 2012 Mark MacKay
11
+ *
12
+ */
13
+
14
+ // Dependencies:
15
+ // 1) units.js
16
+ // 2) browser.js
17
+ // 3) svgcanvas.js
18
+
19
+ (function() {
20
+
21
+ document.addEventListener("touchstart", touchHandler, true);
22
+ document.addEventListener("touchmove", touchHandler, true);
23
+ document.addEventListener("touchend", touchHandler, true);
24
+ document.addEventListener("touchcancel", touchHandler, true);
25
+
26
+ if(!window.methodDraw) window.methodDraw = function($) {
27
+ var svgCanvas;
28
+ var Editor = {};
29
+ var is_ready = false;
30
+ curConfig = {
31
+ canvas_expansion: 1,
32
+ dimensions: [580,400],
33
+ initFill: {color: 'fff', opacity: 1},
34
+ initStroke: {width: 1.5, color: '000', opacity: 1},
35
+ initOpacity: 1,
36
+ imgPath: 'images/',
37
+ extPath: 'extensions/',
38
+ jGraduatePath: 'jgraduate/images/',
39
+ extensions: [],
40
+ initTool: 'select',
41
+ wireframe: false,
42
+ colorPickerCSS: false,
43
+ gridSnapping: false,
44
+ gridColor: "#000",
45
+ baseUnit: 'px',
46
+ snappingStep: 10,
47
+ showRulers: (svgedit.browser.isTouch()) ? false : true,
48
+ show_outside_canvas: false,
49
+ no_save_warning: true,
50
+ initFont: 'Helvetica, Arial, sans-serif'
51
+ },
52
+ uiStrings = Editor.uiStrings = {
53
+ common: {
54
+ "ok":"OK",
55
+ "cancel":"Cancel",
56
+ "key_up":"Up",
57
+ "key_down":"Down",
58
+ "key_backspace":"Backspace",
59
+ "key_del":"Del"
60
+
61
+ },
62
+ // This is needed if the locale is English, since the locale strings are not read in that instance.
63
+ layers: {
64
+ "layer":"Layer"
65
+ },
66
+ notification: {
67
+ "invalidAttrValGiven":"Invalid value given",
68
+ "noContentToFitTo":"No content to fit to",
69
+ "dupeLayerName":"There is already a layer named that!",
70
+ "enterUniqueLayerName":"Please enter a unique layer name",
71
+ "enterNewLayerName":"Please enter the new layer name",
72
+ "layerHasThatName":"Layer already has that name",
73
+ "QmoveElemsToLayer":"Move selected elements to layer \"%s\"?",
74
+ "QwantToClear":"<strong>Do you want to clear the drawing?</strong>\nThis will also erase your undo history",
75
+ "QwantToOpen":"Do you want to open a new file?\nThis will also erase your undo history",
76
+ "QerrorsRevertToSource":"There were parsing errors in your SVG source.\nRevert back to original SVG source?",
77
+ "QignoreSourceChanges":"Ignore changes made to SVG source?",
78
+ "featNotSupported":"Feature not supported",
79
+ "enterNewImgURL":"Enter the new image URL",
80
+ "defsFailOnSave": "NOTE: Due to a bug in your browser, this image may appear wrong (missing gradients or elements). It will however appear correct once actually saved.",
81
+ "loadingImage":"Loading image, please wait...",
82
+ "saveFromBrowser": "Select \"Save As...\" in your browser to save this image as a %s file.",
83
+ "noteTheseIssues": "Also note the following issues: ",
84
+ "unsavedChanges": "There are unsaved changes.",
85
+ "enterNewLinkURL": "Enter the new hyperlink URL",
86
+ "errorLoadingSVG": "Error: Unable to load SVG data",
87
+ "URLloadFail": "Unable to load from URL",
88
+ "retrieving": 'Retrieving "%s" ...'
89
+ }
90
+ };
91
+
92
+
93
+ var curPrefs = {}; //$.extend({}, defaultPrefs);
94
+ var customHandlers = {};
95
+ Editor.curConfig = curConfig;
96
+ Editor.tool_scale = 1;
97
+
98
+ Editor.setConfig = function(opts) {
99
+ $.extend(true, curConfig, opts);
100
+ if(opts.extensions) {
101
+ curConfig.extensions = opts.extensions;
102
+ }
103
+ }
104
+
105
+ // Extension mechanisms must call setCustomHandlers with two functions: opts.open and opts.save
106
+ // opts.open's responsibilities are:
107
+ // - invoke a file chooser dialog in 'open' mode
108
+ // - let user pick a SVG file
109
+ // - calls setCanvas.setSvgString() with the string contents of that file
110
+ // opts.save's responsibilities are:
111
+ // - accept the string contents of the current document
112
+ // - invoke a file chooser dialog in 'save' mode
113
+ // - save the file to location chosen by the user
114
+ Editor.setCustomHandlers = function(opts) {
115
+ Editor.ready(function() {
116
+ if(opts.open) {
117
+ $('#tool_open > input[type="file"]').remove();
118
+ $('#tool_open').show();
119
+ svgCanvas.open = opts.open;
120
+ }
121
+ if(opts.save) {
122
+ Editor.show_save_warning = false;
123
+ svgCanvas.bind("saved", opts.save);
124
+ }
125
+ if(opts.pngsave) {
126
+ svgCanvas.bind("exported", opts.pngsave);
127
+ }
128
+ customHandlers = opts;
129
+ });
130
+ }
131
+
132
+ Editor.randomizeIds = function() {
133
+ svgCanvas.randomizeIds(arguments)
134
+ }
135
+
136
+ Editor.init = function() {
137
+ // For external openers
138
+ (function() {
139
+ // let the opener know SVG Edit is ready
140
+ var w = window.opener;
141
+ if (w) {
142
+ try {
143
+ var methodDrawReadyEvent = w.document.createEvent("Event");
144
+ methodDrawReadyEvent.initEvent("methodDrawReady", true, true);
145
+ w.document.documentElement.dispatchEvent(methodDrawReadyEvent);
146
+ }
147
+ catch(e) {}
148
+ }
149
+ })();
150
+
151
+ (function() {
152
+ $("body").toggleClass("touch", svgedit.browser.isTouch());
153
+ // Load config/data from URL if given
154
+ var urldata = $.deparam.querystring(true);
155
+ if(!$.isEmptyObject(urldata)) {
156
+ if(urldata.dimensions) {
157
+ urldata.dimensions = urldata.dimensions.split(',');
158
+ }
159
+
160
+ if(urldata.extensions) {
161
+ urldata.extensions = urldata.extensions.split(',');
162
+ }
163
+
164
+ if(urldata.bkgd_color) {
165
+ urldata.bkgd_color = '#' + urldata.bkgd_color;
166
+ }
167
+
168
+ methodDraw.setConfig(urldata);
169
+
170
+ var src = urldata.source;
171
+ var qstr = $.param.querystring();
172
+
173
+ if(!src) { // urldata.source may have been null if it ended with '='
174
+ if(qstr.indexOf('source=data:') >= 0) {
175
+ src = qstr.match(/source=(data:[^&]*)/)[1];
176
+ }
177
+ }
178
+
179
+ if(src) {
180
+ if(src.indexOf("data:") === 0) {
181
+ // plusses get replaced by spaces, so re-insert
182
+ src = src.replace(/ /g, "+");
183
+ Editor.loadFromDataURI(src);
184
+ } else {
185
+ Editor.loadFromString(src);
186
+ }
187
+ } else if(qstr.indexOf('paramurl=') !== -1) {
188
+ // Get paramater URL (use full length of remaining location.href)
189
+ methodDraw.loadFromURL(qstr.substr(9));
190
+ } else if(urldata.url) {
191
+ methodDraw.loadFromURL(urldata.url);
192
+ }
193
+ }
194
+ })();
195
+
196
+ $("#canvas_width").val(curConfig.dimensions[0]);
197
+ $("#canvas_height").val(curConfig.dimensions[1]);
198
+
199
+ var extFunc = function() {
200
+ $.each(curConfig.extensions, function() {
201
+ var extname = this;
202
+ $.getScript(curConfig.extPath + extname, function(d) {
203
+ // Fails locally in Chrome 5
204
+ if(!d) {
205
+ var s = document.createElement('script');
206
+ s.src = curConfig.extPath + extname;
207
+ document.querySelector('head').appendChild(s);
208
+ }
209
+ });
210
+ });
211
+ }
212
+
213
+ // Load extensions
214
+ // Bit of a hack to run extensions in local Opera/IE9
215
+ if(document.location.protocol === 'file:') {
216
+ setTimeout(extFunc, 100);
217
+ } else {
218
+ extFunc();
219
+ }
220
+ $.svgIcons(curConfig.imgPath + 'svg_edit_icons.svg', {
221
+ w:27, h:27,
222
+ id_match: false,
223
+ no_img: true, // Opera & Firefox 4 gives odd behavior w/images
224
+ fallback_path: curConfig.imgPath,
225
+ fallback:{
226
+ 'logo':'logo.png',
227
+ 'select':'select.png',
228
+ 'select_node':'select_node.png',
229
+ 'pencil':'pencil.png',
230
+ 'pen':'line.png',
231
+ 'rect':'square.png',
232
+ 'ellipse':'ellipse.png',
233
+ 'path':'path.png',
234
+ 'text':'text.png',
235
+ 'image':'image.png',
236
+ 'zoom':'zoom.png',
237
+ 'delete':'delete.png',
238
+ 'spapelib':'shapelib.png',
239
+ 'node_delete':'node_delete.png',
240
+ 'align_left':'align-left.png',
241
+ 'align_center':'align-center.png',
242
+ 'align_right':'align-right.png',
243
+ 'align_top':'align-top.png',
244
+ 'align_middle':'align-middle.png',
245
+ 'align_bottom':'align-bottom.png',
246
+ 'arrow_right':'flyouth.png',
247
+ 'arrow_down':'dropdown.gif'
248
+ },
249
+ placement: {
250
+ '#logo':'logo',
251
+ '#tool_select':'select',
252
+ '#tool_fhpath':'pencil',
253
+ '#tool_line':'pen',
254
+ '#tool_rect,#tools_rect_show':'rect',
255
+ '#tool_ellipse,#tools_ellipse_show':'ellipse',
256
+ '#tool_path':'path',
257
+ '#tool_text,#layer_rename':'text',
258
+ '#tool_image':'image',
259
+ '#tool_zoom':'zoom',
260
+ '#tool_node_clone':'node_clone',
261
+ '#tool_node_delete':'node_delete',
262
+ '#tool_add_subpath':'add_subpath',
263
+ '#tool_openclose_path':'open_path',
264
+ '#tool_alignleft, #tool_posleft':'align_left',
265
+ '#tool_aligncenter, #tool_poscenter':'align_center',
266
+ '#tool_alignright, #tool_posright':'align_right',
267
+ '#tool_aligntop, #tool_postop':'align_top',
268
+ '#tool_alignmiddle, #tool_posmiddle':'align_middle',
269
+ '#tool_alignbottom, #tool_posbottom':'align_bottom',
270
+ '#cur_position':'align',
271
+ '#zoomLabel':'zoom'
272
+ },
273
+ resize: {
274
+ '#logo .svg_icon': 15,
275
+ '.flyout_arrow_horiz .svg_icon': 5,
276
+ '#fill_bg .svg_icon, #stroke_bg .svg_icon': svgedit.browser.isTouch() ? 24 : 24,
277
+ '.palette_item:first .svg_icon': svgedit.browser.isTouch() ? 30 : 16,
278
+ '#zoomLabel .svg_icon': 16,
279
+ '#zoom_dropdown .svg_icon': 7
280
+ },
281
+ callback: function(icons) {
282
+ $('.toolbar_button button > svg, .toolbar_button button > img').each(function() {
283
+ $(this).parent().prepend(this);
284
+ });
285
+ $('.tool_button, .tool_button_current').addClass("loaded")
286
+ var tleft = $('#tools_left');
287
+ if (tleft.length != 0) {
288
+ var min_height = tleft.offset().top + tleft.outerHeight();
289
+ }
290
+
291
+ // Look for any missing flyout icons from plugins
292
+ $('.tools_flyout').each(function() {
293
+ var shower = $('#' + this.id + '_show');
294
+ var sel = shower.attr('data-curopt');
295
+ // Check if there's an icon here
296
+ if(!shower.children('svg, img').length) {
297
+ var clone = $(sel).children().clone();
298
+ if(clone.length) {
299
+ clone[0].removeAttribute('style'); //Needed for Opera
300
+ shower.append(clone);
301
+ }
302
+ }
303
+ });
304
+ methodDraw.runCallbacks();
305
+
306
+ setTimeout(function() {
307
+ $('.flyout_arrow_horiz:empty').each(function() {
308
+ $(this).append($.getSvgIcon('arrow_right').width(5).height(5));
309
+ });
310
+ }, 1);
311
+ }
312
+ });
313
+
314
+ $('#rulers').on("dblclick", function(e){
315
+ $("#base_unit_container").css({
316
+ top: e.pageY-10,
317
+ left: e.pageX-50,
318
+ display: 'block'
319
+ })
320
+ })
321
+ $("#base_unit_container")
322
+ .on("mouseleave mouseenter", function(e){
323
+ t = setTimeout(function(){$("#base_unit_container").fadeOut(500)}, 200)
324
+ if(event.type == "mouseover") clearTimeout(t)
325
+ })
326
+ $("#base_unit")
327
+ .on("change", function(e) {
328
+ savePreferences();
329
+ });
330
+
331
+ Editor.canvas = svgCanvas = new $.SvgCanvas(document.getElementById("svgcanvas"), curConfig);
332
+ Editor.show_save_warning = false;
333
+ Editor.paintBox = {fill: null, stroke:null, canvas:null};
334
+ var palette = ["#444444", "#482816", "#422C10", "#3B2F0E", "#32320F",
335
+ "#293414", "#1F361B", "#153723", "#0C372C",
336
+ "#083734", "#0E353B", "#1A333F", "#273141",
337
+ "#332D40", "#3E2A3C", "#462735", "#4B252D",
338
+ "#4D2425", "#4C261D", "#666666", "#845335", "#7B572D",
339
+ "#6F5C2A", "#62612C", "#546433", "#46673D",
340
+ "#396849", "#306856", "#2D6862", "#33666C",
341
+ "#426373", "#535F75", "#645A73", "#74556D",
342
+ "#805064", "#884D58", "#8B4D4B", "#894F3F",
343
+ "#999999", "#C48157", "#B8874D", "#A98E49", "#97944B",
344
+ "#849854", "#729C62", "#619E73", "#559E84",
345
+ "#529D94", "#5B9BA2", "#6D97AB", "#8391AE",
346
+ "#9A8AAB", "#AF84A3", "#BF7E96", "#C97A86",
347
+ "#CE7975", "#CC7C65", "#BBBBBB", "#FFB27C", "#FABA6F",
348
+ "#E6C36A", "#CFCA6D", "#B8D078", "#A0D58A",
349
+ "#8CD79F", "#7DD8B5", "#7AD6CA", "#84D3DB",
350
+ "#9ACEE6", "#B6C7EA", "#D3BEE7", "#EDB6DC",
351
+ "#FFAFCC", "#FFAAB8", "#FFA9A2", "#FFAC8D",
352
+ "#DDDDDD", "#FFE7A2", "#FFF093", "#FFFA8D", "#FFFF91",
353
+ "#EEFF9F", "#D1FFB4", "#B9FFCE", "#A8FFE9",
354
+ "#A4FFFF", "#B1FFFF", "#CBFFFF", "#EDFFFF",
355
+ "#FFF5FF", "#FFEBFF", "#FFE2FF", "#FFDCEC",
356
+ "#FFDBD2", "#FFDFB8"
357
+ ],
358
+ isMac = (navigator.platform.indexOf("Mac") >= 0),
359
+ isWebkit = (navigator.userAgent.indexOf("AppleWebKit") >= 0),
360
+ modKey = (isMac ? "meta+" : "ctrl+"), // ⌘
361
+ path = svgCanvas.pathActions,
362
+ undoMgr = svgCanvas.undoMgr,
363
+ Utils = svgedit.utilities,
364
+ default_img_url = curConfig.imgPath + "placeholder.svg",
365
+ workarea = $("#workarea"),
366
+ canv_menu = $("#cmenu_canvas"),
367
+ exportWindow = null,
368
+ tool_scale = 1,
369
+ ui_context = 'toolbars',
370
+ orig_source = '';
371
+
372
+
373
+ // This puts the correct shortcuts in the menus
374
+ if (!isMac) {
375
+ $('.shortcut').each(function(){
376
+ var text = $(this).text();
377
+ $(this).text(text.split("⌘").join("Ctrl+"))
378
+ });
379
+ }
380
+
381
+ // This sets up alternative dialog boxes. They mostly work the same way as
382
+ // their UI counterparts, expect instead of returning the result, a callback
383
+ // needs to be included that returns the result as its first parameter.
384
+ // In the future we may want to add additional types of dialog boxes, since
385
+ // they should be easy to handle this way.
386
+ (function() {
387
+ $('#dialog_container').draggable({cancel:'#dialog_content, #dialog_buttons *', containment: 'window'});
388
+ var box = $('#dialog_box'), btn_holder = $('#dialog_buttons');
389
+
390
+ var dbox = function(type, msg, callback, defText) {
391
+ $('#dialog_content').html('<p>'+msg.replace(/\n/g,'</p><p>')+'</p>')
392
+ .toggleClass('prompt',(type=='prompt'));
393
+ btn_holder.empty();
394
+
395
+ var ok = $('<input type="button" value="' + uiStrings.common.ok + '">').appendTo(btn_holder);
396
+
397
+ if(type != 'alert') {
398
+ $('<input type="button" value="' + uiStrings.common.cancel + '">')
399
+ .appendTo(btn_holder)
400
+ .on("click touchstart", function() { box.hide();callback(false)});
401
+ }
402
+
403
+ if(type == 'prompt') {
404
+ var input = $('<input type="text">').prependTo(btn_holder);
405
+ input.val(defText || '');
406
+ input.bind('keydown', 'return', function() {ok.trigger("click touchstart");});
407
+ }
408
+
409
+ if(type == 'process') {
410
+ ok.hide();
411
+ }
412
+
413
+ box.show();
414
+
415
+ ok.on("click touchstart", function() {
416
+ box.hide();
417
+ var resp = (type == 'prompt')?input.val():true;
418
+ if(callback) callback(resp);
419
+ }).focus();
420
+
421
+ if(type == 'prompt') input.focus();
422
+ }
423
+
424
+ $.alert = function(msg, cb) { dbox('alert', msg, cb);};
425
+ $.confirm = function(msg, cb) { dbox('confirm', msg, cb);};
426
+ $.process_cancel = function(msg, cb) { dbox('process', msg, cb);};
427
+ $.prompt = function(msg, txt, cb) { dbox('prompt', msg, cb, txt);};
428
+ }());
429
+
430
+ var setSelectMode = function() {
431
+ var curr = $('.tool_button_current');
432
+ if(curr.length && curr[0].id !== 'tool_select') {
433
+ curr.removeClass('tool_button_current').addClass('tool_button');
434
+ $('#tool_select').addClass('tool_button_current').removeClass('tool_button');
435
+ }
436
+ svgCanvas.setMode('select');
437
+ };
438
+
439
+ var setEyedropperMode = function() {
440
+ var curr = $('.tool_button_current');
441
+ if(curr.length && curr[0].id !== 'tool_eyedropper') {
442
+ curr.removeClass('tool_button_current').addClass('tool_button');
443
+ $('#tool_eyedropper').addClass('tool_button_current').removeClass('tool_button');
444
+ }
445
+ svgCanvas.setMode('eyedropper');
446
+ }
447
+
448
+ var togglePathEditMode = function(editmode, elems) {
449
+ $('#tools_bottom_2,#tools_bottom_3').toggle(!editmode);
450
+ if(editmode) {
451
+ // Change select icon
452
+ $('.context_panel').hide();
453
+ $('#path_node_panel').show();
454
+ $('.tool_button_current').removeClass('tool_button_current').addClass('tool_button');
455
+ $('#tool_select').addClass('tool_button_current').removeClass('tool_button');
456
+ setIcon('#tool_select', 'select_node');
457
+ multiselected = false;
458
+ } else {
459
+ if (elems[0]) {
460
+ var selector = svgCanvas.selectorManager.requestSelector(elems[0])
461
+ selector.reset(elems[0]);
462
+ selector.selectorRect.setAttribute('display', 'inline');
463
+ }
464
+
465
+ setIcon('#tool_select', 'select');
466
+ }
467
+ }
468
+
469
+ // used to make the flyouts stay on the screen longer the very first time
470
+ var flyoutspeed = 1250;
471
+ var textBeingEntered = false;
472
+ var selectedElement = null;
473
+ var multiselected = false;
474
+ var editingsource = false;
475
+ var docprops = false;
476
+ var preferences = false;
477
+ var cur_context = '';
478
+
479
+ var saveHandler = function(window,svg) {
480
+ Editor.show_save_warning = false;
481
+
482
+ // by default, we add the XML prolog back, systems integrating SVG-edit (wikis, CMSs)
483
+ // can just provide their own custom save handler and might not want the XML prolog
484
+ svg = '<?xml version="1.0"?>\n' + svg;
485
+
486
+ // Opens the SVG in new window, with warning about Mozilla bug #308590 when applicable
487
+
488
+ var ua = navigator.userAgent;
489
+
490
+ // Chrome 5 (and 6?) don't allow saving, show source instead ( http://code.google.com/p/chromium/issues/detail?id=46735 )
491
+ // IE9 doesn't allow standalone Data URLs ( https://connect.microsoft.com/IE/feedback/details/542600/data-uri-images-fail-when-loaded-by-themselves )
492
+ if(~ua.indexOf('MSIE')) {
493
+ showSourceEditor(0,true);
494
+ return;
495
+ }
496
+ var win = window.open("data:image/svg+xml;base64," + Utils.encode64(svg));
497
+
498
+ // Alert will only appear the first time saved OR the first time the bug is encountered
499
+ var done = $.pref('save_notice_done');
500
+ if(done !== "all") {
501
+
502
+ var note = uiStrings.notification.saveFromBrowser.replace('%s', 'SVG');
503
+
504
+ // Check if FF and has <defs/>
505
+ if(ua.indexOf('Gecko/') !== -1) {
506
+ if(svg.indexOf('<defs') !== -1) {
507
+ note += "\n\n" + uiStrings.notification.defsFailOnSave;
508
+ $.pref('save_notice_done', 'all');
509
+ done = "all";
510
+ } else {
511
+ $.pref('save_notice_done', 'part');
512
+ }
513
+ } else {
514
+ $.pref('save_notice_done', 'all');
515
+ }
516
+
517
+ if(done !== 'part') {
518
+ win.alert(note);
519
+ }
520
+ }
521
+ };
522
+
523
+ var exportHandler = function(window, data) {
524
+ var issues = data.issues;
525
+
526
+ if(!$('#export_canvas').length) {
527
+ $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
528
+ }
529
+ var c = $('#export_canvas')[0];
530
+
531
+ c.width = svgCanvas.contentW;
532
+ c.height = svgCanvas.contentH;
533
+ canvg(c, data.svg, {renderCallback: function() {
534
+ var datauri = c.toDataURL('image/png');
535
+ exportWindow.location.href = datauri;
536
+ var done = $.pref('export_notice_done');
537
+ if(done !== "all") {
538
+ var note = uiStrings.notification.saveFromBrowser.replace('%s', 'PNG');
539
+
540
+ // Check if there's issues
541
+ if(issues.length) {
542
+ var pre = "\n \u2022 ";
543
+ note += ("\n\n" + uiStrings.notification.noteTheseIssues + pre + issues.join(pre));
544
+ }
545
+
546
+ // Note that this will also prevent the notice even though new issues may appear later.
547
+ // May want to find a way to deal with that without annoying the user
548
+ $.pref('export_notice_done', 'all');
549
+ exportWindow.alert(note);
550
+ }
551
+ }});
552
+ };
553
+
554
+ // called when we've selected a different element
555
+ var selectedChanged = function(window,elems) {
556
+ var mode = svgCanvas.getMode();
557
+ if(mode === "select") setSelectMode();
558
+ if (mode === "pathedit") return updateContextPanel();
559
+ // if elems[1] is present, then we have more than one element
560
+ selectedElement = (elems.length == 1 || elems[1] == null ? elems[0] : null);
561
+ elems = elems.filter(Boolean)
562
+ multiselected = (elems.length >= 2) ? elems : false;
563
+ if (svgCanvas.elementsAreSame(multiselected)) selectedElement = multiselected[0]
564
+ if (selectedElement != null) {
565
+ $('#multiselected_panel').hide()
566
+ updateToolbar();
567
+ if (multiselected.length) {//multiselected elements are the same
568
+ $('#tools_top').addClass('multiselected')
569
+ }
570
+ }
571
+ else if (multiselected.length) {
572
+ $('.context_panel').hide()
573
+ $('#tools_top').removeClass('multiselected')
574
+ $('#multiselected_panel').show()
575
+ }
576
+ else {
577
+ $('.context_panel').hide()
578
+ $('#canvas_panel').show()
579
+ $('#tools_top').removeClass('multiselected')
580
+ }
581
+ svgCanvas.runExtensions("selectedChanged", {
582
+ elems: elems,
583
+ selectedElement: selectedElement,
584
+ multiselected: multiselected
585
+ });
586
+ };
587
+
588
+ // Call when part of element is in process of changing, generally
589
+ // on mousemove actions like rotate, move, etc.
590
+ var elementTransition = function(window,elems) {
591
+ var mode = svgCanvas.getMode();
592
+ var elem = elems[0];
593
+
594
+ if(!elem) return;
595
+
596
+ multiselected = (elems.length >= 2 && elems[1] != null) ? elems : null;
597
+ // Only updating fields for single elements for now
598
+ if(!multiselected) {
599
+ switch ( mode ) {
600
+ case "rotate":
601
+ var ang = svgCanvas.getRotationAngle(elem);
602
+ $('#angle').val(Math.round(ang));
603
+ rotateCursor(ang);
604
+ $('#tool_reorient').toggleClass('disabled', ang == 0);
605
+ break;
606
+
607
+ // TODO: Update values that change on move/resize, etc
608
+ // case "select":
609
+ // case "resize":
610
+ // break;
611
+ }
612
+ }
613
+ svgCanvas.runExtensions("elementTransition", {
614
+ elems: elems
615
+ });
616
+ };
617
+
618
+ // called when any element has changed
619
+ var elementChanged = function(window,elems) {
620
+ var mode = svgCanvas.getMode();
621
+ if(mode === "select") {
622
+ setSelectMode();
623
+ }
624
+
625
+ for (var i = 0; i < elems.length; ++i) {
626
+ var elem = elems[i];
627
+
628
+ // if the element changed was the svg, then it could be a resolution change
629
+ if (elem && elem.tagName === "svg") {
630
+ //populateLayers();
631
+ updateCanvas();
632
+ }
633
+ // Update selectedElement if element is no longer part of the image.
634
+ // This occurs for the text elements in Firefox
635
+ else if(elem && selectedElement && selectedElement.parentNode == null) {
636
+ // || elem && elem.tagName == "path" && !multiselected) { // This was added in r1430, but not sure why
637
+ selectedElement = elem;
638
+ }
639
+ }
640
+
641
+ Editor.show_save_warning = true;
642
+
643
+ // we update the contextual panel with potentially new
644
+ // positional/sizing information (we DON'T want to update the
645
+ // toolbar here as that creates an infinite loop)
646
+ // also this updates the history buttons
647
+
648
+ // we tell it to skip focusing the text control if the
649
+ // text element was previously in focus
650
+ updateContextPanel();
651
+
652
+ // In the event a gradient was flipped:
653
+ if(selectedElement && mode === "select") {
654
+ Editor.paintBox.fill.update();
655
+ Editor.paintBox.stroke.update();
656
+ }
657
+
658
+ svgCanvas.runExtensions("elementChanged", {
659
+ elems: elems
660
+ });
661
+ };
662
+
663
+ var zoomChanged = function(window, bbox, autoCenter) {
664
+ var scrbar = 15,
665
+ res = svgCanvas.getResolution(),
666
+ w_area = workarea,
667
+ canvas_pos = $('#svgcanvas').position();
668
+ var z_info = svgCanvas.setBBoxZoom(bbox, w_area.width()-scrbar, w_area.height()-scrbar);
669
+ if(!z_info) return;
670
+ var zoomlevel = z_info.zoom,
671
+ bb = z_info.bbox;
672
+
673
+ if(zoomlevel < .001) {
674
+ changeZoom({value: .1});
675
+ return;
676
+ }
677
+ if (typeof animatedZoom != 'undefined') window.cancelAnimationFrame(animatedZoom)
678
+ // zoom duration 500ms
679
+ var start = Date.now();
680
+ var duration = 500;
681
+ var diff = (zoomlevel) - (res.zoom)
682
+ var zoom = $('#zoom')[0]
683
+ var current_zoom = res.zoom
684
+ var animateZoom = function(timestamp) {
685
+ var progress = Date.now() - start
686
+ var tick = progress / duration
687
+ tick = (Math.pow((tick-1), 3) +1);
688
+ svgCanvas.setZoom(current_zoom + (diff*tick));
689
+ updateCanvas();
690
+ if (tick < 1 && tick > -.90) {
691
+ window.animatedZoom = requestAnimationFrame(animateZoom)
692
+ }
693
+ else {
694
+ $("#zoom").val(parseInt(zoomlevel*100))
695
+ $("option", "#zoom_select").removeAttr("selected")
696
+ $("option[value="+ parseInt(zoomlevel*100) +"]", "#zoom_select").attr("selected", "selected")
697
+ }
698
+ }
699
+ animateZoom()
700
+
701
+
702
+
703
+ //if(autoCenter) {
704
+ // updateCanvas();
705
+ //} else {
706
+ // updateCanvas(false, {x: bb.x * zoomlevel + (bb.width * zoomlevel)/2, y: bb.y * zoomlevel + (bb.height * zoomlevel)/2});
707
+ //}
708
+
709
+ if(svgCanvas.getMode() == 'zoom' && bb.width) {
710
+ // Go to select if a zoom box was drawn
711
+ setSelectMode();
712
+ }
713
+
714
+ zoomDone();
715
+ }
716
+
717
+ $('#cur_context_panel').delegate('a', 'click', function() {
718
+ var link = $(this);
719
+ if(link.attr('data-root')) {
720
+ svgCanvas.leaveContext();
721
+ } else {
722
+ svgCanvas.setContext(link.text());
723
+ }
724
+ svgCanvas.clearSelection();
725
+ return false;
726
+ });
727
+
728
+ var contextChanged = function(win, context) {
729
+
730
+ var link_str = '';
731
+ if(context) {
732
+ var str = '';
733
+ link_str = '<a href="#" data-root="y">' + svgCanvas.getCurrentDrawing().getCurrentLayerName() + '</a>';
734
+
735
+ $(context).parentsUntil('#svgcontent > g').andSelf().each(function() {
736
+ if(this.id) {
737
+ str += ' > ' + this.id;
738
+ if(this !== context) {
739
+ link_str += ' > <a href="#">' + this.id + '</a>';
740
+ } else {
741
+ link_str += ' > ' + this.id;
742
+ }
743
+ }
744
+ });
745
+
746
+ cur_context = str;
747
+ } else {
748
+ cur_context = null;
749
+ }
750
+ $('#cur_context_panel').toggle(!!context).html(link_str);
751
+
752
+ }
753
+
754
+ // Makes sure the current selected paint is available to work with
755
+ var prepPaints = function() {
756
+ Editor.paintBox.fill.prep();
757
+ Editor.paintBox.stroke.prep();
758
+ }
759
+
760
+ var flyout_funcs = {};
761
+
762
+ var setupFlyouts = function(holders) {
763
+ $.each(holders, function(hold_sel, btn_opts) {
764
+ var buttons = $(hold_sel).children();
765
+ var show_sel = hold_sel + '_show';
766
+ var shower = $(show_sel);
767
+ var def = false;
768
+ buttons.addClass('tool_button')
769
+ .unbind('click mousedown mouseup') // may not be necessary
770
+ .each(function(i) {
771
+ // Get this buttons options
772
+ var opts = btn_opts[i];
773
+
774
+ // Remember the function that goes with this ID
775
+ flyout_funcs[opts.sel] = opts.fn;
776
+
777
+ if(opts.isDefault) def = i;
778
+
779
+ // Clicking the icon in flyout should set this set's icon
780
+ var func = function(event) {
781
+ var options = opts;
782
+ //find the currently selected tool if comes from keystroke
783
+ if (event.type === "keydown") {
784
+ var flyoutIsSelected = $(options.parent + "_show").hasClass('tool_button_current');
785
+ var currentOperation = $(options.parent + "_show").attr("data-curopt");
786
+ $.each(holders[opts.parent], function(i, tool){
787
+ if (tool.sel == currentOperation) {
788
+ if(!event.shiftKey || !flyoutIsSelected) {
789
+ options = tool;
790
+ }
791
+ else {
792
+ options = holders[opts.parent][i+1] || holders[opts.parent][0];
793
+ }
794
+ }
795
+ });
796
+ }
797
+ if($(this).hasClass('disabled')) return false;
798
+ if (toolButtonClick(show_sel)) {
799
+ options.fn();
800
+ }
801
+ if(options.icon) {
802
+ var icon = $.getSvgIcon(options.icon, true);
803
+ } else {
804
+ var icon = $(options.sel).children().eq(0).clone();
805
+ }
806
+
807
+ icon[0].setAttribute('width',shower.width());
808
+ icon[0].setAttribute('height',shower.height());
809
+ shower.children(':not(.flyout_arrow_horiz)').remove();
810
+ shower.append(icon).attr('data-curopt', options.sel); // This sets the current mode
811
+ }
812
+
813
+ $(this).mouseup(func);
814
+
815
+ if(opts.key) {
816
+ $(document).bind('keydown', opts.key[0] + " shift+" + opts.key[0], func);
817
+ }
818
+ });
819
+
820
+ if(def) {
821
+ shower.attr('data-curopt', btn_opts[def].sel);
822
+ } else if(!shower.attr('data-curopt')) {
823
+ // Set first as default
824
+ shower.attr('data-curopt', btn_opts[0].sel);
825
+ }
826
+
827
+ var timer;
828
+
829
+ var pos = $(show_sel).position();
830
+ $(hold_sel).css({'left': pos.left+34, 'top': pos.top+77});
831
+
832
+ // Clicking the "show" icon should set the current mode
833
+ shower.mousedown(function(evt) {
834
+ $('#workarea').one("mousedown", function(){$('#tools_shapelib').hide()})
835
+ if ($('#tools_shapelib').is(":visible")) toolButtonClick(show_sel, false);
836
+ if(shower.hasClass('disabled')) return false;
837
+ var holder = $(hold_sel);
838
+ var l = pos.left+34;
839
+ var w = holder.width()*-1;
840
+ var time = holder.data('shown_popop')?200:0;
841
+ timer = setTimeout(function() {
842
+ // Show corresponding menu
843
+ if(!shower.data('isLibrary')) {
844
+ holder.css('left', w).show().animate({
845
+ left: l
846
+ },50);
847
+ } else {
848
+ holder.css('left', l).show();
849
+ }
850
+ holder.data('shown_popop',true);
851
+ },time);
852
+ evt.preventDefault();
853
+ }).mouseup(function(evt) {
854
+ clearTimeout(timer);
855
+ var opt = $(this).attr('data-curopt');
856
+ // Is library and popped up, so do nothing
857
+ if(shower.data('isLibrary') && $(show_sel.replace('_show','')).is(':visible')) {
858
+ toolButtonClick(show_sel, true);
859
+ return;
860
+ }
861
+ if (toolButtonClick(show_sel) && (opt in flyout_funcs)) {
862
+ flyout_funcs[opt]();
863
+ }
864
+ });
865
+
866
+ // $('#tools_rect').mouseleave(function(){$('#tools_rect').fadeOut();});
867
+ });
868
+
869
+ setFlyoutTitles();
870
+ }
871
+
872
+ var makeFlyoutHolder = function(id, child) {
873
+ var div = $('<div>',{
874
+ 'class': 'tools_flyout',
875
+ id: id
876
+ }).appendTo('#svg_editor').append(child);
877
+
878
+ return div;
879
+ }
880
+
881
+ var setFlyoutPositions = function() {
882
+ $('.tools_flyout').each(function() {
883
+ var shower = $('#' + this.id + '_show');
884
+ var pos = shower.offset();
885
+ var w = shower.outerWidth();
886
+ $(this).css({left: (pos.left + w)*tool_scale, top: pos.top});
887
+ });
888
+ }
889
+
890
+ var setFlyoutTitles = function() {
891
+ $('.tools_flyout').each(function() {
892
+ var shower = $('#' + this.id + '_show');
893
+ if(shower.data('isLibrary')) return;
894
+
895
+ var tooltips = [];
896
+ $(this).children().each(function() {
897
+ tooltips.push(this.title);
898
+ });
899
+ shower[0].title = tooltips.join(' / ');
900
+ });
901
+ }
902
+
903
+ var resize_timer;
904
+
905
+ var extAdded = function(window, ext) {
906
+
907
+ var cb_called = false;
908
+ var resize_done = false;
909
+ var cb_ready = true; // Set to false to delay callback (e.g. wait for $.svgIcons)
910
+
911
+ function prepResize() {
912
+ if(resize_timer) {
913
+ clearTimeout(resize_timer);
914
+ resize_timer = null;
915
+ }
916
+ if(!resize_done) {
917
+ resize_timer = setTimeout(function() {
918
+ resize_done = true;
919
+ setIconSize(curPrefs.iconsize);
920
+ }, 50);
921
+ }
922
+ }
923
+
924
+
925
+ var runCallback = function() {
926
+ if(ext.callback && !cb_called && cb_ready) {
927
+ cb_called = true;
928
+ ext.callback();
929
+ }
930
+ }
931
+
932
+ var btn_selects = [];
933
+
934
+ if(ext.context_tools) {
935
+ $.each(ext.context_tools, function(i, tool) {
936
+ // Add select tool
937
+ var cont_id = tool.container_id?(' id="' + tool.container_id + '"'):"";
938
+
939
+ var panel = $('#' + tool.panel);
940
+
941
+ // create the panel if it doesn't exist
942
+ if(!panel.length)
943
+ panel = $('<div>', {id: tool.panel}).appendTo("#tools_top").hide();
944
+
945
+ // TODO: Allow support for other types, or adding to existing tool
946
+ switch (tool.type) {
947
+ case 'tool_button':
948
+ var html = '<div class="tool_button">' + tool.id + '</div>';
949
+ var div = $(html).appendTo(panel);
950
+ if (tool.events) {
951
+ $.each(tool.events, function(evt, func) {
952
+ $(div).bind(evt, func);
953
+ });
954
+ }
955
+ break;
956
+ case 'select':
957
+ var html = '<label' + cont_id + '>'
958
+ + '<select id="' + tool.id + '">';
959
+ $.each(tool.options, function(val, text) {
960
+ var sel = (val == tool.defval) ? " selected":"";
961
+ html += '<option value="'+val+'"' + sel + '>' + text + '</option>';
962
+ });
963
+ html += "</select></label>";
964
+ // Creates the tool, hides & adds it, returns the select element
965
+ var sel = $(html).appendTo(panel).find('select');
966
+
967
+ $.each(tool.events, function(evt, func) {
968
+ $(sel).bind(evt, func);
969
+ });
970
+ break;
971
+ case 'button-select':
972
+ var html = '<div id="' + tool.id + '" class="dropdown toolset" title="' + tool.title + '">'
973
+ + '<div id="cur_' + tool.id + '" class="icon_label"></div><button></button></div>';
974
+
975
+ var list = $('<ul id="' + tool.id + '_opts"></ul>').appendTo('#option_lists');
976
+ if(tool.colnum) {
977
+ list.addClass('optcols' + tool.colnum);
978
+ }
979
+
980
+ // Creates the tool, hides & adds it, returns the select element
981
+ var dropdown = $(html).appendTo(panel).children();
982
+
983
+ btn_selects.push({
984
+ elem: ('#' + tool.id),
985
+ list: ('#' + tool.id + '_opts'),
986
+ title: tool.title,
987
+ callback: tool.events.change,
988
+ cur: ('#cur_' + tool.id)
989
+ });
990
+
991
+ break;
992
+ case 'input':
993
+ var html = '<label' + cont_id + '>'
994
+ + '<span id="' + tool.id + '_label">'
995
+ + tool.label + ':</span>'
996
+ + '<input id="' + tool.id + '" title="' + tool.title
997
+ + '" size="' + (tool.size || "4") + '" value="' + (tool.defval || "") + '" type="text"/></label>'
998
+
999
+ // Creates the tool, hides & adds it, returns the select element
1000
+
1001
+ // Add to given tool.panel
1002
+ var inp = $(html).appendTo(panel).find('input');
1003
+
1004
+ if(tool.spindata) {
1005
+ inp.SpinButton(tool.spindata);
1006
+ }
1007
+
1008
+ if(tool.events) {
1009
+ $.each(tool.events, function(evt, func) {
1010
+ inp.bind(evt, func);
1011
+ });
1012
+ }
1013
+ break;
1014
+
1015
+ default:
1016
+ break;
1017
+ }
1018
+ });
1019
+ }
1020
+
1021
+ if(ext.buttons) {
1022
+ var fallback_obj = {},
1023
+ placement_obj = {},
1024
+ svgicons = ext.svgicons;
1025
+ var holders = {};
1026
+
1027
+
1028
+ // Add buttons given by extension
1029
+ $.each(ext.buttons, function(i, btn) {
1030
+ var icon;
1031
+ var id = btn.id;
1032
+ var num = i;
1033
+ // Give button a unique ID
1034
+ while($('#'+id).length) {
1035
+ id = btn.id + '_' + (++num);
1036
+ }
1037
+ if(!svgicons) {
1038
+ icon = (btn.type == "menu") ? "" : $('<img src="' + btn.icon + '">');
1039
+ } else {
1040
+ fallback_obj[id] = btn.icon;
1041
+ var svgicon = btn.svgicon ? btn.svgicon : btn.id;
1042
+ if(btn.type == 'app_menu') {
1043
+ placement_obj['#' + id + ' > div'] = svgicon;
1044
+ } else {
1045
+ placement_obj['#' + id] = svgicon;
1046
+ }
1047
+ }
1048
+
1049
+ var cls, parent;
1050
+
1051
+
1052
+
1053
+ // Set button up according to its type
1054
+ switch ( btn.type ) {
1055
+ case 'mode_flyout':
1056
+ case 'mode':
1057
+ cls = 'tool_button';
1058
+ if(btn.cls) {
1059
+ cls += " " + btn.cls;
1060
+ }
1061
+ parent = "#tools_left";
1062
+ break;
1063
+ case 'context':
1064
+ cls = 'tool_button';
1065
+ parent = "#" + btn.panel;
1066
+ // create the panel if it doesn't exist
1067
+ if(!$(parent).length)
1068
+ $('<div>', {id: btn.panel}).appendTo("#tools_top");
1069
+ break;
1070
+ case 'menu':
1071
+ cls = 'menu_item tool_button';
1072
+ parent = "#" + (btn.after || btn.panel);
1073
+ break;
1074
+ case 'app_menu':
1075
+ cls = '';
1076
+ parent = btn.parent || '#main_menu ul';
1077
+ // create the panel if it doesn't exist
1078
+ if(!$(parent).length)
1079
+ $('<div>', {id: btn.panel}).appendTo("#tools_top");
1080
+ break;
1081
+ }
1082
+
1083
+ var button = $((btn.list || btn.type == 'app_menu')?'<li/>':'<div/>')
1084
+ .attr("id", id)
1085
+ .attr("title", btn.title)
1086
+ .addClass(cls);
1087
+ if(!btn.includeWith && !btn.list) {
1088
+ if("position" in btn) {
1089
+ $(parent).children().eq(btn.position).before(button);
1090
+ } else {
1091
+ if (btn.type != "menu" || !btn.after) button.appendTo(parent);
1092
+ else $(parent).after(button);
1093
+ }
1094
+
1095
+ if(btn.type =='mode_flyout') {
1096
+ // Add to flyout menu / make flyout menu
1097
+ // var opts = btn.includeWith;
1098
+ // // opts.button, default, position
1099
+ var ref_btn = $(button);
1100
+
1101
+ var flyout_holder = ref_btn.parent();
1102
+ // Create a flyout menu if there isn't one already
1103
+ if(!ref_btn.parent().hasClass('tools_flyout')) {
1104
+ // Create flyout placeholder
1105
+ var tls_id = ref_btn[0].id.replace('tool_','tools_')
1106
+ var show_btn = ref_btn.clone()
1107
+ .attr('id',tls_id + '_show')
1108
+ .append($('<div>',{'class':'flyout_arrow_horiz'}));
1109
+
1110
+ ref_btn.before(show_btn);
1111
+
1112
+ // Create a flyout div
1113
+ flyout_holder = makeFlyoutHolder(tls_id, ref_btn);
1114
+ flyout_holder.data('isLibrary', true);
1115
+ show_btn.data('isLibrary', true);
1116
+ }
1117
+
1118
+
1119
+
1120
+ // var ref_data = Actions.getButtonData(opts.button);
1121
+
1122
+ placement_obj['#' + tls_id + '_show'] = btn.id;
1123
+ // TODO: Find way to set the current icon using the iconloader if this is not default
1124
+
1125
+ // Include data for extension button as well as ref button
1126
+ var cur_h = holders['#'+flyout_holder[0].id] = [{
1127
+ sel: '#'+id,
1128
+ fn: btn.events.click,
1129
+ icon: btn.id,
1130
+ //key: btn.key,
1131
+ isDefault: true
1132
+ }, ref_data];
1133
+
1134
+ } else if(btn.type == 'app_menu' || btn.type == 'menu') {
1135
+ button.append(btn.title);
1136
+ }
1137
+
1138
+ } else if(btn.list) {
1139
+ // Add button to list
1140
+ button.addClass('push_button');
1141
+ $('#' + btn.list + '_opts').append(button);
1142
+ if(btn.isDefault) {
1143
+ $('#cur_' + btn.list).append(button.children().clone());
1144
+ var svgicon = btn.svgicon?btn.svgicon:btn.id;
1145
+ placement_obj['#cur_' + btn.list] = svgicon;
1146
+ }
1147
+ } else if(btn.includeWith) {
1148
+ // Add to flyout menu / make flyout menu
1149
+ var opts = btn.includeWith;
1150
+ // opts.button, default, position
1151
+ var ref_btn = $(opts.button);
1152
+
1153
+ var flyout_holder = ref_btn.parent();
1154
+ // Create a flyout menu if there isn't one already
1155
+ if(!ref_btn.parent().hasClass('tools_flyout')) {
1156
+ // Create flyout placeholder
1157
+ var tls_id = ref_btn[0].id.replace('tool_','tools_')
1158
+ var show_btn = ref_btn.clone()
1159
+ .attr('id',tls_id + '_show')
1160
+ .append($('<div>',{'class':'flyout_arrow_horiz'}));
1161
+
1162
+ ref_btn.before(show_btn);
1163
+
1164
+ // Create a flyout div
1165
+ flyout_holder = makeFlyoutHolder(tls_id, ref_btn);
1166
+ }
1167
+
1168
+ var ref_data = Actions.getButtonData(opts.button);
1169
+
1170
+ if(opts.isDefault) {
1171
+ placement_obj['#' + tls_id + '_show'] = btn.id;
1172
+ }
1173
+ // TODO: Find way to set the current icon using the iconloader if this is not default
1174
+
1175
+ // Include data for extension button as well as ref button
1176
+ var cur_h = holders['#'+flyout_holder[0].id] = [{
1177
+ sel: '#'+id,
1178
+ fn: btn.events.click,
1179
+ icon: btn.id,
1180
+ key: btn.key,
1181
+ isDefault: btn.includeWith?btn.includeWith.isDefault:0
1182
+ }, ref_data];
1183
+
1184
+ // {sel:'#tool_rect', fn: clickRect, evt: 'mouseup', key: 4, parent: '#tools_rect', icon: 'rect'}
1185
+
1186
+ var pos = ("position" in opts)?opts.position:'last';
1187
+ var len = flyout_holder.children().length;
1188
+
1189
+ // Add at given position or end
1190
+ if(!isNaN(pos) && pos >= 0 && pos < len) {
1191
+ flyout_holder.children().eq(pos).before(button);
1192
+ } else {
1193
+ flyout_holder.append(button);
1194
+ cur_h.reverse();
1195
+ }
1196
+ }
1197
+
1198
+ if(!svgicons) {
1199
+ button.append(icon);
1200
+ }
1201
+
1202
+ if(!btn.list) {
1203
+ // Add given events to button
1204
+ $.each(btn.events, function(name, func) {
1205
+ if(name == "click") {
1206
+ if(btn.type == 'mode') {
1207
+ if(btn.includeWith) {
1208
+ button.bind(name, func);
1209
+ } else {
1210
+ button.bind(name, function() {
1211
+ if(toolButtonClick(button)) {
1212
+ func();
1213
+ }
1214
+ });
1215
+ }
1216
+ if(btn.key) {
1217
+ $(document).bind('keydown', btn.key, func);
1218
+ if(btn.title) button.attr("title", btn.title + ' ['+btn.key+']');
1219
+ }
1220
+ } else {
1221
+ button.bind(name, func);
1222
+ }
1223
+ } else {
1224
+ button.bind(name, func);
1225
+ }
1226
+ });
1227
+ }
1228
+ setupFlyouts(holders);
1229
+ });
1230
+
1231
+ $.each(btn_selects, function() {
1232
+ addAltDropDown(this.elem, this.list, this.callback, {seticon: true});
1233
+ });
1234
+
1235
+ if (svgicons)
1236
+ cb_ready = false; // Delay callback
1237
+
1238
+ $.svgIcons(svgicons, {
1239
+ w:27, h:27,
1240
+ id_match: false,
1241
+ no_img: (!isWebkit),
1242
+ fallback: fallback_obj,
1243
+ placement: placement_obj,
1244
+ callback: function(icons) {
1245
+ // Non-ideal hack to make the icon match the current size
1246
+ if(curPrefs.iconsize && curPrefs.iconsize != 'm') {
1247
+ prepResize();
1248
+ }
1249
+ cb_ready = true; // Ready for callback
1250
+ runCallback();
1251
+ }
1252
+
1253
+ });
1254
+ }
1255
+
1256
+ runCallback();
1257
+ };
1258
+
1259
+ var getPaint = function(color, opac, type) {
1260
+ // update the editor's fill paint
1261
+ var opts = null;
1262
+ if (color.indexOf("url(#") === 0) {
1263
+ var refElem = svgCanvas.getRefElem(color);
1264
+ if(refElem) {
1265
+ refElem = refElem.cloneNode(true);
1266
+ } else {
1267
+ refElem = $("#" + type + "_color defs *")[0];
1268
+ }
1269
+
1270
+ opts = { alpha: opac };
1271
+ opts[refElem.tagName] = refElem;
1272
+ }
1273
+ else if (color.indexOf("#") === 0) {
1274
+ opts = {
1275
+ alpha: opac,
1276
+ solidColor: color.substr(1)
1277
+ };
1278
+ }
1279
+ else {
1280
+ opts = {
1281
+ alpha: opac,
1282
+ solidColor: 'none'
1283
+ };
1284
+ }
1285
+ return new $.jGraduate.Paint(opts);
1286
+ };
1287
+
1288
+ // set the canvas properties at init
1289
+ var res = svgCanvas.getResolution();
1290
+ if(curConfig.baseUnit !== "px") {
1291
+ res.w = svgedit.units.convertUnit(res.w) + curConfig.baseUnit;
1292
+ res.h = svgedit.units.convertUnit(res.h) + curConfig.baseUnit;
1293
+ }
1294
+
1295
+ var createBackground = function(fill) {
1296
+ svgCanvas.createLayer("background")
1297
+ cur_shape = svgCanvas.addSvgElementFromJson({
1298
+ "element": "rect",
1299
+ "attr": {
1300
+ "x": -1,
1301
+ "y": -1,
1302
+ "width": res.w+2,
1303
+ "height": res.h+2,
1304
+ "stroke": "none",
1305
+ "id": "canvas_background",
1306
+ "opacity": 1,
1307
+ "fill": fill || "#fff",
1308
+ "style": "pointer-events:none"
1309
+ }
1310
+ });
1311
+ svgCanvas.setCurrentLayer("Layer 1")
1312
+ svgCanvas.setCurrentLayerPosition("1")
1313
+ }
1314
+
1315
+ // create a new layer background if it doesn't exist
1316
+ if (!document.getElementById('canvas_background')) createBackground();
1317
+ var fill = document.getElementById('canvas_background').getAttribute("fill");
1318
+
1319
+ // updates the toolbar (colors, opacity, etc) based on the selected element
1320
+ // This function also updates the opacity and id elements that are in the context panel
1321
+ var updateToolbar = function() {
1322
+ if (selectedElement != null) {
1323
+ switch ( selectedElement.tagName ) {
1324
+ case 'use':
1325
+ $(".context_panel").hide();
1326
+ $("#use_panel").show();
1327
+ break;
1328
+ case 'image':
1329
+ $(".context_panel").hide();
1330
+ $("#image_panel").show();
1331
+ break;
1332
+ case 'foreignObject':
1333
+ $(".context_panel").hide();
1334
+ break;
1335
+ case 'g':
1336
+ case 'a':
1337
+ // Look for common styles
1338
+ var gWidth = null;
1339
+
1340
+ var childs = selectedElement.getElementsByTagName('*');
1341
+ for(var i = 0, len = childs.length; i < len; i++) {
1342
+ var swidth = childs[i].getAttribute("stroke-width");
1343
+ if(i === 0) {
1344
+ gWidth = swidth;
1345
+ } else if(gWidth !== swidth) {
1346
+ gWidth = null;
1347
+ }
1348
+ }
1349
+
1350
+ $('#stroke_width').val(gWidth === null ? "0" : gWidth);
1351
+ updateContextPanel();
1352
+ break;
1353
+ default:
1354
+ //removed because multiselect shouldnt set color
1355
+ //Editor.paintBox.fill.update(false);
1356
+ //Editor.paintBox.stroke.update(false);
1357
+
1358
+ $('#stroke_width').val(selectedElement.getAttribute("stroke-width") || 0);
1359
+ var dash = selectedElement.getAttribute("stroke-dasharray") || "none"
1360
+ $('option', '#stroke_style').removeAttr('selected');
1361
+ $('#stroke_style option[value="'+ dash +'"]').attr("selected", "selected");
1362
+ $('#stroke_style').trigger('change');
1363
+
1364
+ $.fn.dragInput.updateCursor($('#stroke_width')[0])
1365
+ $.fn.dragInput.updateCursor($('#blur')[0])
1366
+ }
1367
+
1368
+ }
1369
+
1370
+ // All elements including image and group have opacity
1371
+ if(selectedElement != null) {
1372
+ var opac_perc = ((selectedElement.getAttribute("opacity")||1.0)*100);
1373
+ $('#group_opacity').val(opac_perc);
1374
+ $.fn.dragInput.updateCursor($('#group_opacity')[0])
1375
+ }
1376
+ };
1377
+
1378
+ var setImageURL = Editor.setImageURL = function(url) {
1379
+ if(!url) url = default_img_url;
1380
+
1381
+ svgCanvas.setImageURL(url);
1382
+ $('#image_url').val(url);
1383
+ }
1384
+
1385
+ var setInputWidth = function(elem) {
1386
+ var w = Math.min(Math.max(12 + elem.value.length * 6, 50), 300);
1387
+ $(elem).width(w);
1388
+ }
1389
+
1390
+ // updates the context panel tools based on the selected element
1391
+ var updateContextPanel = function(e) {
1392
+ var elem = selectedElement;
1393
+ // If element has just been deleted, consider it null
1394
+ if(elem != null && !elem.parentNode) elem = null;
1395
+ if (multiselected && multiselected[0] != null && !multiselected[0].parentNode) multiselected = false;
1396
+
1397
+ var currentLayerName = svgCanvas.getCurrentDrawing().getCurrentLayerName();
1398
+ var currentMode = svgCanvas.getMode();
1399
+ var unit = curConfig.baseUnit !== 'px' ? curConfig.baseUnit : null;
1400
+ var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false;
1401
+
1402
+ if (is_node) {
1403
+ $('.context_panel').hide();
1404
+ $('#path_node_panel').show();
1405
+ $('#stroke_panel').hide();
1406
+ var point = path.getNodePoint();
1407
+ $('#tool_add_subpath').removeClass('push_button_pressed').addClass('tool_button');
1408
+ $('#tool_node_delete').toggleClass('disabled', !path.canDeleteNodes);
1409
+
1410
+ // Show open/close button based on selected point
1411
+ setIcon('#tool_openclose_path', path.closed_subpath ? 'open_path' : 'close_path');
1412
+
1413
+ if(point) {
1414
+ var seg_type = $('#seg_type');
1415
+ if(unit) {
1416
+ point.x = svgedit.units.convertUnit(point.x);
1417
+ point.y = svgedit.units.convertUnit(point.y);
1418
+ }
1419
+ $('#path_node_x').val(Math.round(point.x));
1420
+ $('#path_node_y').val(Math.round(point.y));
1421
+ if(point.type) {
1422
+ seg_type.val(point.type).removeAttr('disabled');
1423
+ $("#seg_type_label").html(point.type == 4 ? "Straight" : "Curve")
1424
+ } else {
1425
+ seg_type.val(4).attr('disabled','disabled');
1426
+ }
1427
+ }
1428
+ $("#tools_top").removeClass("multiselected")
1429
+ $("#stroke_panel").hide();
1430
+ $("#canvas_panel").hide();
1431
+ return;
1432
+ }
1433
+
1434
+ var menu_items = $('#cmenu_canvas li');
1435
+ $('.context_panel').hide();
1436
+ $('.menu_item', '#edit_menu').addClass('disabled');
1437
+ $('.menu_item', '#object_menu').addClass('disabled');
1438
+
1439
+
1440
+ //hack to show the proper multialign box
1441
+ if (multiselected) {
1442
+ multiselected = multiselected.filter(Boolean);
1443
+ elem = (svgCanvas.elementsAreSame(multiselected)) ? multiselected[0] : null
1444
+ if (elem) $("#tools_top").addClass("multiselected")
1445
+ }
1446
+
1447
+ if (!elem && !multiselected) {
1448
+ $("#tools_top").removeClass("multiselected")
1449
+ $("#stroke_panel").hide();
1450
+ $("#canvas_panel").show();
1451
+ }
1452
+
1453
+ if (elem != null) {
1454
+ $("#stroke_panel").show();
1455
+ var elname = elem.nodeName;
1456
+ var angle = svgCanvas.getRotationAngle(elem);
1457
+ $('#angle').val(Math.round(angle));
1458
+
1459
+ var blurval = svgCanvas.getBlur(elem);
1460
+ $('#blur').val(blurval);
1461
+ if(!is_node && currentMode != 'pathedit') {
1462
+ $('#selected_panel').show();
1463
+ $('.action_selected').removeClass('disabled');
1464
+ // Elements in this array already have coord fields
1465
+ var x, y
1466
+ if(['g', 'polyline', 'path'].indexOf(elname) >= 0) {
1467
+ var bb = svgCanvas.getStrokedBBox([elem]);
1468
+ if(bb) {
1469
+ x = bb.x;
1470
+ y = bb.y;
1471
+ }
1472
+ }
1473
+
1474
+ if(unit) {
1475
+ x = svgedit.units.convertUnit(x);
1476
+ y = svgedit.units.convertUnit(y);
1477
+ }
1478
+
1479
+ $("#" + elname +"_x").val(Math.round(x))
1480
+ $("#" + elname +"_y").val(Math.round(y))
1481
+ if (elname === "polyline") {
1482
+ //we're acting as if polylines were paths
1483
+ $("#path_x").val(Math.round(x))
1484
+ $("#path_y").val(Math.round(y))
1485
+ }
1486
+
1487
+ // Elements in this array cannot be converted to a path
1488
+ var no_path = ['image', 'text', 'path', 'g', 'use'].indexOf(elname) == -1;
1489
+ if (no_path) $('.action_path_convert_selected').removeClass('disabled');
1490
+ if (elname === "path") $('.action_path_selected').removeClass('disabled');
1491
+
1492
+ }
1493
+
1494
+ var link_href = null;
1495
+ if (el_name === 'a') {
1496
+ link_href = svgCanvas.getHref(elem);
1497
+ $('#g_panel').show();
1498
+ }
1499
+
1500
+ if(elem.parentNode.tagName === 'a') {
1501
+ if(!$(elem).siblings().length) {
1502
+ $('#a_panel').show();
1503
+ link_href = svgCanvas.getHref(elem.parentNode);
1504
+ }
1505
+ }
1506
+
1507
+ // Hide/show the make_link buttons
1508
+ $('#tool_make_link, #tool_make_link').toggle(!link_href);
1509
+
1510
+ if(link_href) {
1511
+ $('#link_url').val(link_href);
1512
+ }
1513
+
1514
+ // update contextual tools here
1515
+ var panels = {
1516
+ g: [],
1517
+ a: [],
1518
+ rect: ['rx','width','height', 'x', 'y'],
1519
+ image: ['width','height', 'x', 'y'],
1520
+ circle: ['cx','cy','r'],
1521
+ ellipse: ['cx','cy','rx','ry'],
1522
+ line: ['x1','y1','x2','y2'],
1523
+ text: ['x', 'y'],
1524
+ 'use': [],
1525
+ path : []
1526
+ };
1527
+
1528
+ var el_name = elem.tagName;
1529
+
1530
+ if($(elem).data('gsvg')) {
1531
+ $('#g_panel').show();
1532
+ }
1533
+
1534
+ if (el_name == "path" || el_name == "polyline") {
1535
+ $('#path_panel').show();
1536
+ }
1537
+
1538
+ if(panels[el_name]) {
1539
+ var cur_panel = panels[el_name];
1540
+ $('#' + el_name + '_panel').show();
1541
+
1542
+ // corner radius has to live in a different panel
1543
+ // because otherwise it changes the position of the
1544
+ // of the elements
1545
+ if(el_name == "rect") $("#cornerRadiusLabel").show()
1546
+ else $("#cornerRadiusLabel").hide()
1547
+
1548
+ $.each(cur_panel, function(i, item) {
1549
+ var attrVal = elem.getAttribute(item);
1550
+ if(curConfig.baseUnit !== 'px' && elem[item]) {
1551
+ var bv = elem[item].baseVal.value;
1552
+ attrVal = svgedit.units.convertUnit(bv);
1553
+ }
1554
+
1555
+ //update the draginput cursors
1556
+ var name_item = document.getElementById(el_name + '_' + item);
1557
+ name_item.value = Math.round(attrVal) || 0;
1558
+ if (name_item.getAttribute("data-cursor") === "true") {
1559
+ $.fn.dragInput.updateCursor(name_item );
1560
+ }
1561
+ });
1562
+
1563
+ if(el_name == 'text') {
1564
+ var font_family = elem.getAttribute("font-family");
1565
+ var select = document.getElementById("font_family_dropdown");
1566
+ select.selectedIndex = 3
1567
+
1568
+ $('#text_panel').css("display", "inline");
1569
+ $('#tool_italic').toggleClass('active', svgCanvas.getItalic())
1570
+ $('#tool_bold').toggleClass('active', svgCanvas.getBold())
1571
+ $('#font_family').val(font_family);
1572
+ $('#font_size').val(elem.getAttribute("font-size"));
1573
+ $('#text').val(elem.textContent);
1574
+ $('#preview_font').text(font_family.split(",")[0].replace(/'/g, "")).css('font-family', font_family);
1575
+ if (svgCanvas.addedNew) {
1576
+ // Timeout needed for IE9
1577
+ setTimeout(function() {
1578
+ $('#text').focus().select();
1579
+ },100);
1580
+ }
1581
+ } // text
1582
+ else if(el_name == 'image') {
1583
+ setImageURL(svgCanvas.getHref(elem));
1584
+ } // image
1585
+ else if(el_name === 'g' || el_name === 'use') {
1586
+ $('#container_panel').show();
1587
+ $('.action_group_selected').removeClass('disabled');
1588
+ var title = svgCanvas.getTitle();
1589
+ }
1590
+ }
1591
+ menu_items[(el_name === 'g' ? 'en':'dis') + 'ableContextMenuItems']('#ungroup');
1592
+ menu_items[((el_name === 'g' || !multiselected) ? 'dis':'en') + 'ableContextMenuItems']('#group');
1593
+ }
1594
+
1595
+ if (multiselected) {
1596
+ $('#multiselected_panel').show();
1597
+ $('.action_multi_selected').removeClass('disabled');
1598
+ menu_items
1599
+ .enableContextMenuItems('#group')
1600
+ .disableContextMenuItems('#ungroup');
1601
+ }
1602
+
1603
+ if (!elem) {
1604
+ menu_items.disableContextMenuItems('#delete,#cut,#copy,#group,#ungroup,#move_front,#move_up,#move_down,#move_back');
1605
+ }
1606
+
1607
+ // update history buttons
1608
+ if (undoMgr.getUndoStackSize() > 0) {
1609
+ $('#tool_undo').removeClass( 'disabled');
1610
+ }
1611
+ else {
1612
+ $('#tool_undo').addClass( 'disabled');
1613
+ }
1614
+ if (undoMgr.getRedoStackSize() > 0) {
1615
+ $('#tool_redo').removeClass( 'disabled');
1616
+ }
1617
+ else {
1618
+ $('#tool_redo').addClass( 'disabled');
1619
+ }
1620
+
1621
+ svgCanvas.addedNew = false;
1622
+
1623
+ if ( (elem && !is_node) || multiselected) {
1624
+ // update the selected elements' layer
1625
+ $('#selLayerNames').removeAttr('disabled').val(currentLayerName);
1626
+
1627
+ // Enable regular menu options
1628
+ canv_menu.enableContextMenuItems('#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back');
1629
+ }
1630
+ };
1631
+
1632
+ $('#text').on("focus", function(e){ textBeingEntered = true; } );
1633
+ $('#text').on("blur", function(){ textBeingEntered = false; } );
1634
+
1635
+ // bind the selected event to our function that handles updates to the UI
1636
+ svgCanvas.bind("selected", selectedChanged);
1637
+ svgCanvas.bind("transition", elementTransition);
1638
+ svgCanvas.bind("changed", elementChanged);
1639
+ svgCanvas.bind("saved", saveHandler);
1640
+ svgCanvas.bind("exported", exportHandler);
1641
+ svgCanvas.bind("zoomed", zoomChanged);
1642
+ svgCanvas.bind("contextset", contextChanged);
1643
+ svgCanvas.bind("extension_added", extAdded);
1644
+ svgCanvas.textActions.setInputElem($("#text")[0]);
1645
+
1646
+ var str = '<div class="palette_item transparent" data-rgb="none"></div>\
1647
+ <div class="palette_item black" data-rgb="#000000"></div>\
1648
+ <div class="palette_item white" data-rgb="#ffffff"></div>'
1649
+ palette.forEach(function(item, i){
1650
+ str += '<div class="palette_item" style="background-color: ' + item + ';" data-rgb="' + item + '"></div>';
1651
+ });
1652
+ $('#palette').append(str);
1653
+
1654
+ var changeFontSize = function(ctl) {
1655
+ svgCanvas.setFontSize(ctl.value);
1656
+ }
1657
+
1658
+ var changeStrokeWidth = function(ctl) {
1659
+ var val = ctl.value;
1660
+ if(val == 0 && selectedElement && ['line', 'polyline'].indexOf(selectedElement.nodeName) >= 0) {
1661
+ val = ctl.value = 1;
1662
+ }
1663
+ svgCanvas.setStrokeWidth(val);
1664
+ }
1665
+
1666
+ //cache
1667
+ var $indicator = $('#tool_angle_indicator')
1668
+ var $reorient = $('#tool_reorient')
1669
+
1670
+ rotateCursor = function(angle){
1671
+ var rotate_string = 'rotate('+ angle + 'deg)'
1672
+ $indicator.css({
1673
+ '-webkit-transform': rotate_string,
1674
+ '-moz-transform': rotate_string,
1675
+ '-o-transform': rotate_string,
1676
+ '-ms-transform': rotate_string,
1677
+ 'transform': rotate_string
1678
+ });
1679
+ }
1680
+
1681
+ var changeRotationAngle = function(ctl) {
1682
+ var preventUndo = true;
1683
+ svgCanvas.setRotationAngle(ctl.value, preventUndo);
1684
+ rotateCursor(ctl.value)
1685
+ $('#tool_reorient').toggleClass('disabled', ctl.value == 0);
1686
+ }
1687
+
1688
+ var changeZoom = function(ctl) {
1689
+ var zoomlevel = ctl.value / 100;
1690
+ if(zoomlevel < .001) {
1691
+ ctl.value = .1;
1692
+ return;
1693
+ }
1694
+ var zoom = svgCanvas.getZoom();
1695
+ var w_area = workarea;
1696
+ zoomChanged(window, {
1697
+ width: 0,
1698
+ height: 0,
1699
+ // center pt of scroll position
1700
+ x: (w_area[0].scrollLeft + w_area.width()/2)/zoom,
1701
+ y: (w_area[0].scrollTop + w_area.height()/2)/zoom,
1702
+ zoom: zoomlevel
1703
+ }, true);
1704
+ }
1705
+
1706
+ var changeBlur = function(ctl, completed) {
1707
+ val = ctl.value;
1708
+ $('#blur').val(val);
1709
+ if (completed) {
1710
+ svgCanvas.setBlur(val, true);
1711
+ }
1712
+ else {
1713
+ svgCanvas.setBlurNoUndo(val);
1714
+ }
1715
+ }
1716
+
1717
+ var operaRepaint = function() {
1718
+ // Repaints canvas in Opera. Needed for stroke-dasharray change as well as fill change
1719
+ if(!window.opera) return;
1720
+ $('<p/>').hide().appendTo('body').remove();
1721
+ }
1722
+
1723
+ $('#stroke_style').change(function(){
1724
+ svgCanvas.setStrokeAttr('stroke-dasharray', $(this).val());
1725
+ $("#stroke_style_label").html(this.options[this.selectedIndex].text)
1726
+ operaRepaint();
1727
+ });
1728
+
1729
+ $('#seg_type').change(function() {
1730
+ svgCanvas.setSegType($(this).val());
1731
+ $("#seg_type_label").html(this.options[this.selectedIndex].text)
1732
+ });
1733
+
1734
+ // Lose focus for select elements when changed (Allows keyboard shortcuts to work better)
1735
+ $('select').change(function(){$(this).blur();});
1736
+
1737
+ $('#font_family').change(function() {
1738
+ svgCanvas.setFontFamily(this.value);
1739
+ });
1740
+
1741
+ $('#text').keyup(function(){
1742
+ svgCanvas.setTextContent(this.value);
1743
+ });
1744
+
1745
+ changeAttribute = function(el, completed) {
1746
+ var attr = el.getAttribute("data-attr");
1747
+ var multiplier = el.getAttribute("data-multiplier") || 1;
1748
+ multiplier = parseFloat(multiplier);
1749
+ var val = el.value * multiplier;
1750
+ var valid = svgedit.units.isValidUnit(attr, val, selectedElement);
1751
+ if(!valid) {
1752
+ $.alert(uiStrings.notification.invalidAttrValGiven);
1753
+ el.value = selectedElement.getAttribute(attr);
1754
+ return false;
1755
+ }
1756
+ //if (!noUndo) svgCanvas.changeSelectedAttribute(attr, val);
1757
+ svgCanvas.changeSelectedAttributeNoUndo(attr, val);
1758
+ };
1759
+
1760
+ picking = false;
1761
+ $(document).on("mouseup", function(){picking = false;})
1762
+
1763
+ $('#palette').on("mousemove mousedown touchstart touchmove", ".palette_item", function(evt){
1764
+ evt.preventDefault();
1765
+
1766
+ if (evt.type == "mousedown") picking = true;
1767
+ if (picking) {
1768
+ var isStroke = $('#tool_stroke').hasClass('active');
1769
+ var picker = isStroke ? "stroke" : "fill";
1770
+ var color = $(this).attr('data-rgb');
1771
+ var paint = null;
1772
+ var noUndo = true;
1773
+ if (evt.type == "mousedown") noUndo = false
1774
+ // Webkit-based browsers returned 'initial' here for no stroke
1775
+ if (color === 'transparent' || color === 'initial' || color === '#none') {
1776
+ color = 'none';
1777
+ paint = new $.jGraduate.Paint();
1778
+ }
1779
+ else {
1780
+ paint = new $.jGraduate.Paint({alpha: 100, solidColor: color.substr(1)});
1781
+ }
1782
+
1783
+ Editor.paintBox[picker].setPaint(paint);
1784
+
1785
+ if (isStroke) {
1786
+ svgCanvas.setColor('stroke', color, noUndo);
1787
+ if (color != 'none' && svgCanvas.getStrokeOpacity() != 1) {
1788
+ svgCanvas.setPaintOpacity('stroke', 1.0);
1789
+ }
1790
+ } else {
1791
+ svgCanvas.setColor('fill', color, noUndo);
1792
+ if (color != 'none' && svgCanvas.getFillOpacity() != 1) {
1793
+ svgCanvas.setPaintOpacity('fill', 1.0);
1794
+ }
1795
+ }
1796
+ }
1797
+ }).bind('contextmenu', function(e) {e.preventDefault()});
1798
+
1799
+ $("#toggle_stroke_tools").toggle(function() {
1800
+ $(".stroke_tool").css('display','table-cell');
1801
+ $(this).addClass('expanded');
1802
+ resetScrollPos();
1803
+ }, function() {
1804
+ $(".stroke_tool").css('display','none');
1805
+ $(this).removeClass('expanded');
1806
+ resetScrollPos();
1807
+ });
1808
+
1809
+ // This is a common function used when a tool has been clicked (chosen)
1810
+ // It does several common things:
1811
+ // - removes the tool_button_current class from whatever tool currently has it
1812
+ // - hides any flyouts
1813
+ // - adds the tool_button_current class to the button passed in
1814
+ var toolButtonClick = function(button, noHiding) {
1815
+ if ($(button).hasClass('disabled')) return false;
1816
+ if($(button).parent().hasClass('tools_flyout')) return true;
1817
+ var fadeFlyouts = fadeFlyouts || 'normal';
1818
+ if(!noHiding) {
1819
+ $('.tools_flyout').fadeOut(fadeFlyouts);
1820
+ }
1821
+ $('#styleoverrides').text('');
1822
+ $('.tool_button_current').removeClass('tool_button_current').addClass('tool_button');
1823
+ $(button).addClass('tool_button_current').removeClass('tool_button');
1824
+ return true;
1825
+ };
1826
+
1827
+ (function() {
1828
+ var last_x = null, last_y = null, w_area = workarea[0],
1829
+ panning = false, keypan = false;
1830
+
1831
+ var move_pan = function(evt) {
1832
+ if(panning === false) return;
1833
+
1834
+ w_area.scrollLeft -= (evt.clientX - last_x);
1835
+ w_area.scrollTop -= (evt.clientY - last_y);
1836
+ last_x = evt.clientX;
1837
+ last_y = evt.clientY;
1838
+ if(evt.type === 'mouseup' || evt.type === 'touchend') panning = false;
1839
+ return false;
1840
+ }
1841
+
1842
+ var start_pan = function(evt) {
1843
+ if(evt.button === 1 || keypan === true || (evt.originalEvent.touches && evt.originalEvent.touches.length >= 2)) {
1844
+ panning = true;
1845
+ last_x = evt.clientX;
1846
+ last_y = evt.clientY;
1847
+ return false;
1848
+ }
1849
+ }
1850
+
1851
+ $('#svgcanvas')
1852
+ .on('mousemove mouseup touchend', move_pan)
1853
+ .on("mousedown touchmove", start_pan)
1854
+
1855
+ $(window).mouseup(function() {
1856
+ panning = false;
1857
+ });
1858
+
1859
+ $(document).bind('keydown', 'space', function(evt) {
1860
+ evt.preventDefault();
1861
+ svgCanvas.spaceKey = keypan = true;
1862
+
1863
+ }).bind('keyup', 'space', function(evt) {
1864
+ evt.preventDefault();
1865
+ svgCanvas.spaceKey = keypan = false;
1866
+ }).bind('keydown', 'alt', function(evt) {
1867
+ if(svgCanvas.getMode() === 'zoom') {
1868
+ workarea.addClass('out');
1869
+ }
1870
+ }).bind('keyup', 'alt', function(evt) {
1871
+ if(svgCanvas.getMode() === 'zoom') {
1872
+ workarea.removeClass('out');
1873
+ }
1874
+ })
1875
+ }());
1876
+
1877
+
1878
+ function setStrokeOpt(opt, changeElem) {
1879
+ var id = opt.id;
1880
+ var bits = id.split('_');
1881
+ var pre = bits[0];
1882
+ var val = bits[1];
1883
+
1884
+ if(changeElem) {
1885
+ svgCanvas.setStrokeAttr('stroke-' + pre, val);
1886
+ }
1887
+ operaRepaint();
1888
+ setIcon('#cur_' + pre , id, 20);
1889
+ $(opt).addClass('current').siblings().removeClass('current');
1890
+ }
1891
+
1892
+ //menu handling
1893
+ var menus = $('.menu');
1894
+ var blinker = function(e) {
1895
+ e.target.style.background = "#fff";
1896
+ setTimeout(function(){e.target.style.background = "#ddd";}, 50);
1897
+ setTimeout(function(){e.target.style.background = "#fff";}, 150);
1898
+ setTimeout(function(){e.target.style.background = "#ddd";}, 200);
1899
+ setTimeout(function(){e.target.style.background = "";}, 200);
1900
+ setTimeout(function(){$('#menu_bar').removeClass('active')}, 220);
1901
+ return false;
1902
+ }
1903
+ var closer = function(e){
1904
+ if (e.target.nodeName && e.target.nodeName.toLowerCase() === "input") return false;
1905
+ if (!$(e.target).hasClass("menu_title") && !$(e.target).parent().hasClass("menu_title")) {
1906
+ if(!$(e.target).hasClass("disabled") && $(e.target).hasClass("menu_item")) blinker(e)
1907
+ else $('#menu_bar').removeClass('active')
1908
+
1909
+ }
1910
+ }
1911
+
1912
+ $('.menu_item').on('mousedown touchstart', function(e){blinker(e)});
1913
+ $("svg, body").on('mousedown touchstart', function(e){closer(e)});
1914
+
1915
+ var accumulatedDelta = 0
1916
+ $('#workarea').on('mousewheel', function(e, delta, deltaX, deltaY){
1917
+ if (e.altKey) {
1918
+ e.preventDefault();
1919
+ zoom = parseInt($("#zoom").val())
1920
+ $("#zoom").val(parseInt(zoom + deltaY*10)).change()
1921
+ }
1922
+ })
1923
+ $('.menu_title')
1924
+ .on('mousedown', function() {
1925
+ $("#tools_shapelib").hide()
1926
+ $("#menu_bar").toggleClass('active');
1927
+ menus.removeClass('open');
1928
+ $(this).parent().addClass('open');
1929
+ })
1930
+ .on('mouseover', function() {
1931
+ menus.removeClass('open');
1932
+ $(this).parent().addClass('open');
1933
+ });
1934
+
1935
+
1936
+ // Made public for UI customization.
1937
+ // TODO: Group UI functions into a public methodDraw.ui interface.
1938
+ Editor.addDropDown = function(elem, callback, dropUp) {
1939
+ if ($(elem).length == 0) return; // Quit if called on non-existant element
1940
+ var button = $(elem).find('button');
1941
+
1942
+ var list = $(elem).find('ul').attr('id', $(elem)[0].id + '-list');
1943
+
1944
+ if(!dropUp) {
1945
+ // Move list to place where it can overflow container
1946
+ $('#option_lists').append(list);
1947
+ }
1948
+
1949
+ var on_button = false;
1950
+ if(dropUp) {
1951
+ $(elem).addClass('dropup');
1952
+ }
1953
+
1954
+ list.find('li').bind('mouseup', callback);
1955
+
1956
+ $(window).mouseup(function(evt) {
1957
+ if(!on_button) {
1958
+ button.removeClass('down');
1959
+ list.hide();
1960
+ }
1961
+ on_button = false;
1962
+ });
1963
+
1964
+ button.bind('mousedown',function() {
1965
+ if (!button.hasClass('down')) {
1966
+ button.addClass('down');
1967
+
1968
+ if(!dropUp) {
1969
+ var pos = $(elem).offset();
1970
+ // position slider
1971
+ list.css({
1972
+ top: pos.top,
1973
+ left: pos.left - 110
1974
+ });
1975
+ }
1976
+ list.show();
1977
+
1978
+ on_button = true;
1979
+ } else {
1980
+ button.removeClass('down');
1981
+ list.hide();
1982
+ }
1983
+ }).hover(function() {
1984
+ on_button = true;
1985
+ }).mouseout(function() {
1986
+ on_button = false;
1987
+ });
1988
+ }
1989
+
1990
+ // TODO: Combine this with addDropDown or find other way to optimize
1991
+ var addAltDropDown = function(elem, list, callback, opts) {
1992
+ var button = $(elem);
1993
+ var list = $(list);
1994
+ var on_button = false;
1995
+ var dropUp = opts.dropUp;
1996
+ if(dropUp) {
1997
+ $(elem).addClass('dropup');
1998
+ }
1999
+ list.find('li').bind('mouseup', function() {
2000
+ if(opts.seticon) {
2001
+ setIcon('#cur_' + button[0].id , $(this).children());
2002
+ $(this).addClass('current').siblings().removeClass('current');
2003
+ }
2004
+ callback.apply(this, arguments);
2005
+
2006
+ });
2007
+
2008
+ $(window).mouseup(function(evt) {
2009
+ if(!on_button) {
2010
+ button.removeClass('down');
2011
+ list.hide();
2012
+ list.css({top:0, left:0});
2013
+ }
2014
+ on_button = false;
2015
+ });
2016
+
2017
+ var height = list.height();
2018
+ $(elem).bind('mousedown',function() {
2019
+ var off = $(elem).offset();
2020
+ if(dropUp) {
2021
+ off.top -= list.height();
2022
+ off.left += 8;
2023
+ } else {
2024
+ off.top += $(elem).height();
2025
+ }
2026
+ $(list).offset(off);
2027
+
2028
+ if (!button.hasClass('down')) {
2029
+ button.addClass('down');
2030
+ list.show();
2031
+ on_button = true;
2032
+ return false;
2033
+ } else {
2034
+ button.removeClass('down');
2035
+ // CSS position must be reset for Webkit
2036
+ list.hide();
2037
+ list.css({top:0, left:0});
2038
+ }
2039
+ }).hover(function() {
2040
+ on_button = true;
2041
+ }).mouseout(function() {
2042
+ on_button = false;
2043
+ });
2044
+
2045
+ if(opts.multiclick) {
2046
+ list.mousedown(function() {
2047
+ on_button = true;
2048
+ });
2049
+ }
2050
+ }
2051
+
2052
+ $('#font_family_dropdown').change(function() {
2053
+ var fam = this.options[this.selectedIndex].value
2054
+ var fam_display = this.options[this.selectedIndex].text
2055
+ $('#preview_font').html(fam_display).css("font-family", fam);
2056
+ $('#font_family').val(fam).change();
2057
+ });
2058
+
2059
+ $('div', '#position_opts').each(function(){
2060
+ this.addEventListener("mouseup", function(){
2061
+ var letter = this.id.replace('tool_pos','').charAt(0);
2062
+ svgCanvas.alignSelectedElements(letter, 'page');
2063
+ })
2064
+ });
2065
+
2066
+ /*
2067
+
2068
+ When a flyout icon is selected
2069
+ (if flyout) {
2070
+ - Change the icon
2071
+ - Make pressing the button run its stuff
2072
+ }
2073
+ - Run its stuff
2074
+
2075
+ When its shortcut key is pressed
2076
+ - If not current in list, do as above
2077
+ , else:
2078
+ - Just run its stuff
2079
+
2080
+ */
2081
+
2082
+ // Unfocus text input when workarea is mousedowned.
2083
+ (function() {
2084
+ var inp;
2085
+ var unfocus = function() {
2086
+ $(inp).blur();
2087
+ }
2088
+
2089
+ $('#svg_editor').find('button, select, input:not(#text)').focus(function() {
2090
+ inp = this;
2091
+ ui_context = 'toolbars';
2092
+ workarea.mousedown(unfocus);
2093
+ }).blur(function() {
2094
+ ui_context = 'canvas';
2095
+ workarea.unbind('mousedown', unfocus);
2096
+ // Go back to selecting text if in textedit mode
2097
+ if(svgCanvas.getMode() == 'textedit') {
2098
+ $('#text').focus();
2099
+ }
2100
+ });
2101
+
2102
+ }());
2103
+
2104
+ var clickSelect = function() {
2105
+ if (toolButtonClick('#tool_select')) {
2106
+ svgCanvas.setMode('select');
2107
+ }
2108
+ };
2109
+
2110
+ var clickFHPath = function() {
2111
+ if (toolButtonClick('#tool_fhpath')) {
2112
+ svgCanvas.setMode('fhpath');
2113
+ }
2114
+ };
2115
+
2116
+ var clickLine = function() {
2117
+ if (toolButtonClick('#tool_line')) {
2118
+ svgCanvas.setMode('line');
2119
+ }
2120
+ };
2121
+
2122
+ var clickSquare = function(){
2123
+ if (toolButtonClick('#tool_square')) {
2124
+ svgCanvas.setMode('square');
2125
+ }
2126
+ };
2127
+
2128
+ var clickRect = function(){
2129
+ if (toolButtonClick('#tool_rect')) {
2130
+ svgCanvas.setMode('rect');
2131
+ }
2132
+ };
2133
+
2134
+ var clickFHRect = function(){
2135
+ if (toolButtonClick('#tool_fhrect')) {
2136
+ svgCanvas.setMode('fhrect');
2137
+ }
2138
+ };
2139
+
2140
+ var clickCircle = function(){
2141
+ if (toolButtonClick('#tool_circle')) {
2142
+ svgCanvas.setMode('circle');
2143
+ }
2144
+ };
2145
+
2146
+ var clickEllipse = function(){
2147
+ if (toolButtonClick('#tool_ellipse')) {
2148
+ svgCanvas.setMode('ellipse');
2149
+ }
2150
+ };
2151
+
2152
+ var clickFHEllipse = function(){
2153
+ if (toolButtonClick('#tool_fhellipse')) {
2154
+ svgCanvas.setMode('fhellipse');
2155
+ }
2156
+ };
2157
+
2158
+ var clickImage = function(){
2159
+ if (toolButtonClick('#tool_image')) {
2160
+ svgCanvas.setMode('image');
2161
+ }
2162
+ };
2163
+
2164
+ var clickZoom = function(){
2165
+ if (toolButtonClick('#tool_zoom')) {
2166
+ svgCanvas.setMode('zoom');
2167
+ }
2168
+ };
2169
+
2170
+ var dblclickZoom = function(){
2171
+ if (toolButtonClick('#tool_zoom')) {
2172
+ zoomImage();
2173
+ setSelectMode();
2174
+ }
2175
+ };
2176
+
2177
+ var clickText = function(){
2178
+ if (toolButtonClick('#tool_text')) {
2179
+ svgCanvas.setMode('text');
2180
+ }
2181
+ };
2182
+
2183
+ var clickPath = function(){
2184
+ if (toolButtonClick('#tool_path')) {
2185
+ svgCanvas.setMode('path');
2186
+ }
2187
+ };
2188
+
2189
+ // Delete is a contextual tool that only appears in the ribbon if
2190
+ // an element has been selected
2191
+ var deleteSelected = function() {
2192
+ if (selectedElement != null || multiselected) {
2193
+ svgCanvas.deleteSelectedElements();
2194
+ }
2195
+ if (path.getNodePoint()) {
2196
+ path.deletePathNode();
2197
+ }
2198
+ };
2199
+
2200
+ var cutSelected = function() {
2201
+ if (selectedElement != null || multiselected) {
2202
+ flash($('#edit_menu'));
2203
+ svgCanvas.cutSelectedElements();
2204
+ }
2205
+ };
2206
+
2207
+ var copySelected = function() {
2208
+ if (selectedElement != null || multiselected) {
2209
+ flash($('#edit_menu'));
2210
+ svgCanvas.copySelectedElements();
2211
+ }
2212
+ };
2213
+
2214
+ var pasteSelected = function() {
2215
+ flash($('#edit_menu'));
2216
+ var zoom = svgCanvas.getZoom();
2217
+ var x = (workarea[0].scrollLeft + workarea.width()/2)/zoom - svgCanvas.contentW;
2218
+ var y = (workarea[0].scrollTop + workarea.height()/2)/zoom - svgCanvas.contentH;
2219
+ svgCanvas.pasteElements('point', x, y);
2220
+ }
2221
+
2222
+ var moveToTopSelected = function() {
2223
+ if (selectedElement != null) {
2224
+ flash($('#object_menu'));
2225
+ svgCanvas.moveToTopSelectedElement();
2226
+ }
2227
+ };
2228
+
2229
+ var moveToBottomSelected = function() {
2230
+ if (selectedElement != null) {
2231
+ flash($('#object_menu'));
2232
+ svgCanvas.moveToBottomSelectedElement();
2233
+ }
2234
+ };
2235
+
2236
+ var moveUpSelected = function() {
2237
+ if (selectedElement != null) {
2238
+ flash($('#object_menu'));
2239
+ svgCanvas.moveUpDownSelected("Up");
2240
+ }
2241
+ };
2242
+
2243
+ var moveDownSelected = function() {
2244
+ if (selectedElement != null) {
2245
+ flash($('#object_menu'));
2246
+ svgCanvas.moveUpDownSelected("Down");
2247
+ }
2248
+ };
2249
+
2250
+ var moveUpDownSelected = function(dir) {
2251
+ if (selectedElement != null) {
2252
+ flash($('#object_menu'));
2253
+ svgCanvas.moveUpDownSelected(dir);
2254
+ }
2255
+ };
2256
+
2257
+ var convertToPath = function() {
2258
+ if (selectedElement != null) {
2259
+ svgCanvas.convertToPath();
2260
+ var elems = svgCanvas.getSelectedElems()
2261
+ svgCanvas.selectorManager.requestSelector(elems[0]).reset(elems[0])
2262
+ svgCanvas.selectorManager.requestSelector(elems[0]).selectorRect.setAttribute("display", "none");
2263
+ svgCanvas.setMode("pathedit")
2264
+ path.toEditMode(elems[0]);
2265
+ svgCanvas.clearSelection();
2266
+ updateContextPanel();
2267
+ }
2268
+ }
2269
+
2270
+ var reorientPath = function() {
2271
+ if (selectedElement != null) {
2272
+ path.reorient();
2273
+ }
2274
+ }
2275
+
2276
+ var makeHyperlink = function() {
2277
+ if (selectedElement != null || multiselected) {
2278
+ $.prompt(uiStrings.notification.enterNewLinkURL, "http://", function(url) {
2279
+ if(url) svgCanvas.makeHyperlink(url);
2280
+ });
2281
+ }
2282
+ }
2283
+
2284
+ var moveSelected = function(dx,dy) {
2285
+ if (selectedElement != null || multiselected) {
2286
+ if(curConfig.gridSnapping) {
2287
+ // Use grid snap value regardless of zoom level
2288
+ var multi = svgCanvas.getZoom() * curConfig.snappingStep;
2289
+ dx *= multi;
2290
+ dy *= multi;
2291
+ }
2292
+ $('input').blur()
2293
+ svgCanvas.moveSelectedElements(dx,dy);
2294
+ }
2295
+ };
2296
+
2297
+ var linkControlPoints = function() {
2298
+ // var linked = document.getElementById('tool_node_link').checked;
2299
+ // path.linkControlPoints(linked);
2300
+ }
2301
+
2302
+ var clonePathNode = function() {
2303
+ if (path.getNodePoint()) {
2304
+ path.clonePathNode();
2305
+ }
2306
+ };
2307
+
2308
+ var deletePathNode = function() {
2309
+ if (path.getNodePoint()) {
2310
+ path.deletePathNode();
2311
+ }
2312
+ };
2313
+
2314
+ var addSubPath = function() {
2315
+ var button = $('#tool_add_subpath');
2316
+ var sp = !button.hasClass('push_button_pressed');
2317
+ if (sp) {
2318
+ button.addClass('push_button_pressed').removeClass('tool_button');
2319
+ } else {
2320
+ button.removeClass('push_button_pressed').addClass('tool_button');
2321
+ }
2322
+
2323
+ path.addSubPath(sp);
2324
+
2325
+ };
2326
+
2327
+ var opencloseSubPath = function() {
2328
+ path.opencloseSubPath();
2329
+ }
2330
+
2331
+ var selectNext = function() {
2332
+ svgCanvas.cycleElement(1);
2333
+ };
2334
+
2335
+ var selectPrev = function() {
2336
+ svgCanvas.cycleElement(0);
2337
+ };
2338
+
2339
+ var rotateSelected = function(cw,step) {
2340
+ if (selectedElement == null || multiselected) return;
2341
+ if(!cw) step *= -1;
2342
+ var new_angle = $('#angle').val()*1 + step;
2343
+ svgCanvas.setRotationAngle(new_angle);
2344
+ updateContextPanel();
2345
+ };
2346
+
2347
+ var clickClear = function(){
2348
+ var dims = curConfig.dimensions;
2349
+ $.confirm(uiStrings.notification.QwantToClear, function(ok) {
2350
+ if(!ok) return;
2351
+ setSelectMode();
2352
+ svgCanvas.clear();
2353
+ svgCanvas.setResolution(dims[0], dims[1]);
2354
+ updateCanvas(true);
2355
+ zoomImage();
2356
+ updateContextPanel();
2357
+ prepPaints();
2358
+ svgCanvas.runExtensions('onNewDocument');
2359
+ });
2360
+ };
2361
+
2362
+ var clickBold = function(){
2363
+ svgCanvas.setBold( !svgCanvas.getBold() );
2364
+ updateContextPanel();
2365
+ };
2366
+
2367
+ var clickItalic = function(){
2368
+ svgCanvas.setItalic( !svgCanvas.getItalic() );
2369
+ updateContextPanel();
2370
+ };
2371
+
2372
+ var clickExport = function() {
2373
+ // Open placeholder window (prevents popup)
2374
+ if(!customHandlers.pngsave) {
2375
+ var str = uiStrings.notification.loadingImage;
2376
+ exportWindow = window.open("data:text/html;charset=utf-8,<title>" + str + "<\/title><h1>" + str + "<\/h1>");
2377
+ }
2378
+
2379
+ if(window.canvg) {
2380
+ svgCanvas.rasterExport();
2381
+ } else {
2382
+ $.getScript('canvg/rgbcolor.js', function() {
2383
+ $.getScript('canvg/canvg.js', function() {
2384
+ svgCanvas.rasterExport();
2385
+ });
2386
+ });
2387
+ }
2388
+ }
2389
+
2390
+ // by default, svgCanvas.open() is a no-op.
2391
+ // it is up to an extension mechanism (opera widget, etc)
2392
+ // to call setCustomHandlers() which will make it do something
2393
+ var clickOpen = function(){
2394
+ svgCanvas.open();
2395
+ };
2396
+ var clickImport = function(){
2397
+ };
2398
+
2399
+ var flash = function($menu){
2400
+ var menu_title = $menu.prev();
2401
+ menu_title.css({
2402
+ "background": "white",
2403
+ "color": "black"
2404
+ });
2405
+ setTimeout(function(){menu_title.removeAttr("style")}, 200);
2406
+ }
2407
+
2408
+ var clickUndo = function(){
2409
+ if (undoMgr.getUndoStackSize() > 0) {
2410
+ flash($('#edit_menu'));
2411
+ undoMgr.undo();
2412
+ }
2413
+ };
2414
+
2415
+ var clickRedo = function(){
2416
+ if (undoMgr.getRedoStackSize() > 0) {
2417
+ flash($('#edit_menu'));
2418
+ undoMgr.redo();
2419
+ }
2420
+ };
2421
+
2422
+ var clickGroup = function(){
2423
+ // group
2424
+ if (multiselected) {
2425
+ flash($('#object_menu'));
2426
+ svgCanvas.groupSelectedElements();
2427
+ }
2428
+ // ungroup
2429
+ else if(selectedElement){
2430
+ flash($('#object_menu'));
2431
+ svgCanvas.ungroupSelectedElement();
2432
+ }
2433
+ };
2434
+
2435
+ var clickClone = function(){
2436
+ flash($('#edit_menu'));
2437
+ svgCanvas.cloneSelectedElements(20,20);
2438
+ };
2439
+
2440
+ var clickAlign = function() {
2441
+ var letter = this.id.replace('tool_align','').charAt(0);
2442
+ svgCanvas.alignSelectedElements(letter, $('#align_relative_to').val());
2443
+ };
2444
+
2445
+ var clickSwitch = function() {
2446
+ var stroke_rect = document.querySelector('#tool_stroke rect');
2447
+ $("#tool_stroke").toggleClass('active')
2448
+ $("#tool_fill").toggleClass('active')
2449
+ var fill_rect = document.querySelector('#tool_fill rect');
2450
+ var fill_color = fill_rect.getAttribute("fill");
2451
+ var stroke_color = stroke_rect.getAttribute("fill");
2452
+ var stroke_opacity = parseFloat(stroke_rect.getAttribute("stroke-opacity"));
2453
+ if (isNaN(stroke_opacity)) {stroke_opacity = 100;}
2454
+ var fill_opacity = parseFloat(fill_rect.getAttribute("fill-opacity"));
2455
+ if (isNaN(fill_opacity)) {fill_opacity = 100;}
2456
+ var stroke = getPaint(stroke_color, stroke_opacity, "stroke");
2457
+ var fill = getPaint(fill_color, fill_opacity, "fill");
2458
+ Editor.paintBox.fill.setPaint(stroke, true);
2459
+ Editor.paintBox.stroke.setPaint(fill, true);
2460
+
2461
+ };
2462
+
2463
+ var zoomImage = function(multiplier) {
2464
+ var res = svgCanvas.getResolution();
2465
+ multiplier = multiplier?res.zoom * multiplier:1;
2466
+ // setResolution(res.w * multiplier, res.h * multiplier, true);
2467
+ $('#zoom').val(multiplier * 100);
2468
+ svgCanvas.setZoom(multiplier);
2469
+ zoomDone();
2470
+ updateCanvas(true);
2471
+ };
2472
+
2473
+ var zoomDone = function() {
2474
+ // updateBgImage();
2475
+ updateWireFrame();
2476
+ //updateCanvas(); // necessary?
2477
+ }
2478
+
2479
+ var clickWireframe = function() {
2480
+ flash($('#view_menu'));
2481
+ var wf = !$('#tool_wireframe').hasClass('push_button_pressed');
2482
+ if (wf)
2483
+ $('#tool_wireframe').addClass('push_button_pressed');
2484
+ else
2485
+ $('#tool_wireframe').removeClass('push_button_pressed');
2486
+ workarea.toggleClass('wireframe');
2487
+
2488
+ if(supportsNonSS) return;
2489
+ var wf_rules = $('#wireframe_rules');
2490
+ if(!wf_rules.length) {
2491
+ wf_rules = $('<style id="wireframe_rules"><\/style>').appendTo('head');
2492
+ } else {
2493
+ wf_rules.empty();
2494
+ }
2495
+
2496
+ updateWireFrame();
2497
+ }
2498
+
2499
+ var clickSnapGrid = function() {
2500
+ flash($('#view_menu'));
2501
+ var sg = !$('#tool_snap').hasClass('push_button_pressed');
2502
+ if (sg)
2503
+ $('#tool_snap').addClass('push_button_pressed');
2504
+ else
2505
+ $('#tool_snap').removeClass('push_button_pressed');
2506
+ curConfig.gridSnapping = sg;
2507
+ }
2508
+
2509
+ var minimizeModal = function() {
2510
+
2511
+ if (window.self != window.top) { //we're in an iframe
2512
+ top.exit_fullscreen();
2513
+ }
2514
+ }
2515
+
2516
+ var clickRulers = function() {
2517
+ flash($('#view_menu'));
2518
+ var rulers = !$('#tool_rulers').hasClass('push_button_pressed');
2519
+ if (rulers) {
2520
+ $('#tool_rulers').addClass('push_button_pressed');
2521
+ $('#show_rulers').attr("checked", true);
2522
+ curConfig.showRulers = true;
2523
+ }
2524
+ else {
2525
+ $('#tool_rulers').removeClass('push_button_pressed');
2526
+ $('#show_rulers').attr("checked", false);
2527
+ curConfig.showRulers = false;
2528
+ }
2529
+ $('#rulers').toggle(!!curConfig.showRulers)
2530
+ }
2531
+
2532
+ var updateWireFrame = function() {
2533
+ // Test support
2534
+ if(supportsNonSS) return;
2535
+
2536
+ var rule = "#workarea.wireframe #svgcontent * { stroke-width: " + 1/svgCanvas.getZoom() + "px; }";
2537
+ $('#wireframe_rules').text(workarea.hasClass('wireframe') ? rule : "");
2538
+ }
2539
+
2540
+ var showSourceEditor = function(e, forSaving){
2541
+ if (editingsource) return;
2542
+ flash($('#view_menu'));
2543
+ editingsource = true;
2544
+
2545
+ $('#save_output_btns').toggle(!!forSaving);
2546
+ $('#tool_source_back').toggle(!forSaving);
2547
+
2548
+ var str = orig_source = svgCanvas.getSvgString();
2549
+ $('#svg_source_textarea').val(str);
2550
+ $('#svg_source_editor').fadeIn();
2551
+ $('#svg_source_textarea').focus().select();
2552
+ };
2553
+
2554
+ var clickSave = function(){
2555
+ flash($('#file_menu'));
2556
+ // In the future, more options can be provided here
2557
+ var saveOpts = {
2558
+ 'images': curPrefs.img_save,
2559
+ 'round_digits': 6
2560
+ }
2561
+ svgCanvas.save(saveOpts);
2562
+ };
2563
+
2564
+ var saveSourceEditor = function(){
2565
+ if (!editingsource) return;
2566
+
2567
+ var saveChanges = function() {
2568
+ svgCanvas.clearSelection();
2569
+ hideSourceEditor();
2570
+ zoomImage();
2571
+ prepPaints();
2572
+ }
2573
+
2574
+ if (!svgCanvas.setSvgString($('#svg_source_textarea').val())) {
2575
+ $.confirm(uiStrings.notification.QerrorsRevertToSource, function(ok) {
2576
+ if(!ok) return false;
2577
+ saveChanges();
2578
+ });
2579
+ } else {
2580
+ saveChanges();
2581
+ }
2582
+ setSelectMode();
2583
+ };
2584
+
2585
+ function setBackground(color, url) {
2586
+ // if(color == curPrefs.bkgd_color && url == curPrefs.bkgd_url) return;
2587
+ $.pref('bkgd_color', color);
2588
+ $.pref('bkgd_url', url);
2589
+
2590
+ // This should be done in svgcanvas.js for the borderRect fill
2591
+ svgCanvas.setBackground(color, url);
2592
+ }
2593
+
2594
+ var setIcon = Editor.setIcon = function(elem, icon_id, forcedSize) {
2595
+ var icon = (typeof icon_id === 'string') ? $.getSvgIcon(icon_id, true) : icon_id.clone();
2596
+ if(!icon) {
2597
+ console.log('NOTE: Icon image missing: ' + icon_id);
2598
+ return;
2599
+ }
2600
+
2601
+ $(elem).find("img").replaceWith(icon);
2602
+ }
2603
+
2604
+ var ua_prefix;
2605
+ (ua_prefix = function() {
2606
+ var regex = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/;
2607
+ var someScript = document.getElementsByTagName('script')[0];
2608
+ for(var prop in someScript.style) {
2609
+ if(regex.test(prop)) {
2610
+ // test is faster than match, so it's better to perform
2611
+ // that on the lot and match only when necessary
2612
+ return prop.match(regex)[0];
2613
+ }
2614
+ }
2615
+
2616
+ // Nothing found so far?
2617
+ if('WebkitOpacity' in someScript.style) return 'Webkit';
2618
+ if('KhtmlOpacity' in someScript.style) return 'Khtml';
2619
+
2620
+ return '';
2621
+ }());
2622
+
2623
+ var scaleElements = function(elems, scale) {
2624
+ var prefix = '-' + ua_prefix.toLowerCase() + '-';
2625
+
2626
+ var sides = ['top', 'left', 'bottom', 'right'];
2627
+
2628
+ elems.each(function() {
2629
+ // console.log('go', scale);
2630
+
2631
+ // Handled in CSS
2632
+ // this.style[ua_prefix + 'Transform'] = 'scale(' + scale + ')';
2633
+
2634
+ var el = $(this);
2635
+
2636
+ var w = el.outerWidth() * (scale - 1);
2637
+ var h = el.outerHeight() * (scale - 1);
2638
+ var margins = {};
2639
+
2640
+ for(var i = 0; i < 4; i++) {
2641
+ var s = sides[i];
2642
+
2643
+ var cur = el.data('orig_margin-' + s);
2644
+ if(cur == null) {
2645
+ cur = parseInt(el.css('margin-' + s));
2646
+ // Cache the original margin
2647
+ el.data('orig_margin-' + s, cur);
2648
+ }
2649
+ var val = cur * scale;
2650
+ if(s === 'right') {
2651
+ val += w;
2652
+ } else if(s === 'bottom') {
2653
+ val += h;
2654
+ }
2655
+
2656
+ el.css('margin-' + s, val);
2657
+ // el.css('outline', '1px solid red');
2658
+ }
2659
+ });
2660
+ }
2661
+
2662
+ var setIconSize = Editor.setIconSize = function(size, force) {
2663
+ if(size == curPrefs.size && !force) return;
2664
+ // return;
2665
+ // var elems = $('.tool_button, .push_button, .tool_button_current, .disabled, .icon_label, #url_notice, #tool_open');
2666
+
2667
+ var sel_toscale = '#tools_top .toolset, #editor_panel > *, #history_panel > *,\
2668
+ #main_button, #tools_left > *, #path_node_panel > *, #multiselected_panel > *,\
2669
+ #g_panel > *, #tool_font_size > *, .tools_flyout';
2670
+
2671
+ var elems = $(sel_toscale);
2672
+
2673
+ var scale = 1;
2674
+
2675
+ if(typeof size == 'number') {
2676
+ scale = size;
2677
+ } else {
2678
+ var icon_sizes = { s:.75, m:1, l:1.25, xl:1.5 };
2679
+ scale = icon_sizes[size];
2680
+ }
2681
+
2682
+ Editor.tool_scale = tool_scale = scale;
2683
+
2684
+ setFlyoutPositions();
2685
+ var hidden_ps = elems.parents(':hidden');
2686
+ hidden_ps.css('visibility', 'hidden').show();
2687
+ scaleElements(elems, scale);
2688
+ hidden_ps.css('visibility', 'visible').hide();
2689
+
2690
+ var rule_elem = $('#tool_size_rules');
2691
+ if(!rule_elem.length) {
2692
+ rule_elem = $('<style id="tool_size_rules"><\/style>').appendTo('head');
2693
+ } else {
2694
+ rule_elem.empty();
2695
+ }
2696
+
2697
+ if(size != 'm') {
2698
+ var style_str = '';
2699
+ $.each(cssResizeRules, function(selector, rules) {
2700
+ selector = '#svg_editor ' + selector.replace(/,/g,', #svg_editor');
2701
+ style_str += selector + '{';
2702
+ $.each(rules, function(prop, values) {
2703
+ if(typeof values === 'number') {
2704
+ var val = (values * scale) + 'px';
2705
+ } else if(values[size] || values.all) {
2706
+ var val = (values[size] || values.all);
2707
+ }
2708
+ style_str += (prop + ':' + val + ';');
2709
+ });
2710
+ style_str += '}';
2711
+ });
2712
+ //this.style[ua_prefix + 'Transform'] = 'scale(' + scale + ')';
2713
+ var prefix = '-' + ua_prefix.toLowerCase() + '-';
2714
+ style_str += (sel_toscale + '{' + prefix + 'transform: scale(' + scale + ');}'
2715
+ + ' #svg_editor div.toolset .toolset {' + prefix + 'transform: scale(1); margin: 1px !important;}' // Hack for markers
2716
+ + ' #svg_editor .ui-slider {' + prefix + 'transform: scale(' + (1/scale) + ');}' // Hack for sliders
2717
+ );
2718
+ rule_elem.text(style_str);
2719
+ }
2720
+
2721
+ setFlyoutPositions();
2722
+ }
2723
+
2724
+ var cancelOverlays = function() {
2725
+ $('#dialog_box').hide();
2726
+ if (!editingsource && !docprops && !preferences) {
2727
+ if(cur_context) {
2728
+ svgCanvas.leaveContext();
2729
+ }
2730
+ return;
2731
+ };
2732
+
2733
+ if (editingsource) {
2734
+ if (orig_source !== $('#svg_source_textarea').val()) {
2735
+ $.confirm(uiStrings.notification.QignoreSourceChanges, function(ok) {
2736
+ if(ok) hideSourceEditor();
2737
+ });
2738
+ } else {
2739
+ hideSourceEditor();
2740
+ }
2741
+ }
2742
+ else if (docprops) {
2743
+ hideDocProperties();
2744
+ } else if (preferences) {
2745
+ hidePreferences();
2746
+ }
2747
+ resetScrollPos();
2748
+ };
2749
+
2750
+ var hideSourceEditor = function(){
2751
+ $('#svg_source_editor').hide();
2752
+ editingsource = false;
2753
+ $('#svg_source_textarea').blur();
2754
+ };
2755
+
2756
+ var win_wh = {width:$(window).width(), height:$(window).height()};
2757
+
2758
+ var resetScrollPos = $.noop, curScrollPos;
2759
+
2760
+ /* Fix for Issue 781: Drawing area jumps to top-left corner on window resize (IE9)
2761
+ if(svgedit.browser.isIE()) {
2762
+ (function() {
2763
+ resetScrollPos = function() {
2764
+ if(workarea[0].scrollLeft === 0
2765
+ && workarea[0].scrollTop === 0) {
2766
+ workarea[0].scrollLeft = curScrollPos.left;
2767
+ workarea[0].scrollTop = curScrollPos.top;
2768
+ }
2769
+ }
2770
+
2771
+ curScrollPos = {
2772
+ left: workarea[0].scrollLeft,
2773
+ top: workarea[0].scrollTop
2774
+ };
2775
+
2776
+ $(window).resize(resetScrollPos);
2777
+ methodDraw.ready(function() {
2778
+ // TODO: Find better way to detect when to do this to minimize
2779
+ // flickering effect
2780
+ setTimeout(function() {
2781
+ resetScrollPos();
2782
+ }, 500);
2783
+ });
2784
+
2785
+ workarea.scroll(function() {
2786
+ curScrollPos = {
2787
+ left: workarea[0].scrollLeft,
2788
+ top: workarea[0].scrollTop
2789
+ };
2790
+ });
2791
+ }());
2792
+ }*/
2793
+
2794
+ $(window).resize(function(evt) {
2795
+ updateCanvas();
2796
+ });
2797
+
2798
+ (function() {
2799
+ workarea.scroll(function() {
2800
+ // TODO: jQuery's scrollLeft/Top() wouldn't require a null check
2801
+ if ($('#ruler_x').length != 0) {
2802
+ $('#ruler_x')[0].scrollLeft = workarea[0].scrollLeft;
2803
+ }
2804
+ if ($('#ruler_y').length != 0) {
2805
+ $('#ruler_y')[0].scrollTop = workarea[0].scrollTop;
2806
+ }
2807
+ });
2808
+
2809
+ }());
2810
+
2811
+ $('#url_notice').click(function() {
2812
+ $.alert(this.title);
2813
+ });
2814
+
2815
+ $('#change_image_url').click(promptImgURL);
2816
+
2817
+ function promptImgURL() {
2818
+ var curhref = svgCanvas.getHref(selectedElement);
2819
+ curhref = curhref.indexOf("data:") === 0?"":curhref;
2820
+ $.prompt(uiStrings.notification.enterNewImgURL, curhref, function(url) {
2821
+ if(url) setImageURL(url);
2822
+ });
2823
+ }
2824
+
2825
+ // TODO: go back to the color boxes having white background-color and then setting
2826
+ // background-image to none.png (otherwise partially transparent gradients look weird)
2827
+ var colorPicker = function(elem) {
2828
+ var picker = elem[0].id == 'stroke_color' ? 'stroke' : 'fill';
2829
+ var is_background = elem[0].id == "canvas_color"
2830
+ if (is_background) picker = 'canvas'
2831
+ // var opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity'));
2832
+ var paint = Editor.paintBox[picker].paint;
2833
+
2834
+ var title = (picker == 'stroke' ? 'Pick a Stroke Paint and Opacity' : 'Pick a Fill Paint and Opacity');
2835
+ var was_none = false;
2836
+ var pos = is_background ? {'right': 175, 'top': 50} : {'left': 50, 'bottom': 50}
2837
+
2838
+ $("#color_picker")
2839
+ .draggable({cancel:'.jGraduate_tabs, .jGraduate_colPick, .jGraduate_gradPick, .jPicker', containment: 'window'})
2840
+ .removeAttr("style")
2841
+ .css(pos)
2842
+ .jGraduate(
2843
+ {
2844
+ paint: paint,
2845
+ window: { pickerTitle: title },
2846
+ images: { clientPath: curConfig.jGraduatePath },
2847
+ newstop: 'inverse'
2848
+ },
2849
+ function(p) {
2850
+ paint = new $.jGraduate.Paint(p);
2851
+
2852
+ Editor.paintBox[picker].setPaint(paint);
2853
+ svgCanvas.setPaint(picker, paint);
2854
+
2855
+ $('#color_picker').hide();
2856
+ },
2857
+ function(p) {
2858
+ $('#color_picker').hide();
2859
+ });
2860
+ };
2861
+
2862
+ var PaintBox = function(container, type) {
2863
+ var background = document.getElementById("canvas_background");
2864
+ var cur = {color: "fff", opacity: 1}
2865
+ if (type == "stroke") cur = curConfig['initStroke'];
2866
+ if (type == "fill") cur = curConfig['initFill'];
2867
+ if (type == "canvas" && background) {
2868
+ var rgb = background.getAttribute("fill").match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
2869
+ if (rgb) {
2870
+ var hex = ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
2871
+ ("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
2872
+ ("0" + parseInt(rgb[3],10).toString(16)).slice(-2);
2873
+ cur = {color: hex, opacity: 1}
2874
+ }
2875
+ }
2876
+
2877
+ // set up gradients to be used for the buttons
2878
+ var svgdocbox = new DOMParser().parseFromString(
2879
+ '<svg xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%"\
2880
+ fill="#' + cur.color + '" opacity="' + cur.opacity + '"/>\
2881
+ <defs><linearGradient id="gradbox_"/></defs></svg>', 'text/xml');
2882
+ var docElem = svgdocbox.documentElement;
2883
+
2884
+ docElem = $(container)[0].appendChild(document.importNode(docElem, true));
2885
+ if (type === 'canvas') docElem.setAttribute('width',60.5);
2886
+ else docElem.setAttribute('width',"100%");
2887
+
2888
+ this.rect = docElem.firstChild;
2889
+ this.defs = docElem.getElementsByTagName('defs')[0];
2890
+ this.grad = this.defs.firstChild;
2891
+ this.paint = new $.jGraduate.Paint({solidColor: cur.color});
2892
+ this.type = type;
2893
+
2894
+ this.setPaint = function(paint, apply, noUndo) {
2895
+ this.paint = paint;
2896
+ var fillAttr = "none";
2897
+ var ptype = paint.type;
2898
+ var opac = paint.alpha / 100;
2899
+ switch ( ptype ) {
2900
+ case 'solidColor':
2901
+ fillAttr = (paint[ptype] == 'none' || paint[ptype] == 'one') ? 'none' : "#" + paint[ptype];
2902
+ break;
2903
+ case 'linearGradient':
2904
+ case 'radialGradient':
2905
+ this.defs.removeChild(this.grad);
2906
+ this.grad = this.defs.appendChild(paint[ptype]);
2907
+ var id = this.grad.id = 'gradbox_' + this.type;
2908
+ fillAttr = "url(#" + id + ')';
2909
+ }
2910
+ this.rect.setAttribute('fill', fillAttr);
2911
+ this.rect.setAttribute('opacity', opac);
2912
+
2913
+ if (this.type == "canvas") {
2914
+ //recache background in case it changed
2915
+ var background = document.getElementById("canvas_background");
2916
+ if (background) {
2917
+ res = svgCanvas.getResolution()
2918
+ background.setAttribute("x", -1);
2919
+ background.setAttribute("y", -1);
2920
+ background.setAttribute("width", res.w+2);
2921
+ background.setAttribute("height", res.h+2);
2922
+ if (fillAttr.indexOf("url") == -1) background.setAttribute('fill', fillAttr)
2923
+ }
2924
+ else createBackground(fillAttr)
2925
+ }
2926
+
2927
+ if(apply) {
2928
+ svgCanvas.setColor(this.type, fillAttr, true);
2929
+ svgCanvas.setPaintOpacity(this.type, opac, true);
2930
+ }
2931
+
2932
+ }
2933
+
2934
+ this.update = function(apply) {
2935
+ if(!selectedElement) return;
2936
+ var type = this.type;
2937
+ switch ( selectedElement.tagName ) {
2938
+ case 'use':
2939
+ case 'image':
2940
+ case 'foreignObject':
2941
+ // These elements don't have fill or stroke, so don't change
2942
+ // the current value
2943
+ return;
2944
+ case 'g':
2945
+ case 'a':
2946
+ var gPaint = null;
2947
+
2948
+ var childs = selectedElement.getElementsByTagName('*');
2949
+ for(var i = 0, len = childs.length; i < len; i++) {
2950
+ var elem = childs[i];
2951
+ var p = elem.getAttribute(type);
2952
+ if(i === 0) {
2953
+ gPaint = p;
2954
+ } else if(gPaint !== p) {
2955
+ gPaint = null;
2956
+ break;
2957
+ }
2958
+ }
2959
+ if(gPaint === null) {
2960
+ // No common color, don't update anything
2961
+ var paintColor = null;
2962
+ return;
2963
+ }
2964
+ var paintColor = gPaint;
2965
+
2966
+ var paintOpacity = 1;
2967
+ break;
2968
+ default:
2969
+ var paintOpacity = parseFloat(selectedElement.getAttribute(type + "-opacity"));
2970
+ if (isNaN(paintOpacity)) {
2971
+ paintOpacity = 1.0;
2972
+ }
2973
+
2974
+ var defColor = type === "fill" ? "black" : "none";
2975
+ var paintColor = selectedElement.getAttribute(type) || defColor;
2976
+ }
2977
+ if(apply) {
2978
+ svgCanvas.setColor(type, paintColor, true);
2979
+ svgCanvas.setPaintOpacity(type, paintOpacity, true);
2980
+ }
2981
+
2982
+ paintOpacity *= 100;
2983
+
2984
+ var paint = getPaint(paintColor, paintOpacity, type);
2985
+ // update the rect inside #fill_color/#stroke_color
2986
+ this.setPaint(paint);
2987
+ }
2988
+
2989
+ this.prep = function() {
2990
+ var ptype = this.paint.type;
2991
+
2992
+ switch ( ptype ) {
2993
+ case 'linearGradient':
2994
+ case 'radialGradient':
2995
+ var paint = new $.jGraduate.Paint({copy: this.paint});
2996
+ svgCanvas.setPaint(type, paint);
2997
+ }
2998
+ }
2999
+ };
3000
+
3001
+ Editor.paintBox.fill = new PaintBox('#fill_color', 'fill');
3002
+ Editor.paintBox.stroke = new PaintBox('#stroke_color', 'stroke');
3003
+ Editor.paintBox.canvas = new PaintBox('#canvas_color', 'canvas');
3004
+
3005
+ $('#stroke_width').val(curConfig.initStroke.width);
3006
+ $('#group_opacity').val(curConfig.initOpacity * 100);
3007
+
3008
+ // Use this SVG elem to test vectorEffect support
3009
+ var test_el = Editor.paintBox.fill.rect.cloneNode(false);
3010
+ test_el.setAttribute('style','vector-effect:non-scaling-stroke');
3011
+ var supportsNonSS = (test_el.style.vectorEffect === 'non-scaling-stroke');
3012
+ test_el.removeAttribute('style');
3013
+ var svgdocbox = Editor.paintBox.fill.rect.ownerDocument;
3014
+ // Use this to test support for blur element. Seems to work to test support in Webkit
3015
+ var blur_test = svgdocbox.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
3016
+ if(typeof blur_test.stdDeviationX === "undefined") {
3017
+ $('#tool_blur').hide();
3018
+ }
3019
+ $(blur_test).remove();
3020
+
3021
+
3022
+
3023
+ // Test for embedImage support (use timeout to not interfere with page load)
3024
+ setTimeout(function() {
3025
+ svgCanvas.embedImage('images/placeholder.svg', function(datauri) {
3026
+ if(!datauri) {
3027
+ // Disable option
3028
+ $('#image_save_opts [value=embed]').attr('disabled','disabled');
3029
+ $('#image_save_opts input').val(['ref']);
3030
+ curPrefs.img_save = 'ref';
3031
+ $('#image_opt_embed').css('color','#666').attr('title',uiStrings.notification.featNotSupported);
3032
+ }
3033
+ });
3034
+ },1000);
3035
+
3036
+ $('#tool_fill').click(function(){
3037
+ if ($('#tool_fill').hasClass('active')) {
3038
+ colorPicker($('#fill_color'));
3039
+ }
3040
+ else {
3041
+ $('#tool_fill').addClass('active');
3042
+ $("#tool_stroke").removeClass('active');
3043
+ }
3044
+ });
3045
+
3046
+ $('#tool_stroke').on("click", function(){
3047
+ if ($('#tool_stroke').hasClass('active')) {
3048
+ colorPicker($('#stroke_color'));
3049
+ }
3050
+ else {
3051
+ $('#tool_stroke').addClass('active');
3052
+ $("#tool_fill").removeClass('active');
3053
+ }
3054
+ });
3055
+
3056
+ $('#tool_canvas').on("click touchstart", function(){
3057
+ colorPicker($('#canvas_color'));
3058
+ });
3059
+
3060
+ $('#tool_stroke').on("touchstart", function(){
3061
+ $('#tool_stroke').addClass('active');
3062
+ $("#tool_fill").removeClass('active');
3063
+ colorPicker($('#stroke_color'));
3064
+ });
3065
+
3066
+ $('#tool_fill').on("touchstart", function(){
3067
+ $('#tool_fill').addClass('active');
3068
+ $("#tool_stroke").removeClass('active');
3069
+ colorPicker($('#fill_color'));
3070
+ });
3071
+
3072
+ $('#zoom_select').on("change", function() {
3073
+ var val = this.options[this.selectedIndex].text
3074
+ val = val.split("%")[0]
3075
+ $("#zoom").val(val).trigger("change")
3076
+ });
3077
+
3078
+ $('.push_button').mousedown(function() {
3079
+ if (!$(this).hasClass('disabled')) {
3080
+ $(this).addClass('push_button_pressed').removeClass('push_button');
3081
+ }
3082
+ }).mouseout(function() {
3083
+ $(this).removeClass('push_button_pressed').addClass('push_button');
3084
+ }).mouseup(function() {
3085
+ $(this).removeClass('push_button_pressed').addClass('push_button');
3086
+ });
3087
+
3088
+
3089
+ // function changeResolution(x,y) {
3090
+ // var zoom = svgCanvas.getResolution().zoom;
3091
+ // setResolution(x * zoom, y * zoom);
3092
+ // }
3093
+
3094
+ var centerCanvas = function() {
3095
+ // this centers the canvas vertically in the workarea (horizontal handled in CSS)
3096
+ workarea.css('line-height', workarea.height() + 'px');
3097
+ };
3098
+
3099
+ $(window).bind('load resize', centerCanvas);
3100
+
3101
+ function stepFontSize(elem, step) {
3102
+ var orig_val = elem.value-0;
3103
+ var sug_val = orig_val + step;
3104
+ var increasing = sug_val >= orig_val;
3105
+ if(step === 0) return orig_val;
3106
+
3107
+ if(orig_val >= 24) {
3108
+ if(increasing) {
3109
+ return Math.round(orig_val * 1.1);
3110
+ } else {
3111
+ return Math.round(orig_val / 1.1);
3112
+ }
3113
+ } else if(orig_val <= 1) {
3114
+ if(increasing) {
3115
+ return orig_val * 2;
3116
+ } else {
3117
+ return orig_val / 2;
3118
+ }
3119
+ } else {
3120
+ return sug_val;
3121
+ }
3122
+ }
3123
+
3124
+ function stepZoom(elem, step) {
3125
+ var orig_val = elem.value-0;
3126
+ if(orig_val === 0) return 100;
3127
+ var sug_val = orig_val + step;
3128
+ if(step === 0) return orig_val;
3129
+
3130
+ if(orig_val >= 100) {
3131
+ return sug_val;
3132
+ } else {
3133
+ if(sug_val >= orig_val) {
3134
+ return orig_val * 2;
3135
+ } else {
3136
+ return orig_val / 2;
3137
+ }
3138
+ }
3139
+ }
3140
+
3141
+ var changeCanvasSize = function(ctl){
3142
+ var width = $("#canvas_width");
3143
+ var height = $("#canvas_height");
3144
+ var w = width.val();
3145
+ var h = height.val()
3146
+
3147
+ if(w != "fit" && !svgedit.units.isValidUnit('width', w)) {
3148
+ $.alert(uiStrings.notification.invalidAttrValGiven);
3149
+ width.parent().addClass('error');
3150
+ return false;
3151
+ }
3152
+
3153
+ width.parent().removeClass('error');
3154
+
3155
+ if(h != "fit" && !svgedit.units.isValidUnit('height', h)) {
3156
+ $.alert(uiStrings.notification.invalidAttrValGiven);
3157
+ height.parent().addClass('error');
3158
+ return false;
3159
+ }
3160
+ height.parent().removeClass('error');
3161
+ if(!svgCanvas.setResolution(w, h)) {
3162
+ $.alert(uiStrings.notification.noContentToFitTo);
3163
+ var dims = svgCanvas.getResolution()
3164
+ width.val(dims.w)
3165
+ height.val(dims.h)
3166
+ return false;
3167
+ }
3168
+ updateCanvas();
3169
+ }
3170
+
3171
+
3172
+ $('#resolution').change(function(){
3173
+ var w = $('#canvas_width')[0];
3174
+ var h = $('#canvas_height')[0];
3175
+ if(!this.selectedIndex) {
3176
+ $('#resolution_label').html("Custom");
3177
+ w.removeAttribute("readonly");
3178
+ w.focus();
3179
+ w.select();
3180
+ if(w.value == 'fit') {
3181
+ w.value = 100
3182
+ h.value = 100
3183
+ }
3184
+ } else if(this.value == 'content') {
3185
+ w.value = 'fit'
3186
+ h.value = 'fit'
3187
+ changeCanvasSize();
3188
+ var res = svgCanvas.getResolution()
3189
+ w.value = res.w
3190
+ h.value = res.h
3191
+
3192
+ } else {
3193
+ var dims = this.value.split('x');
3194
+ dims[0] = parseInt(dims[0]);
3195
+ dims[1] = parseInt(dims[1]);
3196
+ var diff_w = dims[0] - w.value;
3197
+ var diff_h = dims[1] - h.value;
3198
+ //animate
3199
+ var start = Date.now();
3200
+ var duration = 1000;
3201
+ var animateCanvasSize = function(timestamp) {
3202
+ var progress = Date.now() - start;
3203
+ var tick = progress / duration;
3204
+ tick = (Math.pow((tick-1), 3) +1);
3205
+ w.value = (dims[0] - diff_w + (tick*diff_w)).toFixed(0);
3206
+ h.value = (dims[1] - diff_h + (tick*diff_h)).toFixed(0);
3207
+ changeCanvasSize();
3208
+ if (tick >= 1) {
3209
+ var res = svgCanvas.getResolution()
3210
+ $('#canvas_width').val(res.w.toFixed())
3211
+ $('#canvas_height').val(res.h.toFixed())
3212
+ $('#resolution_label').html("<div class='pull'>" + res.w + "<span>×</span></br>" + res.h + "</div>");
3213
+ }
3214
+ else {
3215
+ requestAnimationFrame(animateCanvasSize)
3216
+ }
3217
+ }
3218
+ animateCanvasSize()
3219
+
3220
+ }
3221
+ });
3222
+
3223
+ $('#zoom').change(function(){
3224
+ changeZoom(this)
3225
+ })
3226
+
3227
+ //Prevent browser from erroneously repopulating fields
3228
+ $('input,select').attr("autocomplete","off");
3229
+
3230
+ // Associate all button actions as well as non-button keyboard shortcuts
3231
+ var Actions = function() {
3232
+ // sel:'selector', fn:function, evt:'event', key:[key, preventDefault, NoDisableInInput]
3233
+ var tool_buttons = [
3234
+ {sel:'#tool_select', fn: clickSelect, evt: 'click', key: ['V', true]},
3235
+ {sel:'#tool_fhpath', fn: clickFHPath, evt: 'click', key: ['Q', true]},
3236
+ {sel:'#tool_line', fn: clickLine, evt: 'click', key: ['L', true]},
3237
+ {sel:'#tool_rect', fn: clickRect, evt: 'click', key: ['R', true], icon: 'rect'},
3238
+ {sel:'#tool_ellipse', fn: clickEllipse, evt: 'mouseup', key: ['C', true], icon: 'ellipse'},
3239
+ //{sel:'#tool_circle', fn: clickCircle, evt: 'mouseup', icon: 'circle'},
3240
+ //{sel:'#tool_fhellipse', fn: clickFHEllipse, evt: 'mouseup', parent: '#tools_ellipse', icon: 'fh_ellipse'},
3241
+ {sel:'#tool_path', fn: clickPath, evt: 'click', key: ['P', true]},
3242
+ {sel:'#tool_text', fn: clickText, evt: 'click', key: ['T', true]},
3243
+ {sel:'#tool_image', fn: clickImage, evt: 'mouseup'},
3244
+ {sel:'#tool_zoom', fn: clickZoom, evt: 'mouseup', key: ['Z', true]},
3245
+ {sel:'#tool_clear', fn: clickClear, evt: 'mouseup', key: [modKey + 'N', true]},
3246
+ {sel:'#tool_save', fn: function() { editingsource?saveSourceEditor():clickSave()}, evt: 'mouseup', key: [modKey + 'S', true]},
3247
+ {sel:'#tool_export', fn: clickExport, evt: 'mouseup'},
3248
+ {sel:'#tool_open', fn: clickOpen, evt: 'mouseup'},
3249
+ {sel:'#tool_import', fn: clickImport, evt: 'mouseup'},
3250
+ {sel:'#tool_source', fn: showSourceEditor, evt: 'click', key: [modKey + 'U', true]},
3251
+ {sel:'#tool_wireframe', fn: clickWireframe, evt: 'click'},
3252
+ {sel:'#tool_snap', fn: clickSnapGrid, evt: 'click'},
3253
+ {sel:'#tool_rulers', fn: clickRulers, evt: 'click'},
3254
+ {sel:'#tool_source_cancel,#svg_source_overlay,#tool_docprops_cancel,#tool_prefs_cancel', fn: cancelOverlays, evt: 'click', key: ['esc', false, false], hidekey: true},
3255
+ {sel:'#tool_source_save', fn: saveSourceEditor, evt: 'click'},
3256
+ {sel:'#tool_delete,#tool_delete_multi', fn: deleteSelected, evt: 'click', key: ['del/backspace', true]},
3257
+ {sel:'#tool_reorient', fn: reorientPath, evt: 'click'},
3258
+ {sel:'#tool_node_link', fn: linkControlPoints, evt: 'change'},
3259
+ {sel:'#tool_node_clone', fn: clonePathNode, evt: 'click'},
3260
+ {sel:'#tool_node_delete', fn: deletePathNode, evt: 'click'},
3261
+ {sel:'#tool_openclose_path', fn: opencloseSubPath, evt: 'click'},
3262
+ {sel:'#tool_add_subpath', fn: addSubPath, evt: 'click'},
3263
+ {sel:'#tool_move_top', fn: moveToTopSelected, evt: 'click', key: modKey + 'shift+up'},
3264
+ {sel:'#tool_move_bottom', fn: moveToBottomSelected, evt: 'click', key: modKey + 'shift+down'},
3265
+ {sel:'#tool_move_up', fn: moveUpSelected, evt:'click', key: [modKey+'up', true]},
3266
+ {sel:'#tool_move_down', fn: moveDownSelected, evt:'click', key: [modKey+'down', true]},
3267
+ {sel:'#tool_topath', fn: convertToPath, evt: 'click'},
3268
+ {sel:'#tool_make_link,#tool_make_link_multi', fn: makeHyperlink, evt: 'click'},
3269
+ {sel:'#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: [modKey + 'D', true]},
3270
+ {sel:'#tool_group', fn: clickGroup, evt: 'click', key: [modKey + 'G', true]},
3271
+ {sel:'#tool_ungroup', fn: clickGroup, evt: 'click', key: modKey + 'shift+G'},
3272
+ {sel:'#tool_unlink_use', fn: clickGroup, evt: 'click'},
3273
+ {sel:'[id^=tool_align]', fn: clickAlign, evt: 'click'},
3274
+ {sel:'#tool_undo', fn: clickUndo, evt: 'click', key: modKey + 'z'},
3275
+ {sel:'#tool_redo', fn: clickRedo, evt: 'click', key: ['y', true]},
3276
+ {sel:'#tool_cut', fn: cutSelected, evt: 'click', key: [modKey+'x', true]},
3277
+ {sel:'#tool_copy', fn: copySelected, evt: 'click', key: modKey+'c'},
3278
+ {sel:'#tool_paste', fn: pasteSelected, evt: 'click', key: modKey+'v'},
3279
+ {sel:'#tool_switch', fn: clickSwitch, evt: 'click', key: ['x', true]},
3280
+ {sel:'#tool_bold', fn: clickBold, evt: 'mousedown', key: [modKey + 'B', true]},
3281
+ {sel:'#tool_italic', fn: clickItalic, evt: 'mousedown', key: [modKey + 'I', true]},
3282
+ //{sel:'#sidepanel_handle', fn: toggleSidePanel, key: ['X']},
3283
+ {sel:'#copy_save_done', fn: cancelOverlays, evt: 'click'},
3284
+
3285
+ // Shortcuts not associated with buttons
3286
+
3287
+ {key: 'ctrl+left', fn: function(){rotateSelected(0,1)}},
3288
+ {key: 'ctrl+right', fn: function(){rotateSelected(1,1)}},
3289
+ {key: 'ctrl+shift+left', fn: function(){rotateSelected(0,5)}},
3290
+ {key: 'ctrl+shift+right', fn: function(){rotateSelected(1,5)}},
3291
+ {key: 'shift+O', fn: selectPrev},
3292
+ {key: 'shift+P', fn: selectNext},
3293
+ {key: [modKey+'+', true], fn: function(){zoomImage(2);}},
3294
+ {key: [modKey+'-', true], fn: function(){zoomImage(.5);}},
3295
+ {key: ['up', true], fn: function(){moveSelected(0,-1);}},
3296
+ {key: ['down', true], fn: function(){moveSelected(0,1);}},
3297
+ {key: ['left', true], fn: function(){moveSelected(-1,0);}},
3298
+ {key: ['right', true], fn: function(){moveSelected(1,0);}},
3299
+ {key: 'shift+up', fn: function(){moveSelected(0,-10)}},
3300
+ {key: 'shift+down', fn: function(){moveSelected(0,10)}},
3301
+ {key: 'shift+left', fn: function(){moveSelected(-10,0)}},
3302
+ {key: 'shift+right', fn: function(){moveSelected(10,0)}},
3303
+ {key: ['alt+up', true], fn: function(){svgCanvas.cloneSelectedElements(0,-1)}},
3304
+ {key: ['alt+down', true], fn: function(){svgCanvas.cloneSelectedElements(0,1)}},
3305
+ {key: ['alt+left', true], fn: function(){svgCanvas.cloneSelectedElements(-1,0)}},
3306
+ {key: ['alt+right', true], fn: function(){svgCanvas.cloneSelectedElements(1,0)}},
3307
+ {key: ['alt+shift+up', true], fn: function(){svgCanvas.cloneSelectedElements(0,-10)}},
3308
+ {key: ['alt+shift+down', true], fn: function(){svgCanvas.cloneSelectedElements(0,10)}},
3309
+ {key: ['alt+shift+left', true], fn: function(){svgCanvas.cloneSelectedElements(-10,0)}},
3310
+ {key: ['alt+shift+right', true], fn: function(){svgCanvas.cloneSelectedElements(10,0)}},
3311
+ {key: modKey + 'A', fn: function(){svgCanvas.selectAllInCurrentLayer();}},
3312
+ {key: 'I', fn: function(){setEyedropperMode()}},
3313
+
3314
+ // Standard shortcuts
3315
+ {key: modKey + 'shift+z', fn: clickRedo},
3316
+ {key: 'esc', fn: minimizeModal}
3317
+ ];
3318
+
3319
+ // Tooltips not directly associated with a single function
3320
+ var key_assocs = {
3321
+ '4/Shift+4': '#tools_rect_show',
3322
+ '5/Shift+5': '#tools_ellipse_show'
3323
+ };
3324
+
3325
+ return {
3326
+ setAll: function() {
3327
+ var flyouts = {};
3328
+
3329
+ $.each(tool_buttons, function(i, opts) {
3330
+ // Bind function to button
3331
+ if(opts.sel) {
3332
+ var btn = $(opts.sel);
3333
+ if (btn.length == 0) return true; // Skip if markup does not exist
3334
+ if(opts.evt) {
3335
+ if (svgedit.browser.isTouch() && opts.evt === "click") opts.evt = "mousedown"
3336
+ btn[opts.evt](opts.fn);
3337
+ }
3338
+
3339
+ // Add to parent flyout menu, if able to be displayed
3340
+ if(opts.parent && $(opts.parent + '_show').length != 0) {
3341
+ var f_h = $(opts.parent);
3342
+ if(!f_h.length) {
3343
+ f_h = makeFlyoutHolder(opts.parent.substr(1));
3344
+ }
3345
+
3346
+ f_h.append(btn);
3347
+
3348
+ if(!$.isArray(flyouts[opts.parent])) {
3349
+ flyouts[opts.parent] = [];
3350
+ }
3351
+ flyouts[opts.parent].push(opts);
3352
+ }
3353
+ }
3354
+
3355
+
3356
+ // Bind function to shortcut key
3357
+ if(opts.key) {
3358
+ // Set shortcut based on options
3359
+ var keyval, shortcut = '', disInInp = true, fn = opts.fn, pd = false;
3360
+ if($.isArray(opts.key)) {
3361
+ keyval = opts.key[0];
3362
+ if(opts.key.length > 1) pd = opts.key[1];
3363
+ if(opts.key.length > 2) disInInp = opts.key[2];
3364
+ } else {
3365
+ keyval = opts.key;
3366
+ }
3367
+ keyval += '';
3368
+ if (svgedit.browser.isMac && keyval.indexOf("+") != -1) {
3369
+ var modifier_key = keyval.split("+")[0];
3370
+ if (modifier_key == "ctrl") keyval.replace("ctrl", "cmd")
3371
+ }
3372
+
3373
+ $.each(keyval.split('/'), function(i, key) {
3374
+ $(document).bind('keydown', key, function(e) {
3375
+ fn();
3376
+ if(pd) {
3377
+ e.preventDefault();
3378
+ }
3379
+ // Prevent default on ALL keys?
3380
+ return false;
3381
+ });
3382
+ });
3383
+
3384
+ // Put shortcut in title
3385
+ if(opts.sel && !opts.hidekey && btn.attr('title')) {
3386
+ var new_title = btn.attr('title').split('[')[0] + ' (' + keyval + ')';
3387
+ key_assocs[keyval] = opts.sel;
3388
+ // Disregard for menu items
3389
+ if(!btn.parents('#main_menu').length) {
3390
+ btn.attr('title', new_title);
3391
+ }
3392
+ }
3393
+ }
3394
+ });
3395
+
3396
+ // Setup flyouts
3397
+ setupFlyouts(flyouts);
3398
+
3399
+ $(window).bind('keydown', 'tab', function(e) {
3400
+ if(ui_context === 'canvas') {
3401
+ e.preventDefault();
3402
+ selectNext();
3403
+ }
3404
+ }).bind('keydown', 'shift+tab', function(e) {
3405
+ if(ui_context === 'canvas') {
3406
+ e.preventDefault();
3407
+ selectPrev();
3408
+ }
3409
+ });
3410
+
3411
+ $('#tool_zoom').dblclick(dblclickZoom);
3412
+ },
3413
+ setTitles: function() {
3414
+ $.each(key_assocs, function(keyval, sel) {
3415
+ var menu = ($(sel).parents('#main_menu').length);
3416
+
3417
+ $(sel).each(function() {
3418
+ if(menu) {
3419
+ var t = $(this).text().split(' [')[0];
3420
+ } else {
3421
+ var t = this.title.split(' [')[0];
3422
+ }
3423
+ var key_str = '';
3424
+ // Shift+Up
3425
+ $.each(keyval.split('/'), function(i, key) {
3426
+ var mod_bits = key.split('+'), mod = '';
3427
+ if(mod_bits.length > 1) {
3428
+ mod = mod_bits[0] + '+';
3429
+ key = mod_bits[1];
3430
+ }
3431
+ key_str += (i?'/':'') + mod + (uiStrings['key_'+key] || key);
3432
+ });
3433
+ if(menu) {
3434
+ this.lastChild.textContent = t +' ['+key_str+']';
3435
+ } else {
3436
+ this.title = t +' ['+key_str+']';
3437
+ }
3438
+ });
3439
+ });
3440
+ },
3441
+ getButtonData: function(sel) {
3442
+ var b;
3443
+ $.each(tool_buttons, function(i, btn) {
3444
+ if(btn.sel === sel) b = btn;
3445
+ });
3446
+ return b;
3447
+ }
3448
+ };
3449
+ }();
3450
+
3451
+ Actions.setAll();
3452
+
3453
+ // Select given tool
3454
+ Editor.ready(function() {
3455
+ var tool,
3456
+ itool = curConfig.initTool,
3457
+ container = $("#tools_left, #svg_editor .tools_flyout"),
3458
+ pre_tool = container.find("#tool_" + itool),
3459
+ reg_tool = container.find("#" + itool);
3460
+ if(pre_tool.length) {
3461
+ tool = pre_tool;
3462
+ } else if(reg_tool.length){
3463
+ tool = reg_tool;
3464
+ } else {
3465
+ tool = $("#tool_select");
3466
+ }
3467
+ tool.click().mouseup();
3468
+
3469
+ if(curConfig.wireframe) {
3470
+ $('#tool_wireframe').click();
3471
+ }
3472
+
3473
+ if(curConfig.showlayers) {
3474
+ toggleSidePanel();
3475
+ }
3476
+
3477
+ $('#rulers').toggle(!!curConfig.showRulers);
3478
+ });
3479
+
3480
+
3481
+ $('#canvas_height').dragInput({ min: 10, max: null, step: 10, callback: changeCanvasSize, cursor: false, dragAdjust: .1 });
3482
+ $('#canvas_width') .dragInput({ min: 10, max: null, step: 10, callback: changeCanvasSize, cursor: false, dragAdjust: .1 });
3483
+ $('#rect_width') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3484
+ $('#rect_height') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3485
+ $('#ellipse_cx') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3486
+ $('#ellipse_cy') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3487
+ $('#ellipse_rx') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3488
+ $('#ellipse_ry') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3489
+ $("#image_height") .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3490
+ $('#circle_cx') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3491
+ $('#circle_cy') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3492
+ $('#circle_r') .dragInput({ min: 1, max: null, step: 1, callback: changeAttribute, cursor: false });
3493
+ $("#image_height") .dragInput({ min: 0, max: null, step: 1, callback: changeAttribute, cursor: false });
3494
+ $('#selected_x') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3495
+ $('#selected_y') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3496
+ $("#path_node_x") .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3497
+ $("#path_node_y") .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3498
+ $("#image_width") .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3499
+ $('#line_x1') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3500
+ $('#line_x2') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3501
+ $('#line_y1') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3502
+ $('#line_y2') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3503
+ $('#path_x') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3504
+ $('#path_y') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3505
+ $('#rect_x') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3506
+ $('#rect_y') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3507
+ $('#g_x') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3508
+ $('#g_y') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3509
+ $('#image_x') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3510
+ $('#text_y') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3511
+ $('#text_x') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3512
+ $('#image_y') .dragInput({ min: null, max: null, step: 1, callback: changeAttribute, cursor: false });
3513
+ $('#rect_rx') .dragInput({ min: 0, max: 100, step: 1, callback: changeAttribute, cursor: true });
3514
+ $('#stroke_width') .dragInput({ min: 0, max: 99, step: 1, callback: changeStrokeWidth, cursor: true, smallStep: 0.1, start: 1.5 });
3515
+ $('#angle') .dragInput({ min: -180, max: 180, step: 1, callback: changeRotationAngle, cursor: false, dragAdjust: 0.5 });
3516
+ $('#font_size') .dragInput({ min: 1, max: 250, step: 1, callback: changeFontSize, cursor: true, stepfunc: stepFontSize, dragAdjust: .15 });
3517
+ $('#group_opacity').dragInput({ min: 0, max: 100, step: 5, callback: changeAttribute, cursor: true, start: 100 });
3518
+ $('#blur') .dragInput({ min: 0, max: 10, step: .1, callback: changeBlur, cursor: true, start: 0 });
3519
+ // Set default zoom
3520
+ $('#zoom').val(svgCanvas.getZoom() * 100);
3521
+
3522
+ $("#workarea").contextMenu({
3523
+ menu: 'cmenu_canvas',
3524
+ inSpeed: 0
3525
+ },
3526
+ function(action, el, pos) {
3527
+ switch ( action ) {
3528
+ case 'delete':
3529
+ deleteSelected();
3530
+ break;
3531
+ case 'cut':
3532
+ cutSelected();
3533
+ break;
3534
+ case 'copy':
3535
+ copySelected();
3536
+ break;
3537
+ case 'paste':
3538
+ svgCanvas.pasteElements();
3539
+ break;
3540
+ case 'paste_in_place':
3541
+ svgCanvas.pasteElements('in_place');
3542
+ break;
3543
+ case 'group':
3544
+ svgCanvas.groupSelectedElements();
3545
+ break;
3546
+ case 'ungroup':
3547
+ svgCanvas.ungroupSelectedElement();
3548
+ break;
3549
+ case 'move_front':
3550
+ moveToTopSelected();
3551
+ break;
3552
+ case 'move_up':
3553
+ moveUpDownSelected('Up');
3554
+ break;
3555
+ case 'move_down':
3556
+ moveUpDownSelected('Down');
3557
+ break;
3558
+ case 'move_back':
3559
+ moveToBottomSelected();
3560
+ break;
3561
+ default:
3562
+ if(svgedit.contextmenu && svgedit.contextmenu.hasCustomHandler(action)){
3563
+ svgedit.contextmenu.getCustomHandler(action).call();
3564
+ }
3565
+ break;
3566
+ }
3567
+
3568
+ });
3569
+
3570
+ $('.contextMenu li').mousedown(function(ev) {
3571
+ ev.preventDefault();
3572
+ })
3573
+
3574
+ $('#cmenu_canvas li').disableContextMenu();
3575
+ canv_menu.enableContextMenuItems('#delete,#cut,#copy');
3576
+
3577
+ window.onbeforeunload = function() {
3578
+ // Suppress warning if page is empty
3579
+ if(undoMgr.getUndoStackSize() === 0) {
3580
+ Editor.show_save_warning = false;
3581
+ }
3582
+
3583
+ // show_save_warning is set to "false" when the page is saved.
3584
+ if(!curConfig.no_save_warning && Editor.show_save_warning) {
3585
+ // Browser already asks question about closing the page
3586
+ return uiStrings.notification.unsavedChanges;
3587
+ }
3588
+ };
3589
+
3590
+ Editor.openPrep = function(func) {
3591
+ $('#main_menu').hide();
3592
+ if(undoMgr.getUndoStackSize() === 0) {
3593
+ func(true);
3594
+ } else {
3595
+ $.confirm(uiStrings.notification.QwantToOpen, func);
3596
+ }
3597
+ }
3598
+
3599
+ if (window.FileReader) {
3600
+
3601
+ var import_image = function(e) {
3602
+ e.stopPropagation();
3603
+ e.preventDefault();
3604
+ $("#workarea").removeAttr("style");
3605
+ $('#main_menu').hide();
3606
+ var file = null;
3607
+ if (e.type == "drop") file = e.dataTransfer.files[0]
3608
+ else file = this.files[0];
3609
+ if (file) {
3610
+ if(file.type.indexOf("image") != -1) {
3611
+ //detected an image
3612
+
3613
+ //svg handing
3614
+ if(file.type.indexOf("svg") != -1) {
3615
+ var reader = new FileReader();
3616
+ reader.onloadend = function(e) {
3617
+ svgCanvas.importSvgString(e.target.result, true);
3618
+ svgCanvas.ungroupSelectedElement()
3619
+ svgCanvas.ungroupSelectedElement()
3620
+ svgCanvas.groupSelectedElements()
3621
+ svgCanvas.alignSelectedElements("m", "page")
3622
+ svgCanvas.alignSelectedElements("c", "page")
3623
+ };
3624
+ reader.readAsText(file);
3625
+ }
3626
+
3627
+ //image handling
3628
+ else {
3629
+ var reader = new FileReader();
3630
+ reader.onloadend = function(e) {
3631
+ // lets insert the new image until we know its dimensions
3632
+ insertNewImage = function(img_width, img_height){
3633
+ var newImage = svgCanvas.addSvgElementFromJson({
3634
+ "element": "image",
3635
+ "attr": {
3636
+ "x": 0,
3637
+ "y": 0,
3638
+ "width": img_width,
3639
+ "height": img_height,
3640
+ "id": svgCanvas.getNextId(),
3641
+ "style": "pointer-events:inherit"
3642
+ }
3643
+ });
3644
+ svgCanvas.setHref(newImage, e.target.result);
3645
+ svgCanvas.selectOnly([newImage])
3646
+ svgCanvas.alignSelectedElements("m", "page")
3647
+ svgCanvas.alignSelectedElements("c", "page")
3648
+ updateContextPanel();
3649
+ }
3650
+ // put a placeholder img so we know the default dimensions
3651
+ var img_width = 100;
3652
+ var img_height = 100;
3653
+ var img = new Image()
3654
+ img.src = e.target.result
3655
+ document.body.appendChild(img);
3656
+ img.onload = function() {
3657
+ img_width = img.offsetWidth
3658
+ img_height = img.offsetHeight
3659
+ insertNewImage(img_width, img_height);
3660
+ document.body.removeChild(img);
3661
+ }
3662
+ };
3663
+ reader.readAsDataURL(file)
3664
+ }
3665
+ }
3666
+ }
3667
+ }
3668
+
3669
+ var workarea = $("#workarea")
3670
+
3671
+ function onDragEnter(e) {
3672
+ e.stopPropagation();
3673
+ e.preventDefault();
3674
+ workarea.css({
3675
+ "-webkit-transform": "scale3d(1.1,1.1,1)",
3676
+ "-moz-transform": "scale3d(1.1,1.1,1)",
3677
+ "-o-transform": "scale(1.1)",
3678
+ "-ms-transform": "scale3d(1.1,1.1,1)",
3679
+ "transform": "scale3d(1.1,1.1,1)"
3680
+ })
3681
+
3682
+ }
3683
+
3684
+ function onDragOver(e) {
3685
+ e.stopPropagation();
3686
+ e.preventDefault();
3687
+ }
3688
+
3689
+ function onDragLeave(e) {
3690
+ workarea.removeAttr("style")
3691
+ e.stopPropagation();
3692
+ e.preventDefault();
3693
+ }
3694
+
3695
+ workarea[0].addEventListener('dragenter', onDragEnter, false);
3696
+ workarea[0].addEventListener('dragover', onDragOver, false);
3697
+ workarea[0].addEventListener('dragleave', onDragLeave, false);
3698
+ workarea[0].addEventListener('drop', import_image, false);
3699
+
3700
+ var open = $('<input type="file">').change(function() {
3701
+ var f = this;
3702
+ Editor.openPrep(function(ok) {
3703
+ if(!ok) return;
3704
+ svgCanvas.clear();
3705
+ if(f.files.length==1) {
3706
+ var reader = new FileReader();
3707
+ reader.onloadend = function(e) {
3708
+ loadSvgString(e.target.result);
3709
+ updateCanvas();
3710
+ };
3711
+ reader.readAsText(f.files[0]);
3712
+ }
3713
+ });
3714
+ });
3715
+ $("#tool_open").show().prepend(open);
3716
+
3717
+ var img_import = $('<input type="file">').change(import_image);
3718
+ $("#tool_import").show().prepend(img_import);
3719
+ }
3720
+
3721
+
3722
+ var updateCanvas = Editor.updateCanvas = function(center, new_ctr) {
3723
+ var w = workarea.width(), h = workarea.height();
3724
+ var w_orig = w, h_orig = h;
3725
+ var zoom = svgCanvas.getZoom();
3726
+ var w_area = workarea;
3727
+ var cnvs = $("#svgcanvas");
3728
+
3729
+ var old_ctr = {
3730
+ x: w_area[0].scrollLeft + w_orig/2,
3731
+ y: w_area[0].scrollTop + h_orig/2
3732
+ };
3733
+
3734
+ var multi = curConfig.canvas_expansion;
3735
+ w = Math.max(w_orig, svgCanvas.contentW * zoom * multi);
3736
+ h = Math.max(h_orig, svgCanvas.contentH * zoom * multi);
3737
+
3738
+ if(w == w_orig && h == h_orig) {
3739
+ workarea.css('overflow','hidden');
3740
+ } else {
3741
+ workarea.css('overflow','scroll');
3742
+ }
3743
+
3744
+ var old_can_y = cnvs.height()/2;
3745
+ var old_can_x = cnvs.width()/2;
3746
+ cnvs.width(w).height(h);
3747
+ var new_can_y = h/2;
3748
+ var new_can_x = w/2;
3749
+ var offset = svgCanvas.updateCanvas(w, h);
3750
+
3751
+ var ratio = new_can_x / old_can_x;
3752
+
3753
+ var scroll_x = w/2 - w_orig/2;
3754
+ var scroll_y = h/2 - h_orig/2;
3755
+
3756
+ if(!new_ctr) {
3757
+
3758
+ var old_dist_x = old_ctr.x - old_can_x;
3759
+ var new_x = new_can_x + old_dist_x * ratio;
3760
+
3761
+ var old_dist_y = old_ctr.y - old_can_y;
3762
+ var new_y = new_can_y + old_dist_y * ratio;
3763
+
3764
+ new_ctr = {
3765
+ x: new_x,
3766
+ y: new_y
3767
+ };
3768
+
3769
+ } else {
3770
+ new_ctr.x += offset.x,
3771
+ new_ctr.y += offset.y;
3772
+ }
3773
+
3774
+ //width.val(offset.x)
3775
+ //height.val(offset.y)
3776
+
3777
+ if(center) {
3778
+ // Go to top-left for larger documents
3779
+ if(svgCanvas.contentW > w_area.width()) {
3780
+ // Top-left
3781
+ workarea[0].scrollLeft = offset.x - 10;
3782
+ workarea[0].scrollTop = offset.y - 10;
3783
+ } else {
3784
+ // Center
3785
+ w_area[0].scrollLeft = scroll_x;
3786
+ w_area[0].scrollTop = scroll_y;
3787
+ }
3788
+ } else {
3789
+ w_area[0].scrollLeft = new_ctr.x - w_orig/2;
3790
+ w_area[0].scrollTop = new_ctr.y - h_orig/2;
3791
+ }
3792
+ if(curConfig.showRulers) {
3793
+ updateRulers(cnvs, zoom);
3794
+ workarea.scroll();
3795
+ }
3796
+ }
3797
+
3798
+ // Make [1,2,5] array
3799
+ var r_intervals = [];
3800
+ for(var i = .1; i < 1E5; i *= 10) {
3801
+ r_intervals.push(1 * i);
3802
+ r_intervals.push(2 * i);
3803
+ r_intervals.push(5 * i);
3804
+ }
3805
+
3806
+ function updateRulers(scanvas, zoom) {
3807
+ var workarea = document.getElementById("workarea");
3808
+ var title_show = document.getElementById("title_show");
3809
+ var offset_x = 66;
3810
+ var offset_y = 48;
3811
+ if(!zoom) zoom = svgCanvas.getZoom();
3812
+ if(!scanvas) scanvas = $("#svgcanvas");
3813
+
3814
+ var limit = 30000;
3815
+
3816
+ var c_elem = svgCanvas.getContentElem();
3817
+
3818
+ var units = svgedit.units.getTypeMap();
3819
+ var unit = units[curConfig.baseUnit]; // 1 = 1px
3820
+
3821
+ for(var d = 0; d < 2; d++) {
3822
+ var is_x = (d === 0);
3823
+ var dim = is_x ? 'x' : 'y';
3824
+ var lentype = is_x?'width':'height';
3825
+ var content_d = c_elem.getAttribute(dim)-0;
3826
+
3827
+ var $hcanv_orig = $('#ruler_' + dim + ' canvas:first');
3828
+
3829
+ // Bit of a hack to fully clear the canvas in Safari & IE9
3830
+ $hcanv = $hcanv_orig.clone();
3831
+ $hcanv_orig.replaceWith($hcanv);
3832
+
3833
+ var hcanv = $hcanv[0];
3834
+
3835
+ // Set the canvas size to the width of the container
3836
+ var ruler_len = scanvas[lentype]()*2;
3837
+ var total_len = ruler_len;
3838
+ hcanv.parentNode.style[lentype] = total_len + 'px';
3839
+
3840
+ var canv_count = 1;
3841
+ var ctx_num = 0;
3842
+ var ctx_arr;
3843
+ var ctx = hcanv.getContext("2d");
3844
+
3845
+ ctx.fillStyle = "rgb(200,0,0)";
3846
+ ctx.fillRect(0,0,hcanv.width,hcanv.height);
3847
+
3848
+ // Remove any existing canvasses
3849
+ $hcanv.siblings().remove();
3850
+
3851
+ // Create multiple canvases when necessary (due to browser limits)
3852
+ if(ruler_len >= limit) {
3853
+ var num = parseInt(ruler_len / limit) + 1;
3854
+ ctx_arr = Array(num);
3855
+ ctx_arr[0] = ctx;
3856
+ for(var i = 1; i < num; i++) {
3857
+ hcanv[lentype] = limit;
3858
+ var copy = hcanv.cloneNode(true);
3859
+ hcanv.parentNode.appendChild(copy);
3860
+ ctx_arr[i] = copy.getContext('2d');
3861
+ }
3862
+
3863
+ copy[lentype] = ruler_len % limit;
3864
+
3865
+ // set copy width to last
3866
+ ruler_len = limit;
3867
+ }
3868
+
3869
+ hcanv[lentype] = ruler_len;
3870
+
3871
+ var u_multi = unit * zoom;
3872
+
3873
+ // Calculate the main number interval
3874
+ var raw_m = 50 / u_multi;
3875
+ var multi = 1;
3876
+ for(var i = 0; i < r_intervals.length; i++) {
3877
+ var num = r_intervals[i];
3878
+ multi = num;
3879
+ if(raw_m <= num) {
3880
+ break;
3881
+ }
3882
+ }
3883
+
3884
+ var big_int = multi * u_multi;
3885
+ ctx.font = "normal 9px 'Lucida Grande', sans-serif";
3886
+ ctx.fillStyle = "#777";
3887
+
3888
+ var ruler_d = ((content_d / u_multi) % multi) * u_multi;
3889
+ var label_pos = ruler_d - big_int;
3890
+ for (; ruler_d < total_len; ruler_d += big_int) {
3891
+ label_pos += big_int;
3892
+ var real_d = ruler_d - content_d;
3893
+
3894
+ var cur_d = Math.round(ruler_d) + .5;
3895
+ if(is_x) {
3896
+ ctx.moveTo(cur_d, 15);
3897
+ ctx.lineTo(cur_d, 0);
3898
+ } else {
3899
+ ctx.moveTo(15, cur_d);
3900
+ ctx.lineTo(0, cur_d);
3901
+ }
3902
+
3903
+ var num = (label_pos - content_d) / u_multi;
3904
+ var label;
3905
+ if(multi >= 1) {
3906
+ label = Math.round(num);
3907
+ } else {
3908
+ var decs = (multi+'').split('.')[1].length;
3909
+ label = num.toFixed(decs)-0;
3910
+ }
3911
+
3912
+ // Do anything special for negative numbers?
3913
+ // var is_neg = label < 0;
3914
+ // real_d2 = Math.abs(real_d2);
3915
+
3916
+ // Change 1000s to Ks
3917
+ if(label !== 0 && label !== 1000 && label % 1000 === 0) {
3918
+ label = (label / 1000) + 'K';
3919
+ }
3920
+
3921
+ if(is_x) {
3922
+ ctx.fillText(label, ruler_d+2, 8);
3923
+ ctx.fillStyle = "#777";
3924
+ } else {
3925
+ var str = (label+'').split('');
3926
+ for(var i = 0; i < str.length; i++) {
3927
+ ctx.fillText(str[i], 1, (ruler_d+9) + i*9);
3928
+ ctx.fillStyle = "#777";
3929
+ }
3930
+ }
3931
+
3932
+ var part = big_int / 10;
3933
+ for(var i = 1; i < 10; i++) {
3934
+ var sub_d = Math.round(ruler_d + part * i) + .5;
3935
+ if(ctx_arr && sub_d > ruler_len) {
3936
+ ctx_num++;
3937
+ ctx.stroke();
3938
+ if(ctx_num >= ctx_arr.length) {
3939
+ i = 10;
3940
+ ruler_d = total_len;
3941
+ continue;
3942
+ }
3943
+ ctx = ctx_arr[ctx_num];
3944
+ ruler_d -= limit;
3945
+ sub_d = Math.round(ruler_d + part * i) + .5;
3946
+ }
3947
+
3948
+ var line_num = (i % 2)?12:10;
3949
+ if(is_x) {
3950
+ ctx.moveTo(sub_d, 15);
3951
+ ctx.lineTo(sub_d, line_num);
3952
+ } else {
3953
+ ctx.moveTo(15, sub_d);
3954
+ ctx.lineTo(line_num ,sub_d);
3955
+ }
3956
+ }
3957
+ }
3958
+ ctx.strokeStyle = "#666";
3959
+ ctx.stroke();
3960
+ }
3961
+ }
3962
+
3963
+ // $(function() {
3964
+ updateCanvas(true);
3965
+ // });
3966
+
3967
+ // var revnums = "svg-editor.js ($Rev: 2083 $) ";
3968
+ // revnums += svgCanvas.getVersion();
3969
+ // $('#copyright')[0].setAttribute("title", revnums);
3970
+
3971
+ // Callback handler for embedapi.js
3972
+ try{
3973
+ var json_encode = function(obj){
3974
+ //simple partial JSON encoder implementation
3975
+ if(window.JSON && JSON.stringify) return JSON.stringify(obj);
3976
+ var enc = arguments.callee; //for purposes of recursion
3977
+ if(typeof obj == "boolean" || typeof obj == "number"){
3978
+ return obj+'' //should work...
3979
+ }else if(typeof obj == "string"){
3980
+ //a large portion of this is stolen from Douglas Crockford's json2.js
3981
+ return '"'+
3982
+ obj.replace(
3983
+ /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g
3984
+ , function (a) {
3985
+ return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
3986
+ })
3987
+ +'"'; //note that this isn't quite as purtyful as the usualness
3988
+ }else if(obj.length){ //simple hackish test for arrayish-ness
3989
+ for(var i = 0; i < obj.length; i++){
3990
+ obj[i] = enc(obj[i]); //encode every sub-thingy on top
3991
+ }
3992
+ return "["+obj.join(",")+"]";
3993
+ }else{
3994
+ var pairs = []; //pairs will be stored here
3995
+ for(var k in obj){ //loop through thingys
3996
+ pairs.push(enc(k)+":"+enc(obj[k])); //key: value
3997
+ }
3998
+ return "{"+pairs.join(",")+"}" //wrap in the braces
3999
+ }
4000
+ }
4001
+ window.addEventListener("message", function(e){
4002
+ var cbid = parseInt(e.data.substr(0, e.data.indexOf(";")));
4003
+ try{
4004
+ e.source.postMessage("SVGe"+cbid+";"+json_encode(eval(e.data)), "*");
4005
+ }catch(err){
4006
+ e.source.postMessage("SVGe"+cbid+";error:"+err.message, "*");
4007
+ }
4008
+ }, false)
4009
+ }catch(err){
4010
+ window.embed_error = err;
4011
+ }
4012
+
4013
+
4014
+
4015
+ // For Compatibility with older extensions
4016
+ $(function() {
4017
+ window.svgCanvas = svgCanvas;
4018
+ svgCanvas.ready = methodDraw.ready;
4019
+ });
4020
+
4021
+
4022
+ Editor.setLang = function(lang, allStrings) {
4023
+ $.pref('lang', lang);
4024
+ $('#lang_select').val(lang);
4025
+ if(allStrings) {
4026
+
4027
+ var notif = allStrings.notification;
4028
+
4029
+ svgCanvas.runExtensions("langChanged", lang);
4030
+
4031
+ // Update flyout tooltips
4032
+ setFlyoutTitles();
4033
+
4034
+ // Copy title for certain tool elements
4035
+ var elems = {
4036
+ '#stroke_color': '#tool_stroke .icon_label, #tool_stroke .color_block',
4037
+ '#fill_color': '#tool_fill label, #tool_fill .color_block',
4038
+ '#linejoin_miter': '#cur_linejoin',
4039
+ '#linecap_butt': '#cur_linecap'
4040
+ }
4041
+
4042
+ $.each(elems, function(source, dest) {
4043
+ $(dest).attr('title', $(source)[0].title);
4044
+ });
4045
+
4046
+ // Copy alignment titles
4047
+ $('#multiselected_panel div[id^=tool_align]').each(function() {
4048
+ $('#tool_pos' + this.id.substr(10))[0].title = this.title;
4049
+ });
4050
+
4051
+ }
4052
+ };
4053
+ };
4054
+
4055
+ var callbacks = [];
4056
+
4057
+ function loadSvgString(str, callback) {
4058
+ var success = svgCanvas.setSvgString(str) !== false;
4059
+ callback = callback || $.noop;
4060
+ if(success) {
4061
+ callback(true);
4062
+ } else {
4063
+ $.alert(uiStrings.notification.errorLoadingSVG, function() {
4064
+ callback(false);
4065
+ });
4066
+ }
4067
+ }
4068
+
4069
+ Editor.ready = function(cb) {
4070
+ if(!is_ready) {
4071
+ callbacks.push(cb);
4072
+ } else {
4073
+ cb();
4074
+ }
4075
+ };
4076
+
4077
+ Editor.runCallbacks = function() {
4078
+ $.each(callbacks, function() {
4079
+ this();
4080
+ });
4081
+ is_ready = true;
4082
+ };
4083
+
4084
+ Editor.loadFromString = function(str) {
4085
+ Editor.ready(function() {
4086
+ loadSvgString(str);
4087
+ });
4088
+ };
4089
+
4090
+ Editor.loadFromURL = function(url, opts) {
4091
+ if(!opts) opts = {};
4092
+
4093
+ var cache = opts.cache;
4094
+ var cb = opts.callback;
4095
+
4096
+ Editor.ready(function() {
4097
+ $.ajax({
4098
+ 'url': url,
4099
+ 'dataType': 'text',
4100
+ cache: !!cache,
4101
+ success: function(str) {
4102
+ loadSvgString(str, cb);
4103
+ },
4104
+ error: function(xhr, stat, err) {
4105
+ if(xhr.status != 404 && xhr.responseText) {
4106
+ loadSvgString(xhr.responseText, cb);
4107
+ } else {
4108
+ $.alert(uiStrings.notification.URLloadFail + ": \n"+err+'', cb);
4109
+ }
4110
+ }
4111
+ });
4112
+ });
4113
+ };
4114
+
4115
+ Editor.loadFromDataURI = function(str) {
4116
+ Editor.ready(function() {
4117
+ var pre = 'data:image/svg+xml;base64,';
4118
+ var src = str.substring(pre.length);
4119
+ loadSvgString(svgedit.utilities.decode64(src));
4120
+ });
4121
+ };
4122
+
4123
+ Editor.addExtension = function() {
4124
+ var args = arguments;
4125
+
4126
+ // Note that we don't want this on Editor.ready since some extensions
4127
+ // may want to run before then (like server_opensave).
4128
+ $(function() {
4129
+ if(svgCanvas) svgCanvas.addExtension.apply(this, args);
4130
+ });
4131
+ };
4132
+
4133
+ return Editor;
4134
+ }(jQuery);
4135
+
4136
+ // Run init once DOM is loaded
4137
+ $(methodDraw.init);
4138
+
4139
+
4140
+ })();