diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index dcb640a1..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve - ---- - -### Preflight Checklist - - -* [ ] I agree to follow the [Code of Conduct](https://github.com/jgraph/drawio/blob/master/CODE_OF_CONDUCT.md) that this project adheres to. -* [ ] I have searched the issue tracker for a feature request that matches the one I want to file, without success. - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**draw.io version (In the Help->About menu of the draw.io editor):** - -- draw.io version [e.g. 12.6.7] - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 4dd11042..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project - ---- - -* [ ] I agree to follow the [Code of Conduct](https://github.com/jgraph/drawio/blob/master/CODE_OF_CONDUCT.md) that this project adheres to. -* [ ] I have searched the issue tracker for a feature request that matches the one I want to file, without success. - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 9db1c0d5..00000000 --- a/.github/stale.yml +++ /dev/null @@ -1,18 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 100 -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 2 -# Issues with these labels will never be considered stale -exemptLabels: - - pinned - - security - - notstale -# Label to use when marking an issue as stale -staleLabel: wontfix -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. See [the FAQ](https://github.com/jgraph/drawio/wiki/Stale-bot-FAQ) for more information. -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: false diff --git a/.github/workflows/war.yml b/.github/workflows/war.yml deleted file mode 100644 index 7ded4116..00000000 --- a/.github/workflows/war.yml +++ /dev/null @@ -1,45 +0,0 @@ -# This workflow will build a Java project with Ant -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-ant - -name: WAR CI - -on: - push: - tags: - - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build war with Ant - run: | - cd etc/build - ant war - - name: Create Release - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} - draft: false - prerelease: false - - name: Upload Release Asset - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: build/draw.war - asset_name: draw.war - asset_content_type: application/octet-stream diff --git a/etc/build/cache.txt b/etc/build/cache.txt deleted file mode 100644 index b856f045..00000000 --- a/etc/build/cache.txt +++ /dev/null @@ -1,59 +0,0 @@ -app.html -index.html?offline=1 -index.html?offline=1&ui=min -index.html?offline=1&https=0 -offline.html -open.html -js/app.min.js -js/shapes.min.js -js/stencils.min.js -js/extensions.min.js -js/diagramly/ElectronApp.js -styles/grapheditor.css -styles/atlas.css -styles/dark.css -favicon.ico -mxgraph/css/common.css -mxgraph/images/maximize.gif -mxgraph/images/minimize.gif -mxgraph/images/close.gif -mxgraph/images/resize.gif -mxgraph/images/separator.gif -mxgraph/images/window.gif -mxgraph/images/window-title.gif -mxgraph/images/button.gif -mxgraph/images/point.gif -resources/dia.txt -images/delete.png -images/droptarget.png -images/help.png -images/download.png -images/drawlogo.svg -images/drawlogo-gray.svg -images/drawlogo-text-bottom.svg -images/logo-flat.png -images/osa_drive-harddisk.png -images/osa_database.png -images/glyphicons_star.png -images/logo-confluence.png -images/logo-jira.png -images/clear.gif -images/spin.gif -images/checkmark.gif -images/favicon-16x16.png -images/favicon-32x32.png -images/android-chrome-192x192.png -images/android-chrome-512x512.png -images/glyphicons_google.png -images/glyphicons_facebook.png -images/glyphicons_twitter.png -images/glyphicons_github.png -images/hs.png - -# Redirect app to app.html which redirects to index.html?offline=1 -# this is required to get the URL parameters into the index page. -FALLBACK: -app app.html - -NETWORK: -* diff --git a/etc/docker/Dockerfile b/etc/docker/Dockerfile deleted file mode 100644 index d5d11bee..00000000 --- a/etc/docker/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM frekele/ant:1.10.3-jdk8 as BUILD -RUN mkdir /usr/build -COPY src /usr/build/src -COPY etc /usr/build/etc -COPY VERSION /usr/build -RUN cd /usr/build/etc/build/ && ant war - -FROM tomcat:9.0 as TARGET -COPY --from=BUILD /usr/build/build/draw.war /usr/local/tomcat/webapps/ -EXPOSE 8080 -CMD ["catalina.sh", "run"] diff --git a/etc/docker/drawio-export/Dockerfile b/etc/docker/drawio-export/Dockerfile deleted file mode 100644 index 88895bea..00000000 --- a/etc/docker/drawio-export/Dockerfile +++ /dev/null @@ -1,61 +0,0 @@ -FROM tomcat:9-jre11-slim - -LABEL maintainer="Florian JUDITH " - -ARG VERSION=11.3.0 - -RUN apt-get update -y && \ - apt-get install -y --no-install-recommends \ - openjdk-11-jdk-headless ant git patch wget xmlstarlet certbot curl && \ - curl -sL https://deb.nodesource.com/setup_12.x | bash - && \ - apt-get install -y --no-install-recommends nodejs chromium libatk-bridge2.0-0 libgtk-3-0 && \ - cd /tmp && \ - wget https://github.com/jgraph/draw.io/archive/v${VERSION}.zip && \ - unzip v${VERSION}.zip && \ - cd /tmp/drawio-${VERSION} && \ - cd /tmp/drawio-${VERSION}/etc/build && \ - ant war && \ - cd /tmp/drawio-${VERSION}/build && \ - unzip /tmp/drawio-${VERSION}/build/draw.war -d $CATALINA_HOME/webapps/draw && \ - mkdir /usr/local/drawio && \ - cd /usr/local/drawio && \ - git clone https://github.com/jgraph/draw-image-export2.git && \ - cd draw-image-export2 && \ - npm install && \ - apt-get remove -y --purge openjdk-11-jdk-headless ant git patch wget && \ - apt-get autoremove -y --purge && \ - apt-get remove -y --purge chromium && \ - apt-get clean && \ - rm -r /var/lib/apt/lists/* && \ - rm -rf \ - /tmp/v${VERSION}.zip \ - /tmp/drawio-${VERSION} - -COPY PreConfig.js PostConfig.js $CATALINA_HOME/webapps/draw/js/ - -# Update server.xml to set Draw.io webapp to root -RUN cd $CATALINA_HOME && \ - xmlstarlet ed \ - -P -S -L \ - -i '/Server/Service/Engine/Host/Valve' -t 'elem' -n 'Context' \ - -i '/Server/Service/Engine/Host/Context' -t 'attr' -n 'path' -v '/' \ - -i '/Server/Service/Engine/Host/Context[@path="/"]' -t 'attr' -n 'docBase' -v 'draw' \ - -s '/Server/Service/Engine/Host/Context[@path="/"]' -t 'elem' -n 'WatchedResource' -v 'WEB-INF/web.xml' \ - -i '/Server/Service/Engine/Host/Valve' -t 'elem' -n 'Context' \ - -i '/Server/Service/Engine/Host/Context[not(@path="/")]' -t 'attr' -n 'path' -v '/ROOT' \ - -s '/Server/Service/Engine/Host/Context[@path="/ROOT"]' -t 'attr' -n 'docBase' -v 'ROOT' \ - -s '/Server/Service/Engine/Host/Context[@path="/ROOT"]' -t 'elem' -n 'WatchedResource' -v 'WEB-INF/web.xml' \ - conf/server.xml - - -# Copy docker-entrypoint -COPY docker-entrypoint.sh / -RUN chmod +x /docker-entrypoint.sh - -WORKDIR $CATALINA_HOME - -#If export server is not used outside draw.io, no need to expose port 8000 -EXPOSE 8080 8443 8000 - -ENTRYPOINT ["/docker-entrypoint.sh"] -CMD ["catalina.sh", "run"] diff --git a/etc/docker/drawio-export/PostConfig.js b/etc/docker/drawio-export/PostConfig.js deleted file mode 100644 index df894c28..00000000 --- a/etc/docker/drawio-export/PostConfig.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright (c) 2006-2019, JGraph Ltd - * Copyright (c) 2006-2019, draw.io AG - */ -// null'ing of global vars need to be after init.js -window.VSD_CONVERT_URL = null; -window.EMF_CONVERT_URL = null; -window.ICONSEARCH_PATH = null; \ No newline at end of file diff --git a/etc/docker/drawio-export/PreConfig.js b/etc/docker/drawio-export/PreConfig.js deleted file mode 100644 index e18621d7..00000000 --- a/etc/docker/drawio-export/PreConfig.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) 2006-2019, JGraph Ltd - * Copyright (c) 2006-2019, draw.io AG - */ -// Overrides of global vars need to be pre-loaded -window.EXPORT_URL = '/export'; //This points to ExportProxyServlet which uses the local export server at port 8000. - //This proxy configuration allows https requests to the export server via Tomcat. -window.PLANT_URL = 'REPLACE_WITH_YOUR_PLANTUML_SERVER'; -window.DRAW_MATH_URL = 'math'; -window.DRAWIO_CONFIG = null; //Replace with your custom draw.io configurations. For more details, https://desk.draw.io/support/solutions/articles/16000058316 \ No newline at end of file diff --git a/etc/docker/drawio-export/docker-entrypoint.sh b/etc/docker/drawio-export/docker-entrypoint.sh deleted file mode 100644 index 0e830980..00000000 --- a/etc/docker/drawio-export/docker-entrypoint.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash -#set -e - -LETS_ENCRYPT_ENABLED=${LETS_ENCRYPT_ENABLED:-false} -PUBLIC_DNS=${PUBLIC_DNS:-'draw.example.com'} -ORGANISATION_UNIT=${ORGANIZATION_UNIT:-'Cloud Native Application'} -ORGANISATION=${ORGANISATION:-'example inc'} -CITY=${CITY:-'Paris'} -STATE=${STATE:-'Paris'} -COUNTRY_CODE=${COUNTRY:-'FR'} -KEYSTORE_PASS=${KEYSTORE_PASS:-'V3ry1nS3cur3P4ssw0rd'} -KEY_PASS=${KEY_PASS:-$KEYSTORE_PASS} - - -if ! [ -f $CATALINA_HOME/.keystore ] && [ "$LETS_ENCRYPT_ENABLED" == "true" ]; then - echo "Generating Let's Encrypt certificate" - - keytool -genkey -noprompt -alias tomcat -dname "CN=${PUBLIC_DNS}, OU=${ORGANISATION_UNIT}, O=${ORGANISATION}, L=${CITY}, S=${STATE}, C=${COUNTRY_CODE}" -keystore $CATALINA_HOME/.keystore -storepass "${KEYSTORE_PASS}" -KeySize 2048 -keypass "${KEY_PASS}" -keyalg RSA -storetype pkcs12 - - keytool -list -keystore $CATALINA_HOME/.keystore -v -storepass "${KEYSTORE_PASS}" - - keytool -certreq -alias tomcat -file request.csr -keystore $CATALINA_HOME/.keystore -storepass "${KEYSTORE_PASS}" - - certbot certonly --csr $CATALINA_HOME/request.csr --standalone --register-unsafely-without-email --agree-tos - - keytool -import -trustcacerts -alias tomcat -file 0001_chain.pem -keystore $CATALINA_HOME/.keystore -storepass "${KEYSTORE_PASS}" -fi - -if ! [ -f $CATALINA_HOME/.keystore ] && [ "$LETS_ENCRYPT_ENABLED" == "false" ]; then - echo "Generating Self-Signed certificate" - - keytool -genkey -noprompt -alias selfsigned -dname "CN=${PUBLIC_DNS}, OU=${ORGANISATION_UNIT}, O=${ORGANISATION}, L=${CITY}, S=${STATE}, C=${COUNTRY_CODE}" -keystore $CATALINA_HOME/.keystore -storepass "${KEYSTORE_PASS}" -KeySize 2048 -keypass "${KEY_PASS}" -keyalg RSA -validity 3600 -storetype pkcs12 - - keytool -list -keystore $CATALINA_HOME/.keystore -v -storepass "${KEYSTORE_PASS}" -fi - -# Update SSL port configuration if it does'nt exists -# -UUID="$(cat /dev/urandom | tr -dc 'a-zA-Z' | fold -w 1 | head -n 1)$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 7 | head -n 1)" -VAR=$(cat conf/server.xml | grep "$CATALINA_HOME/.keystore") - -if [ -f $CATALINA_HOME/.keystore ] && [ -z $VAR ]; then - echo "Append https connector to server.xml" - - xmlstarlet ed \ - -P -S -L \ - -s '/Server/Service' -t 'elem' -n "${UUID}" \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'port' -v '8443' \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'protocol' -v 'org.apache.coyote.http11.Http11NioProtocol' \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'SSLEnabled' -v 'true' \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'maxThreads' -v '150' \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'scheme' -v 'https' \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'secure' -v 'true' \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'clientAuth' -v 'false' \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'sslProtocol' -v 'TLS' \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'KeystoreFile' -v "$CATALINA_HOME/.keystore" \ - -i "/Server/Service/${UUID}" -t 'attr' -n 'KeystorePass' -v "${KEY_PASS}" \ - -r "/Server/Service/${UUID}" -v 'Connector' \ - conf/server.xml -fi - -#Run the export server -cd /usr/local/drawio/draw-image-export2 -npm start & -cd $CATALINA_HOME - -exec "$@" \ No newline at end of file diff --git a/src/main/mxgraph/css/common.css b/src/main/mxgraph/css/common.css deleted file mode 100644 index 21f38921..00000000 --- a/src/main/mxgraph/css/common.css +++ /dev/null @@ -1,166 +0,0 @@ -div.mxRubberband { - position: absolute; - overflow: hidden; - border-style: solid; - border-width: 1px; - border-color: #0000FF; - background: #0077FF; -} -.mxCellEditor { - background: url(data:image/gif;base64,R0lGODlhMAAwAIAAAP///wAAACH5BAEAAAAALAAAAAAwADAAAAIxhI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8egpAAA7); - _background: url('../images/transparent.gif'); - border-color: transparent; - border-style: solid; - display: inline-block; - position: absolute; - overflow: visible; - word-wrap: normal; - border-width: 0; - min-width: 1px; - resize: none; - padding: 0px; - margin: 0px; -} -.mxPlainTextEditor * { - padding: 0px; - margin: 0px; -} -div.mxWindow { - -webkit-box-shadow: 3px 3px 12px #C0C0C0; - -moz-box-shadow: 3px 3px 12px #C0C0C0; - box-shadow: 3px 3px 12px #C0C0C0; - background: url(data:image/gif;base64,R0lGODlhGgAUAIAAAOzs7PDw8CH5BAAAAAAALAAAAAAaABQAAAIijI+py70Ao5y02lud3lzhD4ZUR5aPiKajyZbqq7YyB9dhAQA7); - _background: url('../images/window.gif'); - border:1px solid #c3c3c3; - position: absolute; - overflow: hidden; - z-index: 1; -} -table.mxWindow { - border-collapse: collapse; - table-layout: fixed; - font-family: Arial; - font-size: 8pt; -} -td.mxWindowTitle { - background: url(data:image/gif;base64,R0lGODlhFwAXAMQAANfX18rKyuHh4c7OzsDAwMHBwc/Pz+Li4uTk5NHR0dvb2+jo6O/v79/f3/n5+dnZ2dbW1uPj44yMjNPT0+Dg4N3d3ebm5szMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAXABcAAAWQICESxWiW5Ck6bOu+MMvMdG3f86LvfO/rlqBwSCwaj8ikUohoOp/QaDNCrVqvWKpgezhsv+AwmEIum89ocmPNbrvf64p8Tq/b5Yq8fs/v5x+AgYKDhIAAh4iJiouHEI6PkJGSjhOVlpeYmZUJnJ2en6CcBqMDpaanqKgXq6ytrq+rAbKztLW2shK5uru8vbkhADs=) repeat-x; - _background: url('../images/window-title.gif') repeat-x; - text-overflow: ellipsis; - white-space: nowrap; - text-align: center; - font-weight: bold; - overflow: hidden; - height: 13px; - padding: 2px; - padding-top: 4px; - padding-bottom: 6px; - color: black; -} -td.mxWindowPane { - vertical-align: top; - padding: 0px; -} -div.mxWindowPane { - overflow: hidden; - position: relative; -} -td.mxWindowPane td { - font-family: Arial; - font-size: 8pt; -} -td.mxWindowPane input, td.mxWindowPane select, td.mxWindowPane textarea, td.mxWindowPane radio { - border-color: #8C8C8C; - border-style: solid; - border-width: 1px; - font-family: Arial; - font-size: 8pt; - padding: 1px; -} -td.mxWindowPane button { - background: url(data:image/gif;base64,R0lGODlhCgATALMAAP7+/t7e3vj4+Ojo6OXl5e/v7/n5+fb29vPz8/39/e3t7fHx8e7u7v///wAAAAAAACH5BAAAAAAALAAAAAAKABMAAAQ2MMlJhb0Y6c2X/2AhjiRjnqiirizqMkEsz0Rt30Ou7y8K/ouDcEg0GI9IgHLJbDif0Kh06owAADs=) repeat-x; - _background: url('../images/button.gif') repeat-x; - font-family: Arial; - font-size: 8pt; - padding: 2px; - float: left; -} -img.mxToolbarItem { - margin-right: 6px; - margin-bottom: 6px; - border-width: 1px; -} -select.mxToolbarCombo { - vertical-align: top; - border-style: inset; - border-width: 2px; -} -div.mxToolbarComboContainer { - padding: 2px; -} -img.mxToolbarMode { - margin: 2px; - margin-right: 4px; - margin-bottom: 4px; - border-width: 0px; -} -img.mxToolbarModeSelected { - margin: 0px; - margin-right: 2px; - margin-bottom: 2px; - border-width: 2px; - border-style: inset; -} -div.mxTooltip { - -webkit-box-shadow: 3px 3px 12px #C0C0C0; - -moz-box-shadow: 3px 3px 12px #C0C0C0; - box-shadow: 3px 3px 12px #C0C0C0; - background: #FFFFCC; - border-style: solid; - border-width: 1px; - border-color: black; - font-family: Arial; - font-size: 8pt; - position: absolute; - cursor: default; - padding: 4px; - color: black; -} -div.mxPopupMenu { - -webkit-box-shadow: 3px 3px 12px #C0C0C0; - -moz-box-shadow: 3px 3px 12px #C0C0C0; - box-shadow: 3px 3px 12px #C0C0C0; - background: url(data:image/gif;base64,R0lGODlhGgAUAIAAAOzs7PDw8CH5BAAAAAAALAAAAAAaABQAAAIijI+py70Ao5y02lud3lzhD4ZUR5aPiKajyZbqq7YyB9dhAQA7); - _background: url('../images/window.gif'); - position: absolute; - border-style: solid; - border-width: 1px; - border-color: black; -} -table.mxPopupMenu { - border-collapse: collapse; - margin-top: 1px; - margin-bottom: 1px; -} -tr.mxPopupMenuItem { - color: black; - cursor: pointer; -} -tr.mxPopupMenuItemHover { - background-color: #000066; - color: #FFFFFF; - cursor: pointer; -} -td.mxPopupMenuItem { - padding: 2px 30px 2px 10px; - white-space: nowrap; - font-family: Arial; - font-size: 8pt; -} -td.mxPopupMenuIcon { - background-color: #D0D0D0; - padding: 2px 4px 2px 4px; -} -.mxDisabled { - opacity: 0.2 !important; - cursor:default !important; -} diff --git a/src/main/mxgraph/css/explorer.css b/src/main/mxgraph/css/explorer.css deleted file mode 100644 index 50e704fe..00000000 --- a/src/main/mxgraph/css/explorer.css +++ /dev/null @@ -1,18 +0,0 @@ -div.mxTooltip { - filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4, - Color='#A2A2A2', Positive='true'); -} -div.mxPopupMenu { - filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4, - Color='#C0C0C0', Positive='true'); -} -div.mxWindow { - _filter:progid:DXImageTransform.Microsoft.DropShadow(OffX=4, OffY=4, - Color='#C0C0C0', Positive='true'); -} -td.mxWindowTitle { - _height: 23px; -} -.mxDisabled { - filter:alpha(opacity=20) !important; -} diff --git a/src/main/mxgraph/images/button.gif b/src/main/mxgraph/images/button.gif deleted file mode 100644 index ad55cab6..00000000 Binary files a/src/main/mxgraph/images/button.gif and /dev/null differ diff --git a/src/main/mxgraph/images/close.gif b/src/main/mxgraph/images/close.gif deleted file mode 100644 index 1069e94b..00000000 Binary files a/src/main/mxgraph/images/close.gif and /dev/null differ diff --git a/src/main/mxgraph/images/collapsed.gif b/src/main/mxgraph/images/collapsed.gif deleted file mode 100644 index 0276444a..00000000 Binary files a/src/main/mxgraph/images/collapsed.gif and /dev/null differ diff --git a/src/main/mxgraph/images/error.gif b/src/main/mxgraph/images/error.gif deleted file mode 100644 index 14e1aeef..00000000 Binary files a/src/main/mxgraph/images/error.gif and /dev/null differ diff --git a/src/main/mxgraph/images/expanded.gif b/src/main/mxgraph/images/expanded.gif deleted file mode 100644 index 3767b0ba..00000000 Binary files a/src/main/mxgraph/images/expanded.gif and /dev/null differ diff --git a/src/main/mxgraph/images/maximize.gif b/src/main/mxgraph/images/maximize.gif deleted file mode 100644 index e27cf3e1..00000000 Binary files a/src/main/mxgraph/images/maximize.gif and /dev/null differ diff --git a/src/main/mxgraph/images/minimize.gif b/src/main/mxgraph/images/minimize.gif deleted file mode 100644 index 1e95e7ca..00000000 Binary files a/src/main/mxgraph/images/minimize.gif and /dev/null differ diff --git a/src/main/mxgraph/images/normalize.gif b/src/main/mxgraph/images/normalize.gif deleted file mode 100644 index 34a8d302..00000000 Binary files a/src/main/mxgraph/images/normalize.gif and /dev/null differ diff --git a/src/main/mxgraph/images/point.gif b/src/main/mxgraph/images/point.gif deleted file mode 100644 index 9074c395..00000000 Binary files a/src/main/mxgraph/images/point.gif and /dev/null differ diff --git a/src/main/mxgraph/images/resize.gif b/src/main/mxgraph/images/resize.gif deleted file mode 100644 index ff558dba..00000000 Binary files a/src/main/mxgraph/images/resize.gif and /dev/null differ diff --git a/src/main/mxgraph/images/separator.gif b/src/main/mxgraph/images/separator.gif deleted file mode 100644 index 5c1b8956..00000000 Binary files a/src/main/mxgraph/images/separator.gif and /dev/null differ diff --git a/src/main/mxgraph/images/submenu.gif b/src/main/mxgraph/images/submenu.gif deleted file mode 100644 index ffe76176..00000000 Binary files a/src/main/mxgraph/images/submenu.gif and /dev/null differ diff --git a/src/main/mxgraph/images/transparent.gif b/src/main/mxgraph/images/transparent.gif deleted file mode 100644 index 76040f2b..00000000 Binary files a/src/main/mxgraph/images/transparent.gif and /dev/null differ diff --git a/src/main/mxgraph/images/warning.gif b/src/main/mxgraph/images/warning.gif deleted file mode 100644 index 705235f9..00000000 Binary files a/src/main/mxgraph/images/warning.gif and /dev/null differ diff --git a/src/main/mxgraph/images/warning.png b/src/main/mxgraph/images/warning.png deleted file mode 100644 index 2f787896..00000000 Binary files a/src/main/mxgraph/images/warning.png and /dev/null differ diff --git a/src/main/mxgraph/images/window-title.gif b/src/main/mxgraph/images/window-title.gif deleted file mode 100644 index 231def8b..00000000 Binary files a/src/main/mxgraph/images/window-title.gif and /dev/null differ diff --git a/src/main/mxgraph/images/window.gif b/src/main/mxgraph/images/window.gif deleted file mode 100644 index 6631c4f5..00000000 Binary files a/src/main/mxgraph/images/window.gif and /dev/null differ diff --git a/src/main/mxgraph/mxClient.js b/src/main/mxgraph/mxClient.js deleted file mode 100644 index 2a64732e..00000000 --- a/src/main/mxgraph/mxClient.js +++ /dev/null @@ -1,1803 +0,0 @@ -var mxClient={VERSION:"14.0.1",IS_IE:null!=navigator.userAgent&&0<=navigator.userAgent.indexOf("MSIE"),IS_IE6:null!=navigator.userAgent&&0<=navigator.userAgent.indexOf("MSIE 6"),IS_IE11:null!=navigator.userAgent&&!!navigator.userAgent.match(/Trident\/7\./),IS_EDGE:null!=navigator.userAgent&&!!navigator.userAgent.match(/Edge\//),IS_QUIRKS:null!=navigator.userAgent&&0<=navigator.userAgent.indexOf("MSIE")&&(null==document.documentMode||5==document.documentMode),IS_EM:"spellcheck"in document.createElement("textarea")&& -8==document.documentMode,VML_PREFIX:"v",OFFICE_PREFIX:"o",IS_NS:null!=navigator.userAgent&&0<=navigator.userAgent.indexOf("Mozilla/")&&0>navigator.userAgent.indexOf("MSIE")&&0>navigator.userAgent.indexOf("Edge/"),IS_OP:null!=navigator.userAgent&&(0<=navigator.userAgent.indexOf("Opera/")||0<=navigator.userAgent.indexOf("OPR/")),IS_OT:null!=navigator.userAgent&&0<=navigator.userAgent.indexOf("Presto/")&&0>navigator.userAgent.indexOf("Presto/2.4.")&&0>navigator.userAgent.indexOf("Presto/2.3.")&&0>navigator.userAgent.indexOf("Presto/2.2.")&& -0>navigator.userAgent.indexOf("Presto/2.1.")&&0>navigator.userAgent.indexOf("Presto/2.0.")&&0>navigator.userAgent.indexOf("Presto/1."),IS_SF:/Apple Computer, Inc/.test(navigator.vendor),IS_ANDROID:0<=navigator.appVersion.indexOf("Android"),IS_IOS:/iP(hone|od|ad)/.test(navigator.platform),IS_GC:/Google Inc/.test(navigator.vendor),IS_CHROMEAPP:null!=window.chrome&&null!=chrome.app&&null!=chrome.app.runtime,IS_FF:"undefined"!==typeof InstallTrigger,IS_MT:0<=navigator.userAgent.indexOf("Firefox/")&&0> -navigator.userAgent.indexOf("Firefox/1.")&&0>navigator.userAgent.indexOf("Firefox/2.")||0<=navigator.userAgent.indexOf("Iceweasel/")&&0>navigator.userAgent.indexOf("Iceweasel/1.")&&0>navigator.userAgent.indexOf("Iceweasel/2.")||0<=navigator.userAgent.indexOf("SeaMonkey/")&&0>navigator.userAgent.indexOf("SeaMonkey/1.")||0<=navigator.userAgent.indexOf("Iceape/")&&0>navigator.userAgent.indexOf("Iceape/1."),IS_VML:"MICROSOFT INTERNET EXPLORER"==navigator.appName.toUpperCase(),IS_SVG:"MICROSOFT INTERNET EXPLORER"!= -navigator.appName.toUpperCase(),NO_FO:!document.createElementNS||"[object SVGForeignObjectElement]"!=document.createElementNS("http://www.w3.org/2000/svg","foreignObject")||0<=navigator.userAgent.indexOf("Opera/"),IS_WIN:0document.location.href.indexOf("http://")&& -0>document.location.href.indexOf("https://"),defaultBundles:[],isBrowserSupported:function(){return mxClient.IS_VML||mxClient.IS_SVG},link:function(a,b,c,d){c=c||document;if(mxClient.IS_IE6)c.write('');else{var e=c.createElement("link");e.setAttribute("rel",a);e.setAttribute("href",b);e.setAttribute("charset","UTF-8");e.setAttribute("type","text/css");d&&e.setAttribute("id",d);c.getElementsByTagName("head")[0].appendChild(e)}},loadResources:function(a, -b){function c(){0==--d&&a()}for(var d=mxClient.defaultBundles.length,e=0;e\x3c/script>')}};"undefined"==typeof mxLoadResources&&(mxLoadResources=!0);"undefined"==typeof mxForceIncludes&&(mxForceIncludes=!1);"undefined"==typeof mxResourceExtension&&(mxResourceExtension=".txt");"undefined"==typeof mxLoadStylesheets&&(mxLoadStylesheets=!0); -"undefined"!=typeof mxBasePath&&0d&&g?(d++,window.setTimeout(e,f)):null!=c&&c()},f=30;e()},cascadeOpacity:function(a,b,c){for(var d=a.model.getChildCount(b),e=0;edocument.documentMode)?function(a){return null!=a?a.currentStyle:null}:function(a){return null!=a?window.getComputedStyle(a, -""):null}}(),parseCssNumber:function(a){"thin"==a?a="2":"medium"==a?a="4":"thick"==a&&(a="6");a=parseFloat(a);isNaN(a)&&(a=0);return a},setPrefixedStyle:function(){var a=null;mxClient.IS_OT?a="O":mxClient.IS_SF||mxClient.IS_GC?a="Webkit":mxClient.IS_MT?a="Moz":mxClient.IS_IE&&9<=document.documentMode&&10>document.documentMode&&(a="ms");return function(b,c,d){b[c]=d;null!=a&&0document.documentMode)?mxUtils.importNodeImplementation(a,b,c):a.importNode(b,c)},importNodeImplementation:function(a,b,c){switch(b.nodeType){case 1:var d=a.createElement(b.nodeName);if(b.attributes&&0/g,">");if(null==b||b)a=a.replace(/\n/g, -" ");return a},isVml:function(a){return null!=a&&"urn:schemas-microsoft-com:vml"==a.tagUrn},getXml:function(a,b){var c="";mxClient.IS_IE||mxClient.IS_IE11?c=mxUtils.getPrettyXml(a,"","",""):null!=window.XMLSerializer?c=(new XMLSerializer).serializeToString(a):null!=a.xml&&(c=a.xml.replace(/\r\n\t[\t]*/g,"").replace(/>\r\n/g,">").replace(/\r\n/g,"\n"));return c=c.replace(/\n/g,b||" ")},getPrettyXml:function(a,b,c,d,e){var f=[];if(null!=a)if(b=null!=b?b:" ",c=null!=c?c:"",d=null!=d?d:"\n", -null!=a.namespaceURI&&a.namespaceURI!=e&&(e=a.namespaceURI,null==a.getAttribute("xmlns")&&a.setAttribute("xmlns",a.namespaceURI)),a.nodeType==mxConstants.NODETYPE_DOCUMENT)f.push(mxUtils.getPrettyXml(a.documentElement,b,c,d,e));else if(a.nodeType==mxConstants.NODETYPE_DOCUMENT_FRAGMENT){var g=a.firstChild;if(null!=g)for(;null!=g;)f.push(mxUtils.getPrettyXml(g,b,c,d,e)),g=g.nextSibling}else if(a.nodeType==mxConstants.NODETYPE_COMMENT)a=mxUtils.getTextContent(a),0"+d);null!=g;)f.push(mxUtils.getPrettyXml(g, -b,c+b,d,e)),g=g.nextSibling;f.push(c+""+d)}else f.push(" />"+d)}return f.join("")},extractTextWithWhitespace:function(a){function b(a){if(1!=a.length||"BR"!=a[0].nodeName&&"\n"!=a[0].innerHTML)for(var e=0;e"==g.innerHTML.toLowerCase()?d.push("\n"):(3===g.nodeType||4===g.nodeType?0"):(b.push(">"),b.push(a.innerHTML),b.push(""));return b.join("")}return""}:function(a){return null!=a?(new XMLSerializer).serializeToString(a):""}}(),write:function(a,b){var c=a.ownerDocument.createTextNode(b);null!=a&&a.appendChild(c);return c},writeln:function(a,b){var c=a.ownerDocument.createTextNode(b);null!=a&&(a.appendChild(c),a.appendChild(document.createElement("br")));return c},br:function(a,b){b=b||1;for(var c=null, -d=0;dg&&(a.style.left=Math.max(f,g-d)+"px");c=parseInt(a.offsetTop);d=parseInt(a.offsetHeight);b=e+b.height;c+d>b&&(a.style.top=Math.max(e,b-d)+"px")},load:function(a){a=new mxXmlRequest(a,null, -"GET",!1);a.send();return a},get:function(a,b,c,d,e,f,g){a=new mxXmlRequest(a,null,"GET");var k=a.setRequestHeaders;g&&(a.setRequestHeaders=function(a,b){k.apply(this,arguments);for(var c in g)a.setRequestHeader(c,g[c])});null!=d&&a.setBinary(d);a.send(b,c,e,f);return a},getAll:function(a,b,c){for(var d=a.length,e=[],f=0,g=function(){0==f&&null!=c&&c();f++},k=0;kf||299mxUtils.indexOf(b,e))&&(d[e]=c||"object"!=typeof a[e]?a[e]:mxUtils.clone(a[e]))}return d},equalPoints:function(a,b){if(null==a&&null!=b||null!=a&&null==b||null!=a&&null!=b&&a.length!=b.length)return!1;if(null!=a&&null!=b)for(var c=0;c [Function]\n";else if("object"==typeof a[c])var d=mxUtils.getFunctionName(a[c].constructor),b=b+(c+" => ["+d+"]\n");else b+=c+" = "+a[c]+"\n"}catch(e){b+=c+"="+e.message}return b},toRadians:function(a){return Math.PI*a/180},toDegree:function(a){return 180*a/Math.PI},arcToCurves:function(a, -b,c,d,e,f,g,k,l){k-=a;l-=b;if(0===c||0===d)return q;c=Math.abs(c);d=Math.abs(d);var m=-k/2,n=-l/2,p=Math.cos(e*Math.PI/180),q=Math.sin(e*Math.PI/180);e=p*m+q*n;var m=-1*q*m+p*n,n=e*e,r=m*m,t=c*c,u=d*d,x=n/t+r/u;1e&&(e+=2*Math.PI);g=2*e/Math.PI;g=Math.ceil(0>g?-1*g:g);e/=g;m=8/3*Math.sin(e/4)*Math.sin(e/4)/Math.sin(e/2);n=p*c;p*=d;c*=q;d*=q;for(var y=Math.cos(f),B=Math.sin(f),r=-m*(n*B+d*y),t=-m*(c*B-p*y),q=[],A=0;Ac&&(a=3,-135>=c&&(a=2));if(0<=d.indexOf(mxConstants.DIRECTION_NORTH))switch(a){case 0:b|=mxConstants.DIRECTION_MASK_NORTH;break;case 1:b|=mxConstants.DIRECTION_MASK_EAST;break;case 2:b|=mxConstants.DIRECTION_MASK_SOUTH;break;case 3:b|=mxConstants.DIRECTION_MASK_WEST}if(0<=d.indexOf(mxConstants.DIRECTION_WEST))switch(a){case 0:b|=mxConstants.DIRECTION_MASK_WEST;break;case 1:b|=mxConstants.DIRECTION_MASK_NORTH; -break;case 2:b|=mxConstants.DIRECTION_MASK_EAST;break;case 3:b|=mxConstants.DIRECTION_MASK_SOUTH}if(0<=d.indexOf(mxConstants.DIRECTION_SOUTH))switch(a){case 0:b|=mxConstants.DIRECTION_MASK_SOUTH;break;case 1:b|=mxConstants.DIRECTION_MASK_WEST;break;case 2:b|=mxConstants.DIRECTION_MASK_NORTH;break;case 3:b|=mxConstants.DIRECTION_MASK_EAST}if(0<=d.indexOf(mxConstants.DIRECTION_EAST))switch(a){case 0:b|=mxConstants.DIRECTION_MASK_EAST;break;case 1:b|=mxConstants.DIRECTION_MASK_SOUTH;break;case 2:b|= -mxConstants.DIRECTION_MASK_WEST;break;case 3:b|=mxConstants.DIRECTION_MASK_NORTH}return b},reversePortConstraints:function(a){var b;b=(a&mxConstants.DIRECTION_MASK_WEST)<<3;b|=(a&mxConstants.DIRECTION_MASK_NORTH)<<1;b|=(a&mxConstants.DIRECTION_MASK_SOUTH)>>1;return b|=(a&mxConstants.DIRECTION_MASK_EAST)>>3},findNearestSegment:function(a,b,c){var d=-1;if(0f.distSq)&&(d=f)}}return null!=d?d.p:null},rectangleIntersectsSegment:function(a, -b,c){var d=a.y,e=a.x,f=d+a.height,g=e+a.width;a=b.x;var k=c.x;b.x>c.x&&(a=c.x,k=b.x);k>g&&(k=g);ak)return!1;var e=b.y,g=c.y,l=c.x-b.x;1E-7g&&(b=g,g=e,e=b);g>f&&(g=f);eg?!1:!0},contains:function(a,b,c){return a.x<=b&&a.x+a.width>=b&&a.y<=c&&a.y+a.height>=c},intersects:function(a,b){var c=a.width,d=a.height,e=b.width,f=b.height;if(0>=e||0>=f||0>=c||0>=d)return!1;var g=a.x,k=a.y,l=b.x,m=b.y,e=e+l,f=f+m,c=c+ -g,d=d+k;return(eg)&&(fk)&&(cl)&&(dm)},intersectsHotspot:function(a,b,c,d,e,f){d=null!=d?d:1;e=null!=e?e:0;f=null!=f?f:0;if(0a.toLowerCase().indexOf("0x"))},isInteger:function(a){return String(parseInt(a))===String(a)},mod:function(a,b){return(a%b+b)%b},intersection:function(a,b, -c,d,e,f,g,k){var l=(k-f)*(c-a)-(g-e)*(d-b);g=((g-e)*(b-f)-(k-f)*(a-e))/l;e=((c-a)*(b-f)-(d-b)*(a-e))/l;return 0<=g&&1>=g&&0<=e&&1>=e?new mxPoint(a+g*(c-a),b+g*(d-b)):null},ptSegDistSq:function(a,b,c,d,e,f){c-=a;d-=b;e-=a;f-=b;0>=e*c+f*d?c=0:(e=c-e,f=d-f,a=e*c+f*d,c=0>=a?0:a*a/(c*c+d*d));e=e*e+f*f-c;0>e&&(e=0);return e},ptLineDist:function(a,b,c,d,e,f){return Math.abs((d-b)*e-(c-a)*f+c*b-d*a)/Math.sqrt((d-b)*(d-b)+(c-a)*(c-a))},relativeCcw:function(a,b,c,d,e,f){c-=a;d-=b;e-=a;f-=b;a=e*d-f*c;0==a&& -(a=e*c+f*d,0a&&(a=0)));return 0>a?-1:0document.documentMode)?a.style.filter=100<=b?"": -"alpha(opacity="+b+")":a.style.opacity=b/100},createImage:function(a){var b;mxClient.IS_IE6&&"CSS1Compat"!=document.compatMode?(b=document.createElement(mxClient.VML_PREFIX+":image"),b.setAttribute("src",a),b.style.borderStyle="none"):(b=document.createElement("img"),b.setAttribute("src",a),b.setAttribute("border","0"));return b},sortCells:function(a,b){b=null!=b?b:!0;var c=new mxDictionary;a.sort(function(a,e){var d=c.get(a);null==d&&(d=mxCellPath.create(a).split(mxCellPath.PATH_SEPARATOR),c.put(a, -d));var g=c.get(e);null==g&&(g=mxCellPath.create(e).split(mxCellPath.PATH_SEPARATOR),c.put(e,g));d=mxCellPath.compare(d,g);return 0==d?0:0a.indexOf("="))?a:""},getStylenames:function(a){var b=[];if(null!=a){a=a.split(";");for(var c=0;ca[c].indexOf("=")&&b.push(a[c])}return b},indexOfStylename:function(a,b){if(null!=a&&null!=b)for(var c=a.split(";"),d=0,e=0;emxUtils.indexOfStylename(a,b)&&(null==a?a="":0e?";":a.substring(e)):0>e||e==a.length-1?"":a.substring(e+1)}else{var f=a.indexOf(";"+b+"=");0>f?d&&(d=";"==a.charAt(a.length-1)?"":";",a=a+d+b+"="+c+";"):(e=a.indexOf(";", -f+1),a=d?a.substring(0,f+1)+b+"="+c+(0>e?";":a.substring(e)):a.substring(0,f)+(0>e?";":a.substring(e)))}return a},setCellStyleFlags:function(a,b,c,d,e){if(null!=b&&0e)e=";"==a.charAt(a.length-1)?"":";",a=d||null==d?a+ -e+b+"="+c:a+e+b+"=0";else{var f=a.indexOf(";",e),g;g=0>f?a.substring(e+b.length+1):a.substring(e+b.length+1,f);g=null==d?parseInt(g)^c:d?parseInt(g)|c:parseInt(g)&~c;a=a.substring(0,e)+b+"="+g+(0<=f?a.substring(f):"")}}return a},getAlignmentAsPoint:function(a,b){var c=-.5,d=-.5;a==mxConstants.ALIGN_LEFT?c=0:a==mxConstants.ALIGN_RIGHT&&(c=-1);b==mxConstants.ALIGN_TOP?d=0:b==mxConstants.ALIGN_BOTTOM&&(d=-1);return new mxPoint(c,d)},getSizeForString:function(a,b,c,d,e){b=null!=b?b:mxConstants.DEFAULT_FONTSIZE; -c=null!=c?c:mxConstants.DEFAULT_FONTFAMILY;var f=document.createElement("div");f.style.fontFamily=c;f.style.fontSize=Math.round(b)+"px";f.style.lineHeight=Math.round(b*mxConstants.LINE_HEIGHT)+"px";null!=e&&((e&mxConstants.FONT_BOLD)==mxConstants.FONT_BOLD&&(f.style.fontWeight="bold"),(e&mxConstants.FONT_ITALIC)==mxConstants.FONT_ITALIC&&(f.style.fontStyle="italic"),b=[],(e&mxConstants.FONT_UNDERLINE)==mxConstants.FONT_UNDERLINE&&b.push("underline"),(e&mxConstants.FONT_STRIKETHROUGH)==mxConstants.FONT_STRIKETHROUGH&& -b.push("line-through"),0a)return 1;c=null!=c?c:mxConstants.PAGE_FORMAT_A4_PORTRAIT;d=null!=d?d:0;var e=c.width-2*d;c=c.height-2*d;d=b.getGraphBounds().clone();b=b.getView().getScale();d.width/=b;d.height/=b;b=d.width; -var f=Math.sqrt(a);d=Math.sqrt(b/d.height/(e/c));c=f*d;d=f/d;if(1>c&&d>a){var g=d/a;d=a;c/=g}1>d&&c>a&&(g=c/a,c=a,d/=g);g=Math.ceil(c)*Math.ceil(d);for(f=0;g>a;){var g=Math.floor(c)/c,k=Math.floor(d)/d;1==g&&(g=Math.floor(c-1)/c);1==k&&(k=Math.floor(d-1)/d);g=g>k?g:k;c*=g;d*=g;g=Math.ceil(c)*Math.ceil(d);f++;if(10";g=document.getElementsByTagName("base");for(c=0;c";for(c=0;c'+('
')+a.container.innerHTML;b.writeln(d+"
");b.close()}else{b.writeln("");g=document.getElementsByTagName("base");for(c=0;c'); -b.close();c=b.createElement("div");c.position="absolute";c.overflow="hidden";c.style.width=e+"px";c.style.height=f+"px";e=b.createElement("div");e.style.position="absolute";e.style.left=k+"px";e.style.top=l+"px";f=a.container.firstChild;for(d=null;null!=f;)g=f.cloneNode(!0),f==a.view.drawPane.ownerSVGElement?(c.appendChild(g),d=g):e.appendChild(g),f=f.nextSibling;b.body.appendChild(c);null!=e.firstChild&&b.body.appendChild(e);null!=d&&(d.style.minWidth="",d.style.minHeight="",d.firstChild.setAttribute("transform", -"translate("+k+","+l+")"))}mxUtils.removeCursors(b.body);return b},printScreen:function(a){var b=window.open();a.getGraphBounds();mxUtils.show(a,b.document);a=function(){b.focus();b.print();b.close()};mxClient.IS_GC?b.setTimeout(a,500):a()},popup:function(a,b){if(b){var c=document.createElement("div");c.style.overflow="scroll";c.style.width="636px";c.style.height="460px";var d=document.createElement("pre");d.innerHTML=mxUtils.htmlEntities(a,!1).replace(/\n/g,"
").replace(/ /g," ");c.appendChild(d); -c=new mxWindow("Popup Window",c,document.body.clientWidth/2-320,Math.max(document.body.clientHeight||0,document.documentElement.clientHeight)/2-240,640,480,!1,!0);c.setClosable(!0);c.setVisible(!0)}else mxClient.IS_NS?(c=window.open(),c.document.writeln("
"+mxUtils.htmlEntities(a)+"").replace(/ /g," "),c.document.body.appendChild(d))},alert:function(a){alert(a)},
-prompt:function(a,b){return prompt(a,null!=b?b:"")},confirm:function(a){return confirm(a)},error:function(a,b,c,d){var e=document.createElement("div");e.style.padding="20px";var f=document.createElement("img");f.setAttribute("src",d||mxUtils.errorImage);f.setAttribute("valign","bottom");f.style.verticalAlign="middle";e.appendChild(f);e.appendChild(document.createTextNode(" "));e.appendChild(document.createTextNode(" "));e.appendChild(document.createTextNode(" "));mxUtils.write(e,a);a=document.body.clientWidth;
-d=document.body.clientHeight||document.documentElement.clientHeight;var g=new mxWindow(mxResources.get(mxUtils.errorResource)||mxUtils.errorResource,e,(a-b)/2,d/4,b,null,!1,!0);c&&(mxUtils.br(e),b=document.createElement("p"),c=document.createElement("button"),mxClient.IS_IE?c.style.cssText="float:right":c.setAttribute("style","float:right"),mxEvent.addListener(c,"click",function(a){g.destroy()}),mxUtils.write(c,mxResources.get(mxUtils.closeResource)||mxUtils.closeResource),b.appendChild(c),e.appendChild(b),
-mxUtils.br(e),g.setClosable(!0));g.setVisible(!0);return g},makeDraggable:function(a,b,c,d,e,f,g,k,l,m){a=new mxDragSource(a,c);a.dragOffset=new mxPoint(null!=e?e:0,null!=f?f:mxConstants.TOOLTIP_VERTICAL_OFFSET);a.autoscroll=g;a.setGuidesEnabled(!1);null!=l&&(a.highlightDropTargets=l);null!=m&&(a.getDropTarget=m);a.getGraphForEvent=function(a){return"function"==typeof b?b(a):b};null!=d&&(a.createDragElement=function(){return d.cloneNode(!0)},k&&(a.createPreviewElement=function(a){var b=d.cloneNode(!0),
-c=parseInt(b.style.width),e=parseInt(b.style.height);b.style.width=Math.round(c*a.view.scale)+"px";b.style.height=Math.round(e*a.view.scale)+"px";return b}));return a}},mxConstants={DEFAULT_HOTSPOT:.3,MIN_HOTSPOT_SIZE:8,MAX_HOTSPOT_SIZE:0,RENDERING_HINT_EXACT:"exact",RENDERING_HINT_FASTER:"faster",RENDERING_HINT_FASTEST:"fastest",DIALECT_SVG:"svg",DIALECT_VML:"vml",DIALECT_MIXEDHTML:"mixedHtml",DIALECT_PREFERHTML:"preferHtml",DIALECT_STRICTHTML:"strictHtml",NS_SVG:"http://www.w3.org/2000/svg",NS_XHTML:"http://www.w3.org/1999/xhtml",
-NS_XLINK:"http://www.w3.org/1999/xlink",SHADOWCOLOR:"gray",VML_SHADOWCOLOR:"gray",SHADOW_OFFSET_X:2,SHADOW_OFFSET_Y:3,SHADOW_OPACITY:1,NODETYPE_ELEMENT:1,NODETYPE_ATTRIBUTE:2,NODETYPE_TEXT:3,NODETYPE_CDATA:4,NODETYPE_ENTITY_REFERENCE:5,NODETYPE_ENTITY:6,NODETYPE_PROCESSING_INSTRUCTION:7,NODETYPE_COMMENT:8,NODETYPE_DOCUMENT:9,NODETYPE_DOCUMENTTYPE:10,NODETYPE_DOCUMENT_FRAGMENT:11,NODETYPE_NOTATION:12,TOOLTIP_VERTICAL_OFFSET:16,DEFAULT_VALID_COLOR:"#00FF00",DEFAULT_INVALID_COLOR:"#FF0000",OUTLINE_HIGHLIGHT_COLOR:"#00FF00",
-OUTLINE_HIGHLIGHT_STROKEWIDTH:5,HIGHLIGHT_STROKEWIDTH:3,HIGHLIGHT_SIZE:2,HIGHLIGHT_OPACITY:100,CURSOR_MOVABLE_VERTEX:"move",CURSOR_MOVABLE_EDGE:"move",CURSOR_LABEL_HANDLE:"default",CURSOR_TERMINAL_HANDLE:"pointer",CURSOR_BEND_HANDLE:"crosshair",CURSOR_VIRTUAL_BEND_HANDLE:"crosshair",CURSOR_CONNECT:"pointer",HIGHLIGHT_COLOR:"#00FF00",CONNECT_TARGET_COLOR:"#0000FF",INVALID_CONNECT_TARGET_COLOR:"#FF0000",DROP_TARGET_COLOR:"#0000FF",VALID_COLOR:"#00FF00",INVALID_COLOR:"#FF0000",EDGE_SELECTION_COLOR:"#00FF00",
-VERTEX_SELECTION_COLOR:"#00FF00",VERTEX_SELECTION_STROKEWIDTH:1,EDGE_SELECTION_STROKEWIDTH:1,VERTEX_SELECTION_DASHED:!0,EDGE_SELECTION_DASHED:!0,GUIDE_COLOR:"#FF0000",GUIDE_STROKEWIDTH:1,OUTLINE_COLOR:"#0099FF",OUTLINE_STROKEWIDTH:mxClient.IS_IE?2:3,HANDLE_SIZE:6,LABEL_HANDLE_SIZE:4,HANDLE_FILLCOLOR:"#00FF00",HANDLE_STROKECOLOR:"black",LABEL_HANDLE_FILLCOLOR:"yellow",CONNECT_HANDLE_FILLCOLOR:"#0000FF",LOCKED_HANDLE_FILLCOLOR:"#FF0000",OUTLINE_HANDLE_FILLCOLOR:"#00FFFF",OUTLINE_HANDLE_STROKECOLOR:"#0033FF",
-DEFAULT_FONTFAMILY:"Arial,Helvetica",DEFAULT_FONTSIZE:11,DEFAULT_TEXT_DIRECTION:"",LINE_HEIGHT:1.2,WORD_WRAP:"normal",ABSOLUTE_LINE_HEIGHT:!1,DEFAULT_FONTSTYLE:0,DEFAULT_STARTSIZE:40,DEFAULT_MARKERSIZE:6,DEFAULT_IMAGESIZE:24,ENTITY_SEGMENT:30,RECTANGLE_ROUNDING_FACTOR:.15,LINE_ARCSIZE:20,ARROW_SPACING:0,ARROW_WIDTH:30,ARROW_SIZE:30,PAGE_FORMAT_A4_PORTRAIT:new mxRectangle(0,0,827,1169),PAGE_FORMAT_A4_LANDSCAPE:new mxRectangle(0,0,1169,827),PAGE_FORMAT_LETTER_PORTRAIT:new mxRectangle(0,0,850,1100),
-PAGE_FORMAT_LETTER_LANDSCAPE:new mxRectangle(0,0,1100,850),NONE:"none",STYLE_PERIMETER:"perimeter",STYLE_SOURCE_PORT:"sourcePort",STYLE_TARGET_PORT:"targetPort",STYLE_PORT_CONSTRAINT:"portConstraint",STYLE_PORT_CONSTRAINT_ROTATION:"portConstraintRotation",STYLE_SOURCE_PORT_CONSTRAINT:"sourcePortConstraint",STYLE_TARGET_PORT_CONSTRAINT:"targetPortConstraint",STYLE_OPACITY:"opacity",STYLE_FILL_OPACITY:"fillOpacity",STYLE_STROKE_OPACITY:"strokeOpacity",STYLE_TEXT_OPACITY:"textOpacity",STYLE_TEXT_DIRECTION:"textDirection",
-STYLE_OVERFLOW:"overflow",STYLE_ORTHOGONAL:"orthogonal",STYLE_EXIT_X:"exitX",STYLE_EXIT_Y:"exitY",STYLE_EXIT_DX:"exitDx",STYLE_EXIT_DY:"exitDy",STYLE_EXIT_PERIMETER:"exitPerimeter",STYLE_ENTRY_X:"entryX",STYLE_ENTRY_Y:"entryY",STYLE_ENTRY_DX:"entryDx",STYLE_ENTRY_DY:"entryDy",STYLE_ENTRY_PERIMETER:"entryPerimeter",STYLE_WHITE_SPACE:"whiteSpace",STYLE_ROTATION:"rotation",STYLE_FILLCOLOR:"fillColor",STYLE_POINTER_EVENTS:"pointerEvents",STYLE_SWIMLANE_FILLCOLOR:"swimlaneFillColor",STYLE_MARGIN:"margin",
-STYLE_GRADIENTCOLOR:"gradientColor",STYLE_GRADIENT_DIRECTION:"gradientDirection",STYLE_STROKECOLOR:"strokeColor",STYLE_SEPARATORCOLOR:"separatorColor",STYLE_STROKEWIDTH:"strokeWidth",STYLE_ALIGN:"align",STYLE_VERTICAL_ALIGN:"verticalAlign",STYLE_LABEL_WIDTH:"labelWidth",STYLE_LABEL_POSITION:"labelPosition",STYLE_VERTICAL_LABEL_POSITION:"verticalLabelPosition",STYLE_IMAGE_ASPECT:"imageAspect",STYLE_IMAGE_ALIGN:"imageAlign",STYLE_IMAGE_VERTICAL_ALIGN:"imageVerticalAlign",STYLE_GLASS:"glass",STYLE_IMAGE:"image",
-STYLE_IMAGE_WIDTH:"imageWidth",STYLE_IMAGE_HEIGHT:"imageHeight",STYLE_IMAGE_BACKGROUND:"imageBackground",STYLE_IMAGE_BORDER:"imageBorder",STYLE_FLIPH:"flipH",STYLE_FLIPV:"flipV",STYLE_NOLABEL:"noLabel",STYLE_NOEDGESTYLE:"noEdgeStyle",STYLE_LABEL_BACKGROUNDCOLOR:"labelBackgroundColor",STYLE_LABEL_BORDERCOLOR:"labelBorderColor",STYLE_LABEL_PADDING:"labelPadding",STYLE_INDICATOR_SHAPE:"indicatorShape",STYLE_INDICATOR_IMAGE:"indicatorImage",STYLE_INDICATOR_COLOR:"indicatorColor",STYLE_INDICATOR_STROKECOLOR:"indicatorStrokeColor",
-STYLE_INDICATOR_GRADIENTCOLOR:"indicatorGradientColor",STYLE_INDICATOR_SPACING:"indicatorSpacing",STYLE_INDICATOR_WIDTH:"indicatorWidth",STYLE_INDICATOR_HEIGHT:"indicatorHeight",STYLE_INDICATOR_DIRECTION:"indicatorDirection",STYLE_SHADOW:"shadow",STYLE_SEGMENT:"segment",STYLE_ENDARROW:"endArrow",STYLE_STARTARROW:"startArrow",STYLE_ENDSIZE:"endSize",STYLE_STARTSIZE:"startSize",STYLE_SWIMLANE_LINE:"swimlaneLine",STYLE_ENDFILL:"endFill",STYLE_STARTFILL:"startFill",STYLE_DASHED:"dashed",STYLE_DASH_PATTERN:"dashPattern",
-STYLE_FIX_DASH:"fixDash",STYLE_ROUNDED:"rounded",STYLE_CURVED:"curved",STYLE_ARCSIZE:"arcSize",STYLE_ABSOLUTE_ARCSIZE:"absoluteArcSize",STYLE_SOURCE_PERIMETER_SPACING:"sourcePerimeterSpacing",STYLE_TARGET_PERIMETER_SPACING:"targetPerimeterSpacing",STYLE_PERIMETER_SPACING:"perimeterSpacing",STYLE_SPACING:"spacing",STYLE_SPACING_TOP:"spacingTop",STYLE_SPACING_LEFT:"spacingLeft",STYLE_SPACING_BOTTOM:"spacingBottom",STYLE_SPACING_RIGHT:"spacingRight",STYLE_HORIZONTAL:"horizontal",STYLE_DIRECTION:"direction",
-STYLE_ANCHOR_POINT_DIRECTION:"anchorPointDirection",STYLE_ELBOW:"elbow",STYLE_FONTCOLOR:"fontColor",STYLE_FONTFAMILY:"fontFamily",STYLE_FONTSIZE:"fontSize",STYLE_FONTSTYLE:"fontStyle",STYLE_ASPECT:"aspect",STYLE_AUTOSIZE:"autosize",STYLE_FOLDABLE:"foldable",STYLE_EDITABLE:"editable",STYLE_BACKGROUND_OUTLINE:"backgroundOutline",STYLE_BENDABLE:"bendable",STYLE_MOVABLE:"movable",STYLE_RESIZABLE:"resizable",STYLE_RESIZE_WIDTH:"resizeWidth",STYLE_RESIZE_HEIGHT:"resizeHeight",STYLE_ROTATABLE:"rotatable",
-STYLE_CLONEABLE:"cloneable",STYLE_DELETABLE:"deletable",STYLE_SHAPE:"shape",STYLE_EDGE:"edgeStyle",STYLE_JETTY_SIZE:"jettySize",STYLE_SOURCE_JETTY_SIZE:"sourceJettySize",STYLE_TARGET_JETTY_SIZE:"targetJettySize",STYLE_LOOP:"loopStyle",STYLE_ORTHOGONAL_LOOP:"orthogonalLoop",STYLE_ROUTING_CENTER_X:"routingCenterX",STYLE_ROUTING_CENTER_Y:"routingCenterY",FONT_BOLD:1,FONT_ITALIC:2,FONT_UNDERLINE:4,FONT_STRIKETHROUGH:8,SHAPE_RECTANGLE:"rectangle",SHAPE_ELLIPSE:"ellipse",SHAPE_DOUBLE_ELLIPSE:"doubleEllipse",
-SHAPE_RHOMBUS:"rhombus",SHAPE_LINE:"line",SHAPE_IMAGE:"image",SHAPE_ARROW:"arrow",SHAPE_ARROW_CONNECTOR:"arrowConnector",SHAPE_LABEL:"label",SHAPE_CYLINDER:"cylinder",SHAPE_SWIMLANE:"swimlane",SHAPE_CONNECTOR:"connector",SHAPE_ACTOR:"actor",SHAPE_CLOUD:"cloud",SHAPE_TRIANGLE:"triangle",SHAPE_HEXAGON:"hexagon",ARROW_CLASSIC:"classic",ARROW_CLASSIC_THIN:"classicThin",ARROW_BLOCK:"block",ARROW_BLOCK_THIN:"blockThin",ARROW_OPEN:"open",ARROW_OPEN_THIN:"openThin",ARROW_OVAL:"oval",ARROW_DIAMOND:"diamond",
-ARROW_DIAMOND_THIN:"diamondThin",ALIGN_LEFT:"left",ALIGN_CENTER:"center",ALIGN_RIGHT:"right",ALIGN_TOP:"top",ALIGN_MIDDLE:"middle",ALIGN_BOTTOM:"bottom",DIRECTION_NORTH:"north",DIRECTION_SOUTH:"south",DIRECTION_EAST:"east",DIRECTION_WEST:"west",TEXT_DIRECTION_DEFAULT:"",TEXT_DIRECTION_AUTO:"auto",TEXT_DIRECTION_LTR:"ltr",TEXT_DIRECTION_RTL:"rtl",DIRECTION_MASK_NONE:0,DIRECTION_MASK_WEST:1,DIRECTION_MASK_NORTH:2,DIRECTION_MASK_SOUTH:4,DIRECTION_MASK_EAST:8,DIRECTION_MASK_ALL:15,ELBOW_VERTICAL:"vertical",
-ELBOW_HORIZONTAL:"horizontal",EDGESTYLE_ELBOW:"elbowEdgeStyle",EDGESTYLE_ENTITY_RELATION:"entityRelationEdgeStyle",EDGESTYLE_LOOP:"loopEdgeStyle",EDGESTYLE_SIDETOSIDE:"sideToSideEdgeStyle",EDGESTYLE_TOPTOBOTTOM:"topToBottomEdgeStyle",EDGESTYLE_ORTHOGONAL:"orthogonalEdgeStyle",EDGESTYLE_SEGMENT:"segmentEdgeStyle",PERIMETER_ELLIPSE:"ellipsePerimeter",PERIMETER_RECTANGLE:"rectanglePerimeter",PERIMETER_RHOMBUS:"rhombusPerimeter",PERIMETER_HEXAGON:"hexagonPerimeter",PERIMETER_TRIANGLE:"trianglePerimeter"};
-function mxEventObject(a){this.name=a;this.properties=[];for(var b=1;bd,!0),c=b.scale)});mxEvent.addListener(b,"gestureend",function(a){mxEvent.consume(a)})}else{var d=
-[],e=0,f=0;mxEvent.addGestureListeners(b,mxUtils.bind(this,function(a){mxEvent.isMouseEvent(a)||null==a.pointerId||d.push(a)}),mxUtils.bind(this,function(b){if(!mxEvent.isMouseEvent(b)&&2==d.length){for(var c=0;cmxEvent.PINCH_THRESHOLD||m>mxEvent.PINCH_THRESHOLD)a(d[0],g>m?b>e:c>f,!0,d[0].clientX+(d[1].clientX-d[0].clientX)/
-2,d[0].clientY+(d[1].clientY-d[0].clientY)/2),e=b,f=c}}),mxUtils.bind(this,function(a){d=[];f=e=0}))}mxEvent.addListener(b,"wheel",function(b){null==b&&(b=window.event);b.ctrlKey&&b.preventDefault();(.5navigator.userAgent.indexOf("Presto/2.5"))this.contentWrapper.style.overflow=a?"auto":"hidden"};
-mxWindow.prototype.activate=function(){if(mxWindow.activeWindow!=this){var a=mxUtils.getCurrentStyle(this.getElement()),a=null!=a?a.zIndex:3;if(mxWindow.activeWindow){var b=mxWindow.activeWindow.getElement();null!=b&&null!=b.style&&(b.style.zIndex=a)}b=mxWindow.activeWindow;this.getElement().style.zIndex=parseInt(a)+1;mxWindow.activeWindow=this;this.fireEvent(new mxEventObject(mxEvent.ACTIVATE,"previousWindow",b))}};mxWindow.prototype.getElement=function(){return this.div};
-mxWindow.prototype.fit=function(){mxUtils.fit(this.div)};mxWindow.prototype.isResizable=function(){return null!=this.resize?"none"!=this.resize.style.display:!1};
-mxWindow.prototype.setResizable=function(a){if(a)if(null==this.resize){this.resize=document.createElement("img");this.resize.style.position="absolute";this.resize.style.bottom="2px";this.resize.style.right="2px";this.resize.setAttribute("src",this.resizeImage);this.resize.style.cursor="nw-resize";var b=null,c=null,d=null,e=null;a=mxUtils.bind(this,function(a){this.activate();b=mxEvent.getClientX(a);c=mxEvent.getClientY(a);d=this.div.offsetWidth;e=this.div.offsetHeight;mxEvent.addGestureListeners(document,
-null,f,g);this.fireEvent(new mxEventObject(mxEvent.RESIZE_START,"event",a));mxEvent.consume(a)});var f=mxUtils.bind(this,function(a){if(null!=b&&null!=c){var f=mxEvent.getClientX(a)-b,g=mxEvent.getClientY(a)-c;this.setSize(d+f,e+g);this.fireEvent(new mxEventObject(mxEvent.RESIZE,"event",a));mxEvent.consume(a)}}),g=mxUtils.bind(this,function(a){null!=b&&null!=c&&(c=b=null,mxEvent.removeGestureListeners(document,null,f,g),this.fireEvent(new mxEventObject(mxEvent.RESIZE_END,"event",a)),mxEvent.consume(a))});
-mxEvent.addGestureListeners(this.resize,a,f,g);this.div.appendChild(this.resize)}else this.resize.style.display="inline";else null!=this.resize&&(this.resize.style.display="none")};
-mxWindow.prototype.setSize=function(a,b){a=Math.max(this.minimumSize.width,a);b=Math.max(this.minimumSize.height,b);mxClient.IS_QUIRKS||(this.div.style.width=a+"px",this.div.style.height=b+"px");this.table.style.width=a+"px";this.table.style.height=b+"px";mxClient.IS_QUIRKS||(this.contentWrapper.style.height=this.div.offsetHeight-this.title.offsetHeight-this.contentHeightCorrection+"px")};mxWindow.prototype.setMinimizable=function(a){this.minimize.style.display=a?"":"none"};
-mxWindow.prototype.getMinimumSize=function(){return new mxRectangle(0,0,0,this.title.offsetHeight)};
-mxWindow.prototype.installMinimizeHandler=function(){this.minimize=document.createElement("img");this.minimize.setAttribute("src",this.minimizeImage);this.minimize.setAttribute("title","Minimize");this.minimize.style.cursor="pointer";this.minimize.style.marginLeft="2px";this.minimize.style.display="none";this.buttons.appendChild(this.minimize);var a=!1,b=null,c=null,d=mxUtils.bind(this,function(d){this.activate();if(a)a=!1,this.minimize.setAttribute("src",this.minimizeImage),this.minimize.setAttribute("title",
-"Minimize"),this.contentWrapper.style.display="",this.maximize.style.display=b,mxClient.IS_QUIRKS||(this.div.style.height=c),this.table.style.height=c,null!=this.resize&&(this.resize.style.visibility=""),this.fireEvent(new mxEventObject(mxEvent.NORMALIZE,"event",d));else{a=!0;this.minimize.setAttribute("src",this.normalizeImage);this.minimize.setAttribute("title","Normalize");this.contentWrapper.style.display="none";b=this.maximize.style.display;this.maximize.style.display="none";c=this.table.style.height;
-var e=this.getMinimumSize();0=e.x-f.x&&d>=e.y-f.y&&c<=e.x-f.x+a.container.offsetWidth&&d<=e.y-f.y+a.container.offsetHeight};
-mxDragSource.prototype.mouseMove=function(a){var b=this.getGraphForEvent(a);null==b||this.graphContainsEvent(b,a)||(b=null);b!=this.currentGraph&&(null!=this.currentGraph&&this.dragExit(this.currentGraph,a),this.currentGraph=b,null!=this.currentGraph&&this.dragEnter(this.currentGraph,a));null!=this.currentGraph&&this.dragOver(this.currentGraph,a);if(null==this.dragElement||null!=this.previewElement&&"visible"==this.previewElement.style.visibility)null!=this.dragElement&&(this.dragElement.style.visibility=
-"hidden");else{var b=mxEvent.getClientX(a),c=mxEvent.getClientY(a);null==this.dragElement.parentNode&&document.body.appendChild(this.dragElement);this.dragElement.style.visibility="visible";null!=this.dragOffset&&(b+=this.dragOffset.x,c+=this.dragOffset.y);var d=mxUtils.getDocumentScrollOrigin(document);this.dragElement.style.left=b+d.x+"px";this.dragElement.style.top=c+d.y+"px"}mxEvent.consume(a)};
-mxDragSource.prototype.mouseUp=function(a){if(null!=this.currentGraph){if(null!=this.currentPoint&&(null==this.previewElement||"hidden"!=this.previewElement.style.visibility)){var b=this.currentGraph.view.scale,c=this.currentGraph.view.translate;this.drop(this.currentGraph,a,this.currentDropTarget,this.currentPoint.x/b-c.x,this.currentPoint.y/b-c.y)}this.dragExit(this.currentGraph);this.currentGraph=null}this.stopDrag();this.removeListeners();mxEvent.consume(a)};
-mxDragSource.prototype.removeListeners=function(){null!=this.eventSource&&(mxEvent.removeGestureListeners(this.eventSource,null,this.mouseMoveHandler,this.mouseUpHandler),this.eventSource=null);mxEvent.removeGestureListeners(document,null,this.mouseMoveHandler,this.mouseUpHandler);this.mouseUpHandler=this.mouseMoveHandler=null};
-mxDragSource.prototype.dragEnter=function(a,b){a.isMouseDown=!0;a.isMouseTrigger=mxEvent.isMouseEvent(b);this.previewElement=this.createPreviewElement(a);null!=this.previewElement&&this.checkEventSource&&mxClient.IS_SVG&&(this.previewElement.style.pointerEvents="none");this.isGuidesEnabled()&&null!=this.previewElement&&(this.currentGuide=new mxGuide(a,a.graphHandler.getGuideStates()));this.highlightDropTargets&&(this.currentHighlight=new mxCellHighlight(a,mxConstants.DROP_TARGET_COLOR));a.addListener(mxEvent.FIRE_MOUSE_EVENT,
-this.eventConsumer)};mxDragSource.prototype.dragExit=function(a,b){this.currentPoint=this.currentDropTarget=null;a.isMouseDown=!1;a.removeListener(this.eventConsumer);null!=this.previewElement&&(null!=this.previewElement.parentNode&&this.previewElement.parentNode.removeChild(this.previewElement),this.previewElement=null);null!=this.currentGuide&&(this.currentGuide.destroy(),this.currentGuide=null);null!=this.currentHighlight&&(this.currentHighlight.destroy(),this.currentHighlight=null)};
-mxDragSource.prototype.dragOver=function(a,b){var c=mxUtils.getOffset(a.container),d=mxUtils.getScrollOrigin(a.container),e=mxEvent.getClientX(b)-c.x+d.x-a.panDx,c=mxEvent.getClientY(b)-c.y+d.y-a.panDy;a.autoScroll&&(null==this.autoscroll||this.autoscroll)&&a.scrollPointToVisible(e,c,a.autoExtend);null!=this.currentHighlight&&a.isDropEnabled()&&(this.currentDropTarget=this.getDropTarget(a,e,c,b),d=a.getView().getState(this.currentDropTarget),this.currentHighlight.highlight(d));if(null!=this.previewElement){null==
-this.previewElement.parentNode&&(a.container.appendChild(this.previewElement),this.previewElement.style.zIndex="3",this.previewElement.style.position="absolute");var d=this.isGridEnabled()&&a.isGridEnabledEvent(b),f=!0;if(null!=this.currentGuide&&this.currentGuide.isEnabledForEvent(b))var f=parseInt(this.previewElement.style.width),g=parseInt(this.previewElement.style.height),f=new mxRectangle(0,0,f,g),c=new mxPoint(e,c),c=this.currentGuide.move(f,c,d,!0),f=!1,e=c.x,c=c.y;else if(d)var d=a.view.scale,
-g=a.view.translate,k=a.gridSize/2,e=(a.snap(e/d-g.x-k)+g.x)*d,c=(a.snap(c/d-g.y-k)+g.y)*d;null!=this.currentGuide&&f&&this.currentGuide.hide();null!=this.previewOffset&&(e+=this.previewOffset.x,c+=this.previewOffset.y);this.previewElement.style.left=Math.round(e)+"px";this.previewElement.style.top=Math.round(c)+"px";this.previewElement.style.visibility="visible"}this.currentPoint=new mxPoint(e,c)};
-mxDragSource.prototype.drop=function(a,b,c,d,e){this.dropHandler.apply(this,arguments);"hidden"!=a.container.style.visibility&&a.container.focus()};function mxToolbar(a){this.container=a}mxToolbar.prototype=new mxEventSource;mxToolbar.prototype.constructor=mxToolbar;mxToolbar.prototype.container=null;mxToolbar.prototype.enabled=!0;mxToolbar.prototype.noReset=!1;mxToolbar.prototype.updateDefaultMode=!0;
-mxToolbar.prototype.addItem=function(a,b,c,d,e,f){var g=document.createElement(null!=b?"img":"button"),k=e||(null!=f?"mxToolbarMode":"mxToolbarItem");g.className=k;g.setAttribute("src",b);null!=a&&(null!=b?g.setAttribute("title",a):mxUtils.write(g,a));this.container.appendChild(g);null!=c&&(mxEvent.addListener(g,"click",c),mxClient.IS_TOUCH&&mxEvent.addListener(g,"touchend",c));a=mxUtils.bind(this,function(a){null!=d?g.setAttribute("src",b):g.style.backgroundColor=""});mxEvent.addGestureListeners(g,
-mxUtils.bind(this,function(a){null!=d?g.setAttribute("src",d):g.style.backgroundColor="gray";if(null!=f){null==this.menu&&(this.menu=new mxPopupMenu,this.menu.init());var b=this.currentImg;this.menu.isMenuShowing()&&this.menu.hideMenu();b!=g&&(this.currentImg=g,this.menu.factoryMethod=f,b=new mxPoint(g.offsetLeft,g.offsetTop+g.offsetHeight),this.menu.popup(b.x,b.y,null,a),this.menu.isMenuShowing()&&(g.className=k+"Selected",this.menu.hideMenu=function(){mxPopupMenu.prototype.hideMenu.apply(this);
-g.className=k;this.currentImg=null}))}}),null,a);mxEvent.addListener(g,"mouseout",a);return g};mxToolbar.prototype.addCombo=function(a){var b=document.createElement("div");b.style.display="inline";b.className="mxToolbarComboContainer";var c=document.createElement("select");c.className=a||"mxToolbarCombo";b.appendChild(c);this.container.appendChild(b);return c};
-mxToolbar.prototype.addActionCombo=function(a,b){var c=document.createElement("select");c.className=b||"mxToolbarCombo";this.addOption(c,a,null);mxEvent.addListener(c,"change",function(a){var b=c.options[c.selectedIndex];c.selectedIndex=0;null!=b.funct&&b.funct(a)});this.container.appendChild(c);return c};mxToolbar.prototype.addOption=function(a,b,c){var d=document.createElement("option");mxUtils.writeln(d,b);"function"==typeof c?d.funct=c:d.setAttribute("value",c);a.appendChild(d);return d};
-mxToolbar.prototype.addSwitchMode=function(a,b,c,d,e){var f=document.createElement("img");f.initialClassName=e||"mxToolbarMode";f.className=f.initialClassName;f.setAttribute("src",b);f.altIcon=d;null!=a&&f.setAttribute("title",a);mxEvent.addListener(f,"click",mxUtils.bind(this,function(a){a=this.selectedMode.altIcon;null!=a?(this.selectedMode.altIcon=this.selectedMode.getAttribute("src"),this.selectedMode.setAttribute("src",a)):this.selectedMode.className=this.selectedMode.initialClassName;this.updateDefaultMode&&
-(this.defaultMode=f);this.selectedMode=f;a=f.altIcon;null!=a?(f.altIcon=f.getAttribute("src"),f.setAttribute("src",a)):f.className=f.initialClassName+"Selected";this.fireEvent(new mxEventObject(mxEvent.SELECT));c()}));this.container.appendChild(f);null==this.defaultMode&&(this.defaultMode=f,this.selectMode(f),c());return f};
-mxToolbar.prototype.addMode=function(a,b,c,d,e,f){f=null!=f?f:!0;var g=document.createElement(null!=b?"img":"button");g.initialClassName=e||"mxToolbarMode";g.className=g.initialClassName;g.setAttribute("src",b);g.altIcon=d;null!=a&&g.setAttribute("title",a);this.enabled&&f&&(mxEvent.addListener(g,"click",mxUtils.bind(this,function(a){this.selectMode(g,c);this.noReset=!1})),mxEvent.addListener(g,"dblclick",mxUtils.bind(this,function(a){this.selectMode(g,c);this.noReset=!0})),null==this.defaultMode&&
-(this.defaultMode=g,this.defaultFunction=c,this.selectMode(g,c)));this.container.appendChild(g);return g};
-mxToolbar.prototype.selectMode=function(a,b){if(this.selectedMode!=a){if(null!=this.selectedMode){var c=this.selectedMode.altIcon;null!=c?(this.selectedMode.altIcon=this.selectedMode.getAttribute("src"),this.selectedMode.setAttribute("src",c)):this.selectedMode.className=this.selectedMode.initialClassName}this.selectedMode=a;c=this.selectedMode.altIcon;null!=c?(this.selectedMode.altIcon=this.selectedMode.getAttribute("src"),this.selectedMode.setAttribute("src",c)):this.selectedMode.className=this.selectedMode.initialClassName+
-"Selected";this.fireEvent(new mxEventObject(mxEvent.SELECT,"function",b))}};mxToolbar.prototype.resetMode=function(a){!a&&this.noReset||this.selectedMode==this.defaultMode||this.selectMode(this.defaultMode,this.defaultFunction)};mxToolbar.prototype.addSeparator=function(a){return this.addItem(null,a,null)};mxToolbar.prototype.addBreak=function(){mxUtils.br(this.container)};
-mxToolbar.prototype.addLine=function(){var a=document.createElement("hr");a.style.marginRight="6px";a.setAttribute("size","1");this.container.appendChild(a)};mxToolbar.prototype.destroy=function(){mxEvent.release(this.container);this.selectedMode=this.defaultFunction=this.defaultMode=this.container=null;null!=this.menu&&this.menu.destroy()};function mxUndoableEdit(a,b){this.source=a;this.changes=[];this.significant=null!=b?b:!0}mxUndoableEdit.prototype.source=null;
-mxUndoableEdit.prototype.changes=null;mxUndoableEdit.prototype.significant=null;mxUndoableEdit.prototype.undone=!1;mxUndoableEdit.prototype.redone=!1;mxUndoableEdit.prototype.isEmpty=function(){return 0==this.changes.length};mxUndoableEdit.prototype.isSignificant=function(){return this.significant};mxUndoableEdit.prototype.add=function(a){this.changes.push(a)};mxUndoableEdit.prototype.notify=function(){};mxUndoableEdit.prototype.die=function(){};
-mxUndoableEdit.prototype.undo=function(){if(!this.undone){this.source.fireEvent(new mxEventObject(mxEvent.START_EDIT));for(var a=this.changes.length-1;0<=a;a--){var b=this.changes[a];null!=b.execute?b.execute():null!=b.undo&&b.undo();this.source.fireEvent(new mxEventObject(mxEvent.EXECUTED,"change",b))}this.undone=!0;this.redone=!1;this.source.fireEvent(new mxEventObject(mxEvent.END_EDIT))}this.notify()};
-mxUndoableEdit.prototype.redo=function(){if(!this.redone){this.source.fireEvent(new mxEventObject(mxEvent.START_EDIT));for(var a=this.changes.length,b=0;bthis.indexOfNextAdd)for(var a=this.history.splice(this.indexOfNextAdd,this.history.length-this.indexOfNextAdd),b=0;bthis.dx&&Math.abs(this.dx)<
-this.border?this.border+this.dx:this.handleMouseOut?Math.max(this.dx,0):0;0==this.dx&&(this.dx=c-g.scrollLeft,this.dx=0this.dy&&Math.abs(this.dy)e.x+(document.body.clientWidth||f.clientWidth)&&(b.div.style.left=Math.max(0,a.div.offsetLeft-d+(mxClient.IS_IE?6:-6))+"px");mxUtils.fit(b.div)}};
-mxPopupMenu.prototype.addSeparator=function(a,b){a=a||this;if(this.smartSeparators&&!b)a.willAddSeparator=!0;else if(null!=a.tbody){a.willAddSeparator=!1;var c=document.createElement("tr"),d=document.createElement("td");d.className="mxPopupMenuIcon";d.style.padding="0 0 0 0px";c.appendChild(d);d=document.createElement("td");d.style.padding="0 0 0 0px";d.setAttribute("colSpan","2");var e=document.createElement("hr");e.setAttribute("size","1");d.appendChild(e);c.appendChild(d);a.tbody.appendChild(c)}};
-mxPopupMenu.prototype.popup=function(a,b,c,d){if(null!=this.div&&null!=this.tbody&&null!=this.factoryMethod){this.div.style.left=a+"px";for(this.div.style.top=b+"px";null!=this.tbody.firstChild;)mxEvent.release(this.tbody.firstChild),this.tbody.removeChild(this.tbody.firstChild);this.itemCount=0;this.factoryMethod(this,c,d);0this.autoSaveDelay||this.ignoredChanges>=this.autoSaveThreshold&&a>this.autoSaveThrottle?(this.save(),this.reset()):this.ignoredChanges++};mxAutoSaveManager.prototype.reset=function(){this.lastSnapshot=(new Date).getTime();this.ignoredChanges=0};mxAutoSaveManager.prototype.destroy=function(){this.setGraph(null)};
-function mxAnimation(a){this.delay=null!=a?a:20}mxAnimation.prototype=new mxEventSource;mxAnimation.prototype.constructor=mxAnimation;mxAnimation.prototype.delay=null;mxAnimation.prototype.thread=null;mxAnimation.prototype.isRunning=function(){return null!=this.thread};mxAnimation.prototype.startAnimation=function(){null==this.thread&&(this.thread=window.setInterval(mxUtils.bind(this,this.updateAnimation),this.delay))};mxAnimation.prototype.updateAnimation=function(){this.fireEvent(new mxEventObject(mxEvent.EXECUTE))};
-mxAnimation.prototype.stopAnimation=function(){null!=this.thread&&(window.clearInterval(this.thread),this.thread=null,this.fireEvent(new mxEventObject(mxEvent.DONE)))};function mxMorphing(a,b,c,d){mxAnimation.call(this,d);this.graph=a;this.steps=null!=b?b:6;this.ease=null!=c?c:1.5}mxMorphing.prototype=new mxAnimation;mxMorphing.prototype.constructor=mxMorphing;mxMorphing.prototype.graph=null;mxMorphing.prototype.steps=null;mxMorphing.prototype.step=0;mxMorphing.prototype.ease=null;
-mxMorphing.prototype.cells=null;mxMorphing.prototype.updateAnimation=function(){mxAnimation.prototype.updateAnimation.apply(this,arguments);var a=new mxCellStatePreview(this.graph);if(null!=this.cells)for(var b=0;b=this.steps)&&this.stopAnimation()};mxMorphing.prototype.show=function(a){a.show()};
-mxMorphing.prototype.animateCell=function(a,b,c){var d=this.graph.getView().getState(a),e=null;if(null!=d&&(e=this.getDelta(d),this.graph.getModel().isVertex(a)&&(0!=e.x||0!=e.y))){var f=this.graph.view.getTranslate(),g=this.graph.view.getScale();e.x+=f.x*g;e.y+=f.y*g;b.moveState(d,-e.x/this.ease,-e.y/this.ease)}if(c&&!this.stopRecursion(d,e))for(d=this.graph.getModel().getChildCount(a),e=0;ec?";stop-opacity:"+c:"";e=this.createElement("stop");
-e.setAttribute("offset","0%");e.setAttribute("style","stop-color:"+a+c);f.appendChild(e);c=1>d?";stop-opacity:"+d:"";e=this.createElement("stop");e.setAttribute("offset","100%");e.setAttribute("style","stop-color:"+b+c);f.appendChild(e);return f};
-mxSvgCanvas2D.prototype.addNode=function(a,b){var c=this.node,d=this.state;if(null!=c){if("path"==c.nodeName)if(null!=this.path&&0a.alpha||1>a.fillAlpha)&&this.node.setAttribute("fill-opacity",a.alpha*a.fillAlpha);if(null!=a.fillColor)if(null!=a.gradientColor)if(a=this.getSvgGradient(String(a.fillColor),String(a.gradientColor),a.gradientFillAlpha,a.gradientAlpha,a.gradientDirection),this.root.ownerDocument==document&&this.useAbsoluteIds){var b=this.getBaseUrl().replace(/([\(\)])/g,"\\$1");this.node.setAttribute("fill","url("+b+"#"+a+")")}else this.node.setAttribute("fill",
-"url(#"+a+")");else this.node.setAttribute("fill",String(a.fillColor).toLowerCase())};mxSvgCanvas2D.prototype.getCurrentStrokeWidth=function(){return Math.max(this.minStrokeWidth,Math.max(.01,this.format(this.state.strokeWidth*this.state.scale)))};
-mxSvgCanvas2D.prototype.updateStroke=function(){var a=this.state;this.node.setAttribute("stroke",String(a.strokeColor).toLowerCase());(1>a.alpha||1>a.strokeAlpha)&&this.node.setAttribute("stroke-opacity",a.alpha*a.strokeAlpha);var b=this.getCurrentStrokeWidth();1!=b&&this.node.setAttribute("stroke-width",b);"path"==this.node.nodeName&&this.updateStrokeAttributes();a.dashed&&this.node.setAttribute("stroke-dasharray",this.createDashPattern((a.fixDash?1:a.strokeWidth)*a.scale))};
-mxSvgCanvas2D.prototype.updateStrokeAttributes=function(){var a=this.state;null!=a.lineJoin&&"miter"!=a.lineJoin&&this.node.setAttribute("stroke-linejoin",a.lineJoin);if(null!=a.lineCap){var b=a.lineCap;"flat"==b&&(b="butt");"butt"!=b&&this.node.setAttribute("stroke-linecap",b)}null==a.miterLimit||this.styleEnabled&&10==a.miterLimit||this.node.setAttribute("stroke-miterlimit",a.miterLimit)};
-mxSvgCanvas2D.prototype.createDashPattern=function(a){var b=[];if("string"===typeof this.state.dashPattern){var c=this.state.dashPattern.split(" ");if(0l.alpha||1>l.fillAlpha)&&m.setAttribute("opacity",l.alpha*l.fillAlpha);e=this.state.transform||"";if(g||k){var n=f=1,p=0,q=0;g&&(f=-1,p=-c-2*a);k&&(n=-1,q=-d-2*b);e+="scale("+f+","+n+")translate("+p*l.scale+","+q*l.scale+")"}0",5)+1)),""==a.substring(a.length-7,a.length)&&(a=a.substring(0,a.length-7)))}else{if(null!=document.implementation&&null!=document.implementation.createDocument){var b=document.implementation.createDocument("http://www.w3.org/1999/xhtml","html",null),c=b.createElement("body");
-b.documentElement.appendChild(c);var d=document.createElement("div");d.innerHTML=a;for(a=d.firstChild;null!=a;)d=a.nextSibling,c.appendChild(b.adoptNode(a)),a=d;return c.innerHTML}b=document.createElement("textarea");b.innerHTML=a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(//g,">");a=b.value.replace(/&/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,
-"&").replace(/
/g,"
").replace(/
/g,"
").replace(/(]+)>/gm,"$1 />")}return a}; -mxSvgCanvas2D.prototype.createDiv=function(a){mxUtils.isNode(a)||(a="
"+this.convertHtml(a)+"
");if(mxClient.IS_IE||mxClient.IS_IE11||!document.createElementNS)return mxUtils.isNode(a)&&(a="
"+mxUtils.getXml(a)+"
"),mxUtils.parseXml('
'+a+"
").documentElement;var b=document.createElementNS("http://www.w3.org/1999/xhtml","div");if(mxUtils.isNode(a)){var c=document.createElement("div"),d=c.cloneNode(!1);this.root.ownerDocument!= -document?c.appendChild(a.cloneNode(!0)):c.appendChild(a);d.appendChild(c);b.appendChild(d)}else b.innerHTML=a;return b};mxSvgCanvas2D.prototype.updateText=function(a,b,c,d,e,f,g,k,l,m,n){null!=n&&null!=n.firstChild&&null!=n.firstChild.firstChild&&this.updateTextNodes(a,b,c,d,e,f,g,k,l,m,n.firstChild)}; -mxSvgCanvas2D.prototype.addForeignObject=function(a,b,c,d,e,f,g,k,l,m,n,p,q,r,t){q=this.createElement("g");var u=this.createElement("foreignObject");u.setAttribute("style","overflow: visible; text-align: left;");u.setAttribute("pointer-events","none");r.ownerDocument!=document&&(r=mxUtils.importNodeImplementation(u.ownerDocument,r,!0));u.appendChild(r);q.appendChild(u);this.updateTextNodes(a,b,c,d,f,g,k,m,n,p,q);this.root.ownerDocument!=document&&(a=this.createAlternateContent(u,a,b,c,d,e,f,g,k,l, -m,n,p),null!=a&&(u.setAttribute("requiredFeatures","http://www.w3.org/TR/SVG11/feature#Extensibility"),b=this.createElement("switch"),b.appendChild(u),b.appendChild(a),q.appendChild(b)));t.appendChild(q)}; -mxSvgCanvas2D.prototype.updateTextNodes=function(a,b,c,d,e,f,g,k,l,m,n){var p=this.state.scale;mxSvgCanvas2D.createCss(c+2,d,e,f,g,k,l,null!=this.state.fontBackgroundColor?this.state.fontBackgroundColor:null,null!=this.state.fontBorderColor?this.state.fontBorderColor:null,"display: flex; align-items: unsafe "+(f==mxConstants.ALIGN_TOP?"flex-start":f==mxConstants.ALIGN_BOTTOM?"flex-end":"center")+"; justify-content: unsafe "+(e==mxConstants.ALIGN_LEFT?"flex-start":e==mxConstants.ALIGN_RIGHT?"flex-end": -"center")+"; ",this.getTextCss(),p,mxUtils.bind(this,function(c,d,e,f,g){a+=this.state.dx;b+=this.state.dy;var k=n.firstChild,l=k.firstChild,q=l.firstChild,r=(this.rotateHtml?this.state.rotation:0)+(null!=m?m:0),t=(0!=this.foOffset?"translate("+this.foOffset+" "+this.foOffset+")":"")+(1!=p?"scale("+p+")":"");q.firstChild.setAttribute("style",g);q.setAttribute("style",f);k.setAttribute("width",Math.ceil(1/Math.min(1,p)*100)+"%");k.setAttribute("height",Math.ceil(1/Math.min(1,p)*100)+"%");d=Math.round(b+ -d);0>d?k.setAttribute("y",d):(k.removeAttribute("y"),e+="padding-top: "+d+"px; ");l.setAttribute("style",e+"margin-left: "+Math.round(a+c)+"px;");t+=0!=r?"rotate("+r+" "+a+" "+b+")":"";""!=t?n.setAttribute("transform",t):n.removeAttribute("transform");1!=this.state.alpha?n.setAttribute("opacity",this.state.alpha):n.removeAttribute("opacity")}))}; -mxSvgCanvas2D.createCss=function(a,b,c,d,e,f,g,k,l,m,n,p,q){p="box-sizing: border-box; font-size: 0; text-align: "+(c==mxConstants.ALIGN_LEFT?"left":c==mxConstants.ALIGN_RIGHT?"right":"center")+"; ";var r=mxUtils.getAlignmentAsPoint(c,d);c="overflow: hidden; ";var t="width: 1px; ",u="height: 1px; ",x=r.x*a,r=r.y*b;g?(t="width: "+Math.round(a)+"px; ",p+="max-height: "+Math.round(b)+"px; ",r=0):"fill"==f?(t="width: "+Math.round(a)+"px; ",u="height: "+Math.round(b)+"px; ",n+="width: 100%; height: 100%; ", -p+="width: "+Math.round(a-2)+"px; "+u):"width"==f?(t="width: "+Math.round(a-2)+"px; ",n+="width: 100%; ",p+=t,r=0,0k.alpha&&r.setAttribute("opacity",k.alpha);t=e.split("\n");p=Math.round(q*mxConstants.LINE_HEIGHT);var u=q+(t.length-1)*p;n=b+q-1;g==mxConstants.ALIGN_MIDDLE?"fill"==l?n-=d/2:(m=(this.matchHtmlAlignment&&m&&0"),document.body.appendChild(n),e=n.offsetWidth,f=n.offsetHeight,n.parentNode.removeChild(n),g==mxConstants.ALIGN_CENTER?c-=e/2:g==mxConstants.ALIGN_RIGHT&&(c-=e),k==mxConstants.ALIGN_MIDDLE?d-=f/2:k==mxConstants.ALIGN_BOTTOM&&(d-=f),n=new mxRectangle((c+1)*m.scale,(d+2)*m.scale,e*m.scale,(f+1)* -m.scale);null!=n&&(b=this.createElement("rect"),b.setAttribute("fill",m.fontBackgroundColor||"none"),b.setAttribute("stroke",m.fontBorderColor||"none"),b.setAttribute("x",Math.floor(n.x-1)),b.setAttribute("y",Math.floor(n.y-1)),b.setAttribute("width",Math.ceil(n.width+2)),b.setAttribute("height",Math.ceil(n.height)),m=null!=m.fontBorderColor?Math.max(1,this.format(m.scale)):0,b.setAttribute("stroke-width",m),this.root.ownerDocument==document&&1==mxUtils.mod(m,2)&&b.setAttribute("transform","translate(0.5, 0.5)"), -a.insertBefore(b,a.firstChild))}};mxSvgCanvas2D.prototype.stroke=function(){this.addNode(!1,!0)};mxSvgCanvas2D.prototype.fill=function(){this.addNode(!0,!1)};mxSvgCanvas2D.prototype.fillAndStroke=function(){this.addNode(!0,!0)};var mxVmlCanvas2D=function(a){mxAbstractCanvas2D.call(this);this.root=a};mxUtils.extend(mxVmlCanvas2D,mxAbstractCanvas2D);mxVmlCanvas2D.prototype.node=null;mxVmlCanvas2D.prototype.textEnabled=!0;mxVmlCanvas2D.prototype.moveOp="m";mxVmlCanvas2D.prototype.lineOp="l"; -mxVmlCanvas2D.prototype.curveOp="c";mxVmlCanvas2D.prototype.closeOp="x";mxVmlCanvas2D.prototype.rotatedHtmlBackground="";mxVmlCanvas2D.prototype.vmlScale=1;mxVmlCanvas2D.prototype.createElement=function(a){return document.createElement(a)};mxVmlCanvas2D.prototype.createVmlElement=function(a){return this.createElement(mxClient.VML_PREFIX+":"+a)}; -mxVmlCanvas2D.prototype.addNode=function(a,b){var c=this.node,d=this.state;if(null!=c){if("shape"==c.nodeName)if(null!=this.path&&0a.alpha||1>a.fillAlpha)b.opacity=a.alpha*a.fillAlpha*100+"%";return b}; -mxVmlCanvas2D.prototype.createStroke=function(){var a=this.state,b=this.createVmlElement("stroke");b.endcap=a.lineCap||"flat";b.joinstyle=a.lineJoin||"miter";b.miterlimit=a.miterLimit||"10";if(1>a.alpha||1>a.strokeAlpha)b.opacity=a.alpha*a.strokeAlpha*100+"%";a.dashed&&(b.dashstyle=this.getVmlDashStyle());return b};mxVmlCanvas2D.prototype.getVmlDashStyle=function(){var a="dash";if("string"===typeof this.state.dashPattern){var b=this.state.dashPattern.split(" ");0this.state.alpha||1>this.state.fillAlpha)a.style.filter+="alpha(opacity="+this.state.alpha*this.state.fillAlpha*100+")";this.root.appendChild(a)}; -mxVmlCanvas2D.prototype.createDiv=function(a,b,c,d){c=this.createElement("div");var e=this.state,f="";null!=e.fontBackgroundColor&&(f+="background-color:"+mxUtils.htmlEntities(e.fontBackgroundColor)+";");null!=e.fontBorderColor&&(f+="border:1px solid "+mxUtils.htmlEntities(e.fontBorderColor)+";");mxUtils.isNode(a)?c.appendChild(a):"fill"!=d&&"width"!=d?(d=this.createElement("div"),d.style.cssText=f,d.style.display=mxClient.IS_QUIRKS?"inline":"inline-block",d.style.zoom="1",d.style.textDecoration= -"inherit",d.innerHTML=a,c.appendChild(d)):(c.style.cssText=f,c.innerHTML=a);a=c.style;a.fontSize=e.fontSize/this.vmlScale+"px";a.fontFamily=e.fontFamily;a.color=e.fontColor;a.verticalAlign="top";a.textAlign=b||"left";a.lineHeight=mxConstants.ABSOLUTE_LINE_HEIGHT?e.fontSize*mxConstants.LINE_HEIGHT/this.vmlScale+"px":mxConstants.LINE_HEIGHT;(e.fontStyle&mxConstants.FONT_BOLD)==mxConstants.FONT_BOLD&&(a.fontWeight="bold");(e.fontStyle&mxConstants.FONT_ITALIC)==mxConstants.FONT_ITALIC&&(a.fontStyle="italic"); -(e.fontStyle&mxConstants.FONT_UNDERLINE)==mxConstants.FONT_UNDERLINE&&(a.textDecoration="underline");return c}; -mxVmlCanvas2D.prototype.text=function(a,b,c,d,e,f,g,k,l,m,n,p,q){if(this.textEnabled&&null!=e){var r=this.state;if("html"==l){null!=r.rotation&&(b=this.rotatePoint(a,b,r.rotation,r.rotationCx,r.rotationCy),a=b.x,b=b.y);8!=document.documentMode||mxClient.IS_EM?(a*=r.scale,b*=r.scale):(a+=r.dx,b+=r.dy,"fill"!=m&&g==mxConstants.ALIGN_TOP&&--b);l=8!=document.documentMode||mxClient.IS_EM?this.createElement("div"):this.createVmlElement("group");l.style.position="absolute";l.style.display="inline";l.style.left= -this.format(a)+"px";l.style.top=this.format(b)+"px";l.style.zoom=r.scale;var t=this.createElement("div");t.style.position="relative";t.style.display="inline";var u=mxUtils.getAlignmentAsPoint(f,g),x=u.x,u=u.y;e=this.createDiv(e,f,g,m);f=this.createElement("div");null!=q&&e.setAttribute("dir",q);if(k&&0y&&(y+=2*Math.PI);y%=Math.PI;y>Math.PI/2&&(y=Math.PI-y);g=Math.cos(y);var B=Math.sin(y);8!=document.documentMode||mxClient.IS_EM||(e.style.display="inline-block",f.style.display="inline-block",t.style.display="inline-block");e.style.visibility="hidden";e.style.position="absolute";document.body.appendChild(e);t=e;null!=t.firstChild&&"DIV"==t.firstChild.nodeName&&(t=t.firstChild);y=t.offsetWidth+3;t=t.offsetHeight;n?(c=Math.min(c,y),t= -Math.min(t,d)):c=y;k&&(e.style.width=c+"px");mxClient.IS_QUIRKS&&(n||"width"==m)&&t>d&&(t=d,e.style.height=t+"px");d=t;n=(d-d*g+c*-B)/2-q*c*(x+.5)+p*d*(u+.5);k=(c-c*g+d*-B)/2+p*c*(x+.5)+q*d*(u+.5);"group"==l.nodeName&&"DIV"==this.root.nodeName?(m=this.createElement("div"),m.style.display="inline-block",m.style.position="absolute",m.style.left=this.format(a+(k-c/2)*r.scale)+"px",m.style.top=this.format(b+(n-d/2)*r.scale)+"px",l.parentNode.appendChild(m),m.appendChild(l)):(r=8!=document.documentMode|| -mxClient.IS_EM?r.scale:1,l.style.left=this.format(a+(k-c/2)*r)+"px",l.style.top=this.format(b+(n-d/2)*r)+"px");f.style.filter="progid:DXImageTransform.Microsoft.Matrix(M11="+p+", M12="+q+", M21="+-q+", M22="+p+", sizingMethod='auto expand')";f.style.backgroundColor=this.rotatedHtmlBackground;1>this.state.alpha&&(f.style.filter+="alpha(opacity="+100*this.state.alpha+")");f.appendChild(e);e.style.position="";e.style.visibility=""}else 8!=document.documentMode||mxClient.IS_EM?(e.style.verticalAlign= -"top",1>this.state.alpha&&(l.style.filter="alpha(opacity="+100*this.state.alpha+")"),r=e.parentNode,e.style.visibility="hidden",document.body.appendChild(e),c=e.offsetWidth,t=e.offsetHeight,mxClient.IS_QUIRKS&&n&&t>d&&(t=d,e.style.height=t+"px"),d=t,e.style.visibility="",r.appendChild(e),l.style.left=this.format(a+c*x*this.state.scale)+"px",l.style.top=this.format(b+d*u*this.state.scale)+"px"):(1>this.state.alpha&&(e.style.filter="alpha(opacity="+100*this.state.alpha+")"),t.style.left=100*x+"%",t.style.top= -100*u+"%")}else this.plainText(a,b,c,d,mxUtils.htmlEntities(e,!1),f,g,k,l,m,n,p,q)}}; -mxVmlCanvas2D.prototype.plainText=function(a,b,c,d,e,f,g,k,l,m,n,p,q){k=this.state;a=(a+k.dx)*k.scale;b=(b+k.dy)*k.scale;c=this.createVmlElement("shape");c.style.width="1px";c.style.height="1px";c.stroked="false";d=this.createVmlElement("fill");d.color=k.fontColor;d.opacity=100*k.alpha+"%";c.appendChild(d);d=this.createVmlElement("path");d.textpathok="true";d.v="m "+this.format(0)+" "+this.format(0)+" l "+this.format(1)+" "+this.format(0);c.appendChild(d);d=this.createVmlElement("textpath");d.style.cssText= -"v-text-align:"+f;d.style.align=f;d.style.fontFamily=k.fontFamily;d.string=e;d.on="true";f=k.fontSize*k.scale/this.vmlScale;d.style.fontSize=f+"px";(k.fontStyle&mxConstants.FONT_BOLD)==mxConstants.FONT_BOLD&&(d.style.fontWeight="bold");(k.fontStyle&mxConstants.FONT_ITALIC)==mxConstants.FONT_ITALIC&&(d.style.fontStyle="italic");(k.fontStyle&mxConstants.FONT_UNDERLINE)==mxConstants.FONT_UNDERLINE&&(d.style.textDecoration="underline");e=e.split("\n");k=f+(e.length-1)*f*mxConstants.LINE_HEIGHT;f=e=0; -g==mxConstants.ALIGN_BOTTOM?f=-k/2:g!=mxConstants.ALIGN_MIDDLE&&(f=k/2);null!=p&&(c.style.rotation=p,g=Math.PI/180*p,e=Math.sin(g)*f,f*=Math.cos(g));c.appendChild(d);c.style.left=this.format(a-e)+"px";c.style.top=this.format(b+f)+"px";this.root.appendChild(c)};mxVmlCanvas2D.prototype.stroke=function(){this.addNode(!1,!0)};mxVmlCanvas2D.prototype.fill=function(){this.addNode(!0,!1)};mxVmlCanvas2D.prototype.fillAndStroke=function(){this.addNode(!0,!0)}; -function mxGuide(a,b){this.graph=a;this.setStates(b)}mxGuide.prototype.graph=null;mxGuide.prototype.states=null;mxGuide.prototype.horizontal=!0;mxGuide.prototype.vertical=!0;mxGuide.prototype.guideX=null;mxGuide.prototype.guideY=null;mxGuide.prototype.rounded=!1;mxGuide.prototype.tolerance=2;mxGuide.prototype.setStates=function(a){this.states=a};mxGuide.prototype.isEnabledForEvent=function(a){return!0}; -mxGuide.prototype.getGuideTolerance=function(a){return a&&this.graph.gridEnabled?this.graph.gridSize/2:this.tolerance};mxGuide.prototype.createGuideShape=function(a){a=new mxPolyline([],mxConstants.GUIDE_COLOR,mxConstants.GUIDE_STROKEWIDTH);a.isDashed=!0;return a};mxGuide.prototype.isStateIgnored=function(a){return!1}; -mxGuide.prototype.move=function(a,b,c,d){if(null!=this.states&&(this.horizontal||this.vertical)&&null!=a&&null!=b){d=function(c,d,e){var f=!1;e&&Math.abs(c-z)this.opacity&&(b+="alpha(opacity="+this.opacity+")");this.isShadow&&(b+="progid:DXImageTransform.Microsoft.dropShadow (OffX='"+Math.round(mxConstants.SHADOW_OFFSET_X*this.scale)+"', OffY='"+Math.round(mxConstants.SHADOW_OFFSET_Y*this.scale)+"', Color='"+mxConstants.VML_SHADOWCOLOR+"')");if(null!=this.fill&&this.fill!=mxConstants.NONE&&this.gradient&&this.gradient!=mxConstants.NONE){var c=this.fill,d=this.gradient,e="0",f={east:0,south:1, -west:2,north:3},g=null!=this.direction?f[this.direction]:0;null!=this.gradientDirection&&(g=mxUtils.mod(g+f[this.gradientDirection]-1,4));1==g?(e="1",f=c,c=d,d=f):2==g?(f=c,c=d,d=f):3==g&&(e="1");b+="progid:DXImageTransform.Microsoft.gradient(startColorStr='"+c+"', endColorStr='"+d+"', gradientType='"+e+"')"}a.style.filter=b}; -mxShape.prototype.updateHtmlColors=function(a){var b=this.stroke;null!=b&&b!=mxConstants.NONE?(a.style.borderColor=b,this.isDashed?a.style.borderStyle="dashed":0mxUtils.indexOf(f,l-1))){var p=Math.sqrt(n*n+m*m);a.lineTo(g.x+n*Math.min(d,p/2)/p,g.y+m*Math.min(d,p/2)/p);for(m=b[mxUtils.mod(l+ -1,b.length)];l
"));var l=!mxUtils.isNode(this.value)&&this.replaceLinefeeds&&"html"==k?l.replace(/\n/g,"
"):l,m=this.textDirection;m!=mxConstants.TEXT_DIRECTION_AUTO||g||(m=this.getAutoDirection());m!=mxConstants.TEXT_DIRECTION_LTR&&m!=mxConstants.TEXT_DIRECTION_RTL&&(m=null);a.text(d,e,f,c,l,this.align,this.valign,this.wrap,k,this.overflow,this.clipped,this.getTextRotation(),m)}}; -mxText.prototype.redraw=function(){if(this.visible&&this.checkBounds()&&this.cacheEnabled&&this.lastValue==this.value&&(mxUtils.isNode(this.value)||this.dialect==mxConstants.DIALECT_STRICTHTML))if("DIV"!=this.node.nodeName||!this.isHtmlAllowed()&&mxClient.IS_VML){var a=this.createCanvas();null!=a&&null!=a.updateText?(a.pointerEvents=this.pointerEvents,this.paint(a,!0),this.destroyCanvas(a),this.updateBoundingBox()):mxShape.prototype.redraw.apply(this,arguments)}else mxClient.IS_SVG?this.redrawHtmlShapeWithCss3(): -(this.updateSize(this.node,null==this.state||null==this.state.view.textDiv),mxClient.IS_IE&&(null==document.documentMode||8>=document.documentMode)?this.updateHtmlFilter():this.updateHtmlTransform()),this.updateBoundingBox();else mxShape.prototype.redraw.apply(this,arguments),mxUtils.isNode(this.value)||this.dialect==mxConstants.DIALECT_STRICTHTML?this.lastValue=this.value:this.lastValue=null}; -mxText.prototype.resetStyles=function(){mxShape.prototype.resetStyles.apply(this,arguments);this.color="black";this.align=mxConstants.ALIGN_CENTER;this.valign=mxConstants.ALIGN_MIDDLE;this.family=mxConstants.DEFAULT_FONTFAMILY;this.size=mxConstants.DEFAULT_FONTSIZE;this.fontStyle=mxConstants.DEFAULT_FONTSTYLE;this.spacingLeft=this.spacingBottom=this.spacingRight=this.spacingTop=this.spacing=2;this.horizontal=!0;delete this.background;delete this.border;this.textDirection=mxConstants.DEFAULT_TEXT_DIRECTION; -delete this.margin}; -mxText.prototype.apply=function(a){var b=this.spacing;mxShape.prototype.apply.apply(this,arguments);null!=this.style&&(this.fontStyle=mxUtils.getValue(this.style,mxConstants.STYLE_FONTSTYLE,this.fontStyle),this.family=mxUtils.getValue(this.style,mxConstants.STYLE_FONTFAMILY,this.family),this.size=mxUtils.getValue(this.style,mxConstants.STYLE_FONTSIZE,this.size),this.color=mxUtils.getValue(this.style,mxConstants.STYLE_FONTCOLOR,this.color),this.align=mxUtils.getValue(this.style,mxConstants.STYLE_ALIGN, -this.align),this.valign=mxUtils.getValue(this.style,mxConstants.STYLE_VERTICAL_ALIGN,this.valign),this.spacing=parseInt(mxUtils.getValue(this.style,mxConstants.STYLE_SPACING,this.spacing)),this.spacingTop=parseInt(mxUtils.getValue(this.style,mxConstants.STYLE_SPACING_TOP,this.spacingTop-b))+this.spacing,this.spacingRight=parseInt(mxUtils.getValue(this.style,mxConstants.STYLE_SPACING_RIGHT,this.spacingRight-b))+this.spacing,this.spacingBottom=parseInt(mxUtils.getValue(this.style,mxConstants.STYLE_SPACING_BOTTOM, -this.spacingBottom-b))+this.spacing,this.spacingLeft=parseInt(mxUtils.getValue(this.style,mxConstants.STYLE_SPACING_LEFT,this.spacingLeft-b))+this.spacing,this.horizontal=mxUtils.getValue(this.style,mxConstants.STYLE_HORIZONTAL,this.horizontal),this.background=mxUtils.getValue(this.style,mxConstants.STYLE_LABEL_BACKGROUNDCOLOR,this.background),this.border=mxUtils.getValue(this.style,mxConstants.STYLE_LABEL_BORDERCOLOR,this.border),this.textDirection=mxUtils.getValue(this.style,mxConstants.STYLE_TEXT_DIRECTION, -mxConstants.DEFAULT_TEXT_DIRECTION),this.opacity=mxUtils.getValue(this.style,mxConstants.STYLE_TEXT_OPACITY,100),this.updateMargin());this.flipH=this.flipV=null};mxText.prototype.getAutoDirection=function(){var a=/[A-Za-z\u05d0-\u065f\u066a-\u06ef\u06fa-\u07ff\ufb1d-\ufdff\ufe70-\ufefc]/.exec(this.value);return null!=a&&0
");return a=this.replaceLinefeeds?a.replace(/\n/g,"
"):a}; -mxText.prototype.getTextCss=function(){var a="display: inline-block; font-size: "+this.size+"px; font-family: "+this.family+"; color: "+this.color+"; line-height: "+(mxConstants.ABSOLUTE_LINE_HEIGHT?this.size*mxConstants.LINE_HEIGHT+"px":mxConstants.LINE_HEIGHT)+"; pointer-events: "+(this.pointerEvents?"all":"none")+"; ";(this.fontStyle&mxConstants.FONT_BOLD)==mxConstants.FONT_BOLD&&(a+="font-weight: bold; ");(this.fontStyle&mxConstants.FONT_ITALIC)==mxConstants.FONT_ITALIC&&(a+="font-style: italic; "); -var b=[];(this.fontStyle&mxConstants.FONT_UNDERLINE)==mxConstants.FONT_UNDERLINE&&b.push("underline");(this.fontStyle&mxConstants.FONT_STRIKETHROUGH)==mxConstants.FONT_STRIKETHROUGH&&b.push("line-through");0=document.documentMode)?this.updateHtmlFilter():this.updateHtmlTransform()}}; -mxText.prototype.redrawHtmlShapeWithCss3=function(){var a=Math.max(0,Math.round(this.bounds.width/this.scale)),b=Math.max(0,Math.round(this.bounds.height/this.scale)),c="position: absolute; left: "+Math.round(this.bounds.x)+"px; top: "+Math.round(this.bounds.y)+"px; pointer-events: none; ",d=this.getTextCss();mxSvgCanvas2D.createCss(a+2,b,this.align,this.valign,this.wrap,this.overflow,this.clipped,null!=this.background?mxUtils.htmlEntities(this.background):null,null!=this.border?mxUtils.htmlEntities(this.border): -null,c,d,this.scale,mxUtils.bind(this,function(a,c,d,k,l,m){a=this.getTextRotation();a=(1!=this.scale?"scale("+this.scale+") ":"")+(0!=a?"rotate("+a+"deg) ":"")+(0!=this.margin.x||0!=this.margin.y?"translate("+100*this.margin.x+"%,"+100*this.margin.y+"%)":"");""!=a&&(a="transform-origin: 0 0; transform: "+a+"; ");"block"==this.overflow&&this.valign==mxConstants.ALIGN_MIDDLE&&(a+="max-height: "+(b+1)+"px;");""==m?(d+=k,k="display:inline-block; min-width: 100%; "+a):(k+=a,mxClient.IS_SF&&(k+="-webkit-clip-path: content-box;")); -"block"==this.overflow&&(k+="width: 100%; ");100>this.opacity&&(l+="opacity: "+this.opacity/100+"; ");this.node.setAttribute("style",d);d=mxUtils.isNode(this.value)?this.value.outerHTML:this.getHtmlValue();null==this.node.firstChild&&(this.node.innerHTML="
"+d+"
",mxClient.IS_IE11&&this.fixFlexboxForIe11(this.node));this.node.firstChild.firstChild.setAttribute("style",l);this.node.firstChild.setAttribute("style",k)}))}; -mxText.prototype.fixFlexboxForIe11=function(a){for(var b=a.querySelectorAll('div[style*="display: flex; justify-content: flex-end;"]'),c=0;cthis.opacity?this.opacity/100:""}; -mxText.prototype.updateInnerHtml=function(a){if(mxUtils.isNode(this.value))a.innerHTML=this.value.outerHTML;else{var b=this.value;this.dialect!=mxConstants.DIALECT_STRICTHTML&&(b=mxUtils.htmlEntities(b,!1));b=mxUtils.replaceTrailingNewlines(b,"
 
");b=this.replaceLinefeeds?b.replace(/\n/g,"
"):b;a.innerHTML='
'+b+"
"}}; -mxText.prototype.updateHtmlFilter=function(){var a=this.node.style,b=this.margin.x,c=this.margin.y,d=this.scale;mxUtils.setOpacity(this.node,this.opacity);var e,f=0,g=null!=this.state?this.state.view.textDiv:null,k=this.node;if(null!=g){g.style.overflow="";g.style.height="";g.style.width="";this.updateFont(g);this.updateSize(g,!1);this.updateInnerHtml(g);var l=Math.round(this.bounds.width/this.scale);this.wrap&&0m&&(m+=2*Math.PI);m%=Math.PI;m>Math.PI/2&&(m=Math.PI-m);var k=Math.cos(m),n=Math.sin(-m),b=l*-(b+.5),p=g*-(c+.5);0!=m&&(c="progid:DXImageTransform.Microsoft.Matrix(M11="+e+", M12="+f+", M21="+-f+", M22="+e+", sizingMethod='auto expand')",a.filter=null!=a.filter&&0
"),a=this.replaceLinefeeds?a.replace(/\n/g,"
"):a,b=null!=this.background&&this.background!=mxConstants.NONE?this.background:null,c=null!=this.border&&this.border!=mxConstants.NONE?this.border:null;if("fill"==this.overflow|| -"width"==this.overflow)null!=b&&(this.node.style.backgroundColor=b),null!=c&&(this.node.style.border="1px solid "+c);else{var d="";null!=b&&(d+="background-color:"+mxUtils.htmlEntities(b)+";");null!=c&&(d+="border:1px solid "+mxUtils.htmlEntities(c)+";");a='
'+a+"
"}this.node.innerHTML= -a;a=this.node.getElementsByTagName("div");0=document.documentMode)&&0!=this.rotation?mxClient.VML_PREFIX+":image":"img");a.setAttribute("border","0");a.style.position="absolute";a.src=this.image;b=100>this.opacity?"alpha(opacity="+this.opacity+")":"";this.node.style.filter=b;this.flipH&&this.flipV?b+="progid:DXImageTransform.Microsoft.BasicImage(rotation=2)":this.flipH?b+="progid:DXImageTransform.Microsoft.BasicImage(mirror=1)":this.flipV&& -(b+="progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)");a.style.filter!=b&&(a.style.filter=b);"image"==a.nodeName?a.style.rotation=this.rotation:0!=this.rotation?mxUtils.setPrefixedStyle(a.style,"transform","rotate("+this.rotation+"deg)"):mxUtils.setPrefixedStyle(a.style,"transform","");a.style.width=this.node.style.width;a.style.height=this.node.style.height;this.node.style.backgroundImage="";this.node.appendChild(a)}else this.setTransparentBackgroundImage(this.node)}; -function mxLabel(a,b,c,d){mxRectangleShape.call(this,a,b,c,d)}mxUtils.extend(mxLabel,mxRectangleShape);mxLabel.prototype.imageSize=mxConstants.DEFAULT_IMAGESIZE;mxLabel.prototype.spacing=2;mxLabel.prototype.indicatorSize=10;mxLabel.prototype.indicatorSpacing=2;mxLabel.prototype.init=function(a){mxShape.prototype.init.apply(this,arguments);null!=this.indicatorShape&&(this.indicator=new this.indicatorShape,this.indicator.dialect=this.dialect,this.indicator.init(this.node))}; -mxLabel.prototype.redraw=function(){null!=this.indicator&&(this.indicator.fill=this.indicatorColor,this.indicator.stroke=this.indicatorStrokeColor,this.indicator.gradient=this.indicatorGradientColor,this.indicator.direction=this.indicatorDirection,this.indicator.redraw());mxShape.prototype.redraw.apply(this,arguments)};mxLabel.prototype.isHtmlAllowed=function(){return mxRectangleShape.prototype.isHtmlAllowed.apply(this,arguments)&&null==this.indicatorColor&&null==this.indicatorShape}; -mxLabel.prototype.paintForeground=function(a,b,c,d,e){this.paintImage(a,b,c,d,e);this.paintIndicator(a,b,c,d,e);mxRectangleShape.prototype.paintForeground.apply(this,arguments)};mxLabel.prototype.paintImage=function(a,b,c,d,e){null!=this.image&&(b=this.getImageBounds(b,c,d,e),a.image(b.x,b.y,b.width,b.height,this.image,!1,!1,!1))}; -mxLabel.prototype.getImageBounds=function(a,b,c,d){var e=mxUtils.getValue(this.style,mxConstants.STYLE_IMAGE_ALIGN,mxConstants.ALIGN_LEFT),f=mxUtils.getValue(this.style,mxConstants.STYLE_IMAGE_VERTICAL_ALIGN,mxConstants.ALIGN_MIDDLE),g=mxUtils.getNumber(this.style,mxConstants.STYLE_IMAGE_WIDTH,mxConstants.DEFAULT_IMAGESIZE),k=mxUtils.getNumber(this.style,mxConstants.STYLE_IMAGE_HEIGHT,mxConstants.DEFAULT_IMAGESIZE),l=mxUtils.getNumber(this.style,mxConstants.STYLE_SPACING,this.spacing)+5;a=e==mxConstants.ALIGN_CENTER? -a+(c-g)/2:e==mxConstants.ALIGN_RIGHT?a+(c-g-l):a+l;b=f==mxConstants.ALIGN_TOP?b+l:f==mxConstants.ALIGN_BOTTOM?b+(d-k-l):b+(d-k)/2;return new mxRectangle(a,b,g,k)};mxLabel.prototype.paintIndicator=function(a,b,c,d,e){null!=this.indicator?(this.indicator.bounds=this.getIndicatorBounds(b,c,d,e),this.indicator.paint(a)):null!=this.indicatorImage&&(b=this.getIndicatorBounds(b,c,d,e),a.image(b.x,b.y,b.width,b.height,this.indicatorImage,!1,!1,!1))}; -mxLabel.prototype.getIndicatorBounds=function(a,b,c,d){var e=mxUtils.getValue(this.style,mxConstants.STYLE_IMAGE_ALIGN,mxConstants.ALIGN_LEFT),f=mxUtils.getValue(this.style,mxConstants.STYLE_IMAGE_VERTICAL_ALIGN,mxConstants.ALIGN_MIDDLE),g=mxUtils.getNumber(this.style,mxConstants.STYLE_INDICATOR_WIDTH,this.indicatorSize),k=mxUtils.getNumber(this.style,mxConstants.STYLE_INDICATOR_HEIGHT,this.indicatorSize),l=this.spacing+5;a=e==mxConstants.ALIGN_RIGHT?a+(c-g-l):e==mxConstants.ALIGN_CENTER?a+(c-g)/ -2:a+l;b=f==mxConstants.ALIGN_BOTTOM?b+(d-k-l):f==mxConstants.ALIGN_TOP?b+l:b+(d-k)/2;return new mxRectangle(a,b,g,k)}; -mxLabel.prototype.redrawHtmlShape=function(){for(mxRectangleShape.prototype.redrawHtmlShape.apply(this,arguments);this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);if(null!=this.image){var a=document.createElement("img");a.style.position="relative";a.setAttribute("border","0");var b=this.getImageBounds(this.bounds.x,this.bounds.y,this.bounds.width,this.bounds.height);b.x-=this.bounds.x;b.y-=this.bounds.y;a.style.left=Math.round(b.x)+"px";a.style.top=Math.round(b.y)+"px";a.style.width= -Math.round(b.width)+"px";a.style.height=Math.round(b.height)+"px";a.src=this.image;this.node.appendChild(a)}};function mxCylinder(a,b,c,d){mxShape.call(this);this.bounds=a;this.fill=b;this.stroke=c;this.strokewidth=null!=d?d:1}mxUtils.extend(mxCylinder,mxShape);mxCylinder.prototype.maxHeight=40;mxCylinder.prototype.svgStrokeTolerance=0; -mxCylinder.prototype.paintVertexShape=function(a,b,c,d,e){a.translate(b,c);a.begin();this.redrawPath(a,b,c,d,e,!1);a.fillAndStroke();this.outline&&null!=this.style&&0!=mxUtils.getValue(this.style,mxConstants.STYLE_BACKGROUND_OUTLINE,0)||(a.setShadow(!1),a.begin(),this.redrawPath(a,b,c,d,e,!0),a.stroke())};mxCylinder.prototype.getCylinderSize=function(a,b,c,d){return Math.min(this.maxHeight,Math.round(d/5))}; -mxCylinder.prototype.redrawPath=function(a,b,c,d,e,f){b=this.getCylinderSize(b,c,d,e);if(f&&null!=this.fill||!f&&null==this.fill)a.moveTo(0,b),a.curveTo(0,2*b,d,2*b,d,b),f||(a.stroke(),a.begin());f||(a.moveTo(0,b),a.curveTo(0,-b/3,d,-b/3,d,b),a.lineTo(d,e-b),a.curveTo(d,e+b/3,0,e+b/3,0,e-b),a.close())};function mxConnector(a,b,c){mxPolyline.call(this,a,b,c)}mxUtils.extend(mxConnector,mxPolyline); -mxConnector.prototype.updateBoundingBox=function(){this.useSvgBoundingBox=null!=this.style&&1==this.style[mxConstants.STYLE_CURVED];mxShape.prototype.updateBoundingBox.apply(this,arguments)};mxConnector.prototype.paintEdgeShape=function(a,b){var c=this.createMarker(a,b,!0),d=this.createMarker(a,b,!1);mxPolyline.prototype.paintEdgeShape.apply(this,arguments);a.setFillColor(this.stroke);a.setShadow(!1);a.setDashed(!1);null!=c&&c();null!=d&&d()}; -mxConnector.prototype.createMarker=function(a,b,c){var d=null,e=b.length,f=mxUtils.getValue(this.style,c?mxConstants.STYLE_STARTARROW:mxConstants.STYLE_ENDARROW),g=c?b[1]:b[e-2],k=c?b[0]:b[e-1];if(null!=f&&null!=g&&null!=k){for(d=1;da.weightedValue?-1:b.weightedValuec)break;g=l}}f=e.getIndex(a);f=Math.max(0,b-(b>f?1:0));d.add(e,a,f)}}; -mxStackLayout.prototype.getParentSize=function(a){var b=this.graph.getModel(),c=b.getGeometry(a);null!=this.graph.container&&(null==c&&b.isLayer(a)||a==this.graph.getView().currentRoot)&&(c=new mxRectangle(0,0,this.graph.container.offsetWidth-1,this.graph.container.offsetHeight-1));return c}; -mxStackLayout.prototype.getLayoutCells=function(a){for(var b=this.graph.getModel(),c=b.getChildCount(a),d=[],e=0;ed.x>0?1:-1:c.y==d.y?0:c.y>d.y>0?1:-1}));return d}; -mxStackLayout.prototype.snap=function(a){if(null!=this.gridSize&&0this.gridSize/2?this.gridSize-b:-b}return a}; -mxStackLayout.prototype.execute=function(a){if(null!=a){var b=this.getParentSize(a),c=this.isHorizontal(),d=this.graph.getModel(),e=null;null!=b&&(e=c?b.height-this.marginTop-this.marginBottom:b.width-this.marginLeft-this.marginRight);var e=e-2*this.border,f=this.x0+this.border+this.marginLeft,g=this.y0+this.border+this.marginTop;if(this.graph.isSwimlane(a)){var k=this.graph.getCellStyle(a),l=mxUtils.getNumber(k,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_STARTSIZE),k=1==mxUtils.getValue(k,mxConstants.STYLE_HORIZONTAL, -!0);null!=b&&(l=k?Math.min(l,b.height):Math.min(l,b.width));c==k&&(e-=l);k?g+=l:f+=l}d.beginUpdate();try{for(var l=0,k=null,m=0,n=null,p=this.getLayoutCells(a),q=0;qthis.wrap||!c&&k.y+k.height+t.height+2*this.spacing>this.wrap)&&(k=null,c?g+=l+this.spacing:f+=l+this.spacing,l=0);var l=Math.max(l,c?t.height:t.width),u=0;if(!this.borderCollapse)var x=this.graph.getCellStyle(r), -u=mxUtils.getNumber(x,mxConstants.STYLE_STROKEWIDTH,1);if(null!=k){var y=m+this.spacing+Math.floor(u/2);c?t.x=this.snap((this.allowGaps?Math.max(y,t.x):y)-this.marginLeft)+this.marginLeft:t.y=this.snap((this.allowGaps?Math.max(y,t.y):y)-this.marginTop)+this.marginTop}else this.keepFirstLocation||(c?t.x=this.allowGaps&&t.x>f?Math.max(this.snap(t.x-this.marginLeft)+this.marginLeft,f):f:t.y=this.allowGaps&&t.y>g?Math.max(this.snap(t.y-this.marginTop)+this.marginTop,g):g);c?t.y=g:t.x=f;this.fill&&null!= -e&&(c?t.height=e:t.width=e);c?t.width=this.snap(t.width):t.height=this.snap(t.height);this.setChildGeometry(r,t);n=r;k=t;m=c?k.x+k.width+Math.floor(u/2):k.y+k.height+Math.floor(u/2)}}this.resizeParent&&null!=b&&null!=k&&!this.graph.isCellCollapsed(a)?this.updateParentGeometry(a,b,k):this.resizeLast&&null!=b&&null!=k&&null!=n&&(c?k.width=b.width-k.x-this.spacing-this.marginRight-this.marginLeft:k.height=b.height-k.y-this.spacing-this.marginBottom,this.setChildGeometry(n,k))}finally{d.endUpdate()}}}; -mxStackLayout.prototype.setChildGeometry=function(a,b){var c=this.graph.getCellGeometry(a);null!=c&&b.x==c.x&&b.y==c.y&&b.width==c.width&&b.height==c.height||this.graph.getModel().setGeometry(a,b)}; -mxStackLayout.prototype.updateParentGeometry=function(a,b,c){var d=this.isHorizontal(),e=this.graph.getModel(),f=b.clone();d?(c=c.x+c.width+this.marginRight+this.border,f.width=this.resizeParentMax?Math.max(f.width,c):c):(c=c.y+c.height+this.marginBottom+this.border,f.height=this.resizeParentMax?Math.max(f.height,c):c);b.x==f.x&&b.y==f.y&&b.width==f.width&&b.height==f.height||e.setGeometry(a,f)}; -function mxPartitionLayout(a,b,c,d){mxGraphLayout.call(this,a);this.horizontal=null!=b?b:!0;this.spacing=c||0;this.border=d||0}mxPartitionLayout.prototype=new mxGraphLayout;mxPartitionLayout.prototype.constructor=mxPartitionLayout;mxPartitionLayout.prototype.horizontal=null;mxPartitionLayout.prototype.spacing=null;mxPartitionLayout.prototype.border=null;mxPartitionLayout.prototype.resizeVertices=!0;mxPartitionLayout.prototype.isHorizontal=function(){return this.horizontal}; -mxPartitionLayout.prototype.moveCell=function(a,b,c){c=this.graph.getModel();var d=c.getParent(a);if(null!=a&&null!=d){var e,f=0,g=c.getChildCount(d);for(e=0;eb)break;f=k}}b=d.getIndex(a);b=Math.max(0,e-(e>b?1:0));c.add(d,a,b)}}; -mxPartitionLayout.prototype.execute=function(a){var b=this.isHorizontal(),c=this.graph.getModel(),d=c.getGeometry(a);null!=this.graph.container&&(null==d&&c.isLayer(a)||a==this.graph.getView().currentRoot)&&(d=new mxRectangle(0,0,this.graph.container.offsetWidth-1,this.graph.container.offsetHeight-1));if(null!=d){for(var e=[],f=c.getChildCount(a),g=0;gk.x&&(e=Math.abs(g-k.x));0>k.y&&(l=Math.abs(d-k.y));0==e&&0==l||this.moveNode(this.node,e,l);this.resizeParent&&this.adjustParents();this.edgeRouting&&this.localEdgeProcessing(this.node)}null!=this.parentX&&null!=this.parentY&&(f=this.graph.getCellGeometry(a),null!=f&&(f=f.clone(),f.x=this.parentX,f.y=this.parentY,c.setGeometry(a,f)))}}finally{c.endUpdate()}}}; -mxCompactTreeLayout.prototype.moveNode=function(a,b,c){a.x+=b;a.y+=c;this.apply(a);for(a=a.child;null!=a;)this.moveNode(a,b,c),a=a.next}; -mxCompactTreeLayout.prototype.sortOutgoingEdges=function(a,b){var c=new mxDictionary;b.sort(function(b,e){var d=b.getTerminal(b.getTerminal(!1)==a),g=c.get(d);null==g&&(g=mxCellPath.create(d).split(mxCellPath.PATH_SEPARATOR),c.put(d,g));var d=e.getTerminal(e.getTerminal(!1)==a),k=c.get(d);null==k&&(k=mxCellPath.create(d).split(mxCellPath.PATH_SEPARATOR),c.put(d,k));return mxCellPath.compare(g,k)})}; -mxCompactTreeLayout.prototype.findRankHeights=function(a,b){if(null==this.maxRankHeight[b]||this.maxRankHeight[b]a.height&&(a.height=this.maxRankHeight[b]);for(var c=a.child;null!=c;)this.setCellHeights(c,b+1),c=c.next}; -mxCompactTreeLayout.prototype.dfs=function(a,b){var c=mxCellPath.create(a),d=null;if(null!=a&&null==this.visited[c]&&!this.isVertexIgnored(a)){this.visited[c]=a;var d=this.createNode(a),c=this.graph.getModel(),e=null,f=this.graph.getEdges(a,b,this.invert,!this.invert,!1,!0),g=this.graph.getView();this.sortEdges&&this.sortOutgoingEdges(a,f);for(var k=0;k=a+c)return 0;a=0a?a*d/c-b:0a+c?(c+a)*f/e-(b+d):f-(b+d);return 0g+2*this.prefHozEdgeSep&&(f-=2*this.prefHozEdgeSep);a=f/d;b=a/2;f>g+2*this.prefHozEdgeSep&&(b+=this.prefHozEdgeSep);for(var f=this.minEdgeJetty-this.prefVertEdgeOff,g=this.getVertexBounds(c),k=0;kd/2&&(f-=this.prefVertEdgeOff);b+=a}}; -function mxRadialTreeLayout(a){mxCompactTreeLayout.call(this,a,!1)}mxUtils.extend(mxRadialTreeLayout,mxCompactTreeLayout);mxRadialTreeLayout.prototype.angleOffset=.5;mxRadialTreeLayout.prototype.rootx=0;mxRadialTreeLayout.prototype.rooty=0;mxRadialTreeLayout.prototype.levelDistance=120;mxRadialTreeLayout.prototype.nodeDistance=10;mxRadialTreeLayout.prototype.autoRadius=!1;mxRadialTreeLayout.prototype.sortEdges=!1;mxRadialTreeLayout.prototype.rowMinX=[];mxRadialTreeLayout.prototype.rowMaxX=[]; -mxRadialTreeLayout.prototype.rowMinCenX=[];mxRadialTreeLayout.prototype.rowMaxCenX=[];mxRadialTreeLayout.prototype.rowRadi=[];mxRadialTreeLayout.prototype.row=[];mxRadialTreeLayout.prototype.isVertexIgnored=function(a){return mxGraphLayout.prototype.isVertexIgnored.apply(this,arguments)||0==this.graph.getConnections(a).length}; -mxRadialTreeLayout.prototype.execute=function(a,b){this.parent=a;this.edgeRouting=this.useBoundingBox=!1;mxCompactTreeLayout.prototype.execute.apply(this,arguments);var c=null,d=this.getVertexBounds(this.root);this.centerX=d.x+d.width/2;this.centerY=d.y+d.height/2;for(var e in this.visited){var f=this.getVertexBounds(this.visited[e]),c=null!=c?c:f.clone();c.add(f)}this.calcRowDims([this.node],0);for(var g=0,k=0,c=0;c -d.theta&&ethis.forceConstant&&(this.forceConstant= -.001);this.forceConstantSquared=this.forceConstant*this.forceConstant;for(d=0;db&&(b=.001);var c=this.dispX[a]/b*Math.min(b,this.temperature),b=this.dispY[a]/b*Math.min(b,this.temperature);this.dispX[a]=0;this.dispY[a]=0;this.cellLocation[a][0]+=c;this.cellLocation[a][1]+=b}}; -mxFastOrganicLayout.prototype.calcAttraction=function(){for(var a=0;athis.maxDistanceLimit||(gb?b+"-"+c:c+"-"+b)+d}return null}; -mxParallelEdgeLayout.prototype.layout=function(a){var b=a[0],c=this.graph.getView(),d=this.graph.getModel(),e=d.getGeometry(c.getVisibleTerminal(b,!0)),d=d.getGeometry(c.getVisibleTerminal(b,!1));if(e==d)for(var b=e.x+e.width+this.spacing,c=e.y+e.height/2,f=0;fmxUtils.indexOf(l.connectsAsTarget,g)&&l.connectsAsTarget.push(g))}}c[d].temp[0]=1}}mxGraphHierarchyModel.prototype.maxRank=null;mxGraphHierarchyModel.prototype.vertexMapper=null;mxGraphHierarchyModel.prototype.edgeMapper=null;mxGraphHierarchyModel.prototype.ranks=null;mxGraphHierarchyModel.prototype.roots=null;mxGraphHierarchyModel.prototype.parent=null; -mxGraphHierarchyModel.prototype.dfsCount=0;mxGraphHierarchyModel.prototype.SOURCESCANSTARTRANK=1E8;mxGraphHierarchyModel.prototype.tightenToSource=!1; -mxGraphHierarchyModel.prototype.createInternalCells=function(a,b,c){for(var d=a.getGraph(),e=0;e=l.length){for(var k= -new mxGraphHierarchyEdge(l),m=0;mmxUtils.indexOf(c[e].connectsAsSource,k)&&c[e].connectsAsSource.push(k)}}}c[e].temp[0]=0}}; -mxGraphHierarchyModel.prototype.initialRank=function(){var a=[];if(null!=this.roots)for(var b=0;bc.maxRank&&0>c.minRank&&(a[c.temp[0]].push(c),c.maxRank=c.temp[0],c.minRank=c.temp[0],c.temp[0]=a[c.maxRank].length-1);if(null!=b&&null!=d&&1mxUtils.indexOf(l.connectsAsTarget,g)&&l.connectsAsTarget.push(g))}}c[d].temp[0]=1}}mxSwimlaneModel.prototype.maxRank=null;mxSwimlaneModel.prototype.vertexMapper=null;mxSwimlaneModel.prototype.edgeMapper=null;mxSwimlaneModel.prototype.ranks=null;mxSwimlaneModel.prototype.roots=null;mxSwimlaneModel.prototype.parent=null;mxSwimlaneModel.prototype.dfsCount=0; -mxSwimlaneModel.prototype.SOURCESCANSTARTRANK=1E8;mxSwimlaneModel.prototype.tightenToSource=!1;mxSwimlaneModel.prototype.ranksPerGroup=null; -mxSwimlaneModel.prototype.createInternalCells=function(a,b,c){for(var d=a.getGraph(),e=a.swimlanes,f=0;f=m.length){for(var l=new mxGraphHierarchyEdge(m),n=0;nmxUtils.indexOf(c[f].connectsAsSource,l)&&c[f].connectsAsSource.push(l)}}}c[f].temp[0]=0}}; -mxSwimlaneModel.prototype.initialRank=function(){this.ranksPerGroup=[];var a=[],b={};if(null!=this.roots)for(var c=0;cb[d.swimlaneIndex]&&(k=b[d.swimlaneIndex]);d.temp[0]=k;if(null!=f)for(c=0;cc.maxRank&&0>c.minRank&&(a[c.temp[0]].push(c),c.maxRank=c.temp[0],c.minRank=c.temp[0],c.temp[0]=a[c.maxRank].length-1);if(null!=b&&null!=d&&1>1,++e[l];return c}; -mxMedianHybridCrossingReduction.prototype.transpose=function(a,b){for(var c=!0,d=0;c&&10>d++;)for(var e=1==a%2&&1==d%2,c=!1,f=0;fn&&(n=l);k[n]=m}for(var p=null,q=null,r,t,u=null,x=null,y,B=null,l=0;lu[v]&&z++,r[A]x[v]&&z++,t[A]a.medianValue?-1:b.medianValuex+1&&(m==d[l].length-1?(e.setGeneralPurposeVariable(l,y),p=!0):(m=d[l][m+1],x=m.getGeneralPurposeVariable(l),x=x-m.width/2-this.intraCellSpacing-e.width/2,x>y?(e.setGeneralPurposeVariable(l, -y),p=!0):x>e.getGeneralPurposeVariable(l)+1&&(e.setGeneralPurposeVariable(l,x),p=!0)));if(p){for(e=0;e=k&&l<=q?g.setGeneralPurposeVariable(a,l):lq&&(g.setGeneralPurposeVariable(a,q),this.currentXDelta+=l-q);d[f].visited=!0}};mxCoordinateAssignment.prototype.calculatedWeightedValue=function(a,b){for(var c=0,d=0;dthis.widestRankValue&&(this.widestRankValue=k,this.widestRank=e);this.rankWidths[e]=k}1==l&&mxLog.warn("At least one cell has no bounds");this.rankY[e]=c;k=f/2+d/2+this.interRankCellSpacing;d=f;c=this.orientation==mxConstants.DIRECTION_NORTH||this.orientation==mxConstants.DIRECTION_WEST?c+k:c- -k;for(m=0;me.maxRank-e.minRank-1)){for(var f=e.getGeneralPurposeVariable(e.minRank+1),g=!0,k=0,l=e.minRank+2;le.minRank+1;l--)q=e.getX(l-1),p==q?(n[l-e.minRank-2]=p,g++):this.repositionValid(b,e,l-1,p)?(n[l-e.minRank-2]=p,g++):(n[l-e.minRank-2]=e.getX(l-1),p=q);if(g>k||f>k)if(g>=f)for(l=e.maxRank-2;l>e.minRank;l--)e.setX(l,n[l-e.minRank-1]);else if(f>g)for(l=e.minRank+2;le)return!1;f=b.getGeneralPurposeVariable(c);if(df){if(e==a.length-1)return!0;a=a[e+1];c=a.getGeneralPurposeVariable(c);c=c-a.width/2-this.intraCellSpacing-b.width/2;if(!(c>=d))return!1}return!0}; -mxCoordinateAssignment.prototype.setCellLocations=function(a,b){this.rankTopY=[];this.rankBottomY=[];for(var c=0;ck;k++){if(-1(f+1)*this.prefHozEdgeSep+2*this.prefHozEdgeSep&&(n+=this.prefHozEdgeSep,p-=this.prefHozEdgeSep);l=(p-n)/f;n+=l/2;p=this.minEdgeJetty-this.prefVertEdgeOff;for(m=0;mf/2&&(p-=this.prefVertEdgeOff),t=0;tf&&(f=l,e=k)}}0==c.length&&null!=e&&c.push(e)}return c}; -mxHierarchicalLayout.prototype.getEdges=function(a){var b=this.edgesCache.get(a);if(null!=b)return b;for(var c=this.graph.model,b=[],d=this.graph.isCellCollapsed(a),e=c.getChildCount(a),f=0;fb.length)){null==a&&(a=c.getParent(b[0]));this.parentY=this.parentX=null;if(a!=this.root&&null!=c.isVertex(a)&&this.maintainParentLocation){var d=this.graph.getCellGeometry(a);null!=d&&(this.parentX=d.x,this.parentY=d.y)}this.swimlanes=b;for(var e=[],f=0;ff&&(f=l,e=k)}}0==c.length&&null!=e&&c.push(e)}return c}; -mxSwimlaneLayout.prototype.getEdges=function(a){var b=this.edgesCache.get(a);if(null!=b)return b;for(var c=this.graph.model,b=[],d=this.graph.isCellCollapsed(a),e=c.getChildCount(a),f=0;f=this.swimlanes.length||!(q>k||(!b||p)&&q==k)||(e=this.traverse(n, -b,m[c],d,e,f,g,q))}}else if(null==e[l])for(c=0;cmxUtils.indexOf(this.edges,a))&&(null==this.edges&&(this.edges=[]),this.edges.push(a));return a};mxCell.prototype.removeEdge=function(a,b){if(null!=a){if(a.getTerminal(!b)!=this&&null!=this.edges){var c=this.getEdgeIndex(a);0<=c&&this.edges.splice(c,1)}a.setTerminal(null,b)}return a}; -mxCell.prototype.removeFromTerminal=function(a){var b=this.getTerminal(a);null!=b&&b.removeEdge(this,a)};mxCell.prototype.hasAttribute=function(a){var b=this.getValue();return null!=b&&b.nodeType==mxConstants.NODETYPE_ELEMENT&&b.hasAttribute?b.hasAttribute(a):null!=b.getAttribute(a)};mxCell.prototype.getAttribute=function(a,b){var c=this.getValue(),c=null!=c&&c.nodeType==mxConstants.NODETYPE_ELEMENT?c.getAttribute(a):null;return null!=c?c:b}; -mxCell.prototype.setAttribute=function(a,b){var c=this.getValue();null!=c&&c.nodeType==mxConstants.NODETYPE_ELEMENT&&c.setAttribute(a,b)};mxCell.prototype.clone=function(){var a=mxUtils.clone(this,this.mxTransient);a.setValue(this.cloneValue());return a};mxCell.prototype.cloneValue=function(){var a=this.getValue();null!=a&&("function"==typeof a.clone?a=a.clone():isNaN(a.nodeType)||(a=a.cloneNode(!0)));return a};function mxGeometry(a,b,c,d){mxRectangle.call(this,a,b,c,d)}mxGeometry.prototype=new mxRectangle; -mxGeometry.prototype.constructor=mxGeometry;mxGeometry.prototype.TRANSLATE_CONTROL_POINTS=!0;mxGeometry.prototype.alternateBounds=null;mxGeometry.prototype.sourcePoint=null;mxGeometry.prototype.targetPoint=null;mxGeometry.prototype.points=null;mxGeometry.prototype.offset=null;mxGeometry.prototype.relative=!1; -mxGeometry.prototype.swap=function(){if(null!=this.alternateBounds){var a=new mxRectangle(this.x,this.y,this.width,this.height);this.x=this.alternateBounds.x;this.y=this.alternateBounds.y;this.width=this.alternateBounds.width;this.height=this.alternateBounds.height;this.alternateBounds=a}};mxGeometry.prototype.getTerminalPoint=function(a){return a?this.sourcePoint:this.targetPoint};mxGeometry.prototype.setTerminalPoint=function(a,b){b?this.sourcePoint=a:this.targetPoint=a;return a}; -mxGeometry.prototype.rotate=function(a,b){var c=mxUtils.toRadians(a),d=Math.cos(c),c=Math.sin(c);if(!this.relative){var e=new mxPoint(this.getCenterX(),this.getCenterY()),e=mxUtils.getRotatedPoint(e,d,c,b);this.x=Math.round(e.x-this.width/2);this.y=Math.round(e.y-this.height/2)}null!=this.sourcePoint&&(e=mxUtils.getRotatedPoint(this.sourcePoint,d,c,b),this.sourcePoint.x=Math.round(e.x),this.sourcePoint.y=Math.round(e.y));null!=this.targetPoint&&(e=mxUtils.getRotatedPoint(this.targetPoint,d,c,b),this.targetPoint.x= -Math.round(e.x),this.targetPoint.y=Math.round(e.y));if(null!=this.points)for(var f=0;fb[e]?1:-1:(c=parseInt(a[e]),e=parseInt(b[e]),d=c==e?0:c>e?1:-1);break}0==d&&(c=a.length,e=b.length,c!=e&&(d=c>e?1:-1));return d}},mxPerimeter={RectanglePerimeter:function(a,b,c,d){b=a.getCenterX();var e=a.getCenterY(),f=Math.atan2(c.y-e,c.x-b),g=new mxPoint(0,0),k=Math.PI,l=Math.PI/2-f,m=Math.atan2(a.height,a.width);f<-k+m||f>k-m?(g.x=a.x,g.y=e-a.width* -Math.tan(f)/2):f<-m?(g.y=a.y,g.x=b-a.height*Math.tan(l)/2):f=a.x&&c.x<=a.x+a.width?g.x=c.x:c.y>=a.y&&c.y<=a.y+a.height&&(g.y=c.y),c.xa.x+a.width&&(g.x=a.x+a.width),c.ya.y+a.height&&(g.y=a.y+a.height));return g},EllipsePerimeter:function(a,b,c,d){var e=a.x,f=a.y,g=a.width/2,k=a.height/2,l=e+g,m=f+k;b=c.x;c=c.y;var n=parseInt(b-l),p=parseInt(c-m);if(0==n&&0!=p)return new mxPoint(l, -m+k*p/Math.abs(p));if(0==n&&0==p)return new mxPoint(b,c);if(d){if(c>=f&&c<=f+a.height)return a=c-m,a=Math.sqrt(g*g*(1-a*a/(k*k)))||0,b<=e&&(a=-a),new mxPoint(l+a,c);if(b>=e&&b<=e+a.width)return a=b-l,a=Math.sqrt(k*k*(1-a*a/(g*g)))||0,c<=f&&(a=-a),new mxPoint(b,m+a)}e=p/n;m-=e*l;f=g*g*e*e+k*k;a=-2*l*f;k=Math.sqrt(a*a-4*f*(g*g*e*e*l*l+k*k*l*l-g*g*k*k));g=(-a+k)/(2*f);l=(-a-k)/(2*f);k=e*g+m;m=e*l+m;Math.sqrt(Math.pow(g-b,2)+Math.pow(k-c,2))c?new mxPoint(g,e):new mxPoint(g,e+a);if(k==c)return g>l?new mxPoint(b,k):new mxPoint(b+f,k);var m=g,n=k;d&&(l>=b&&l<=b+f?m=l:c>=e&&c<=e+a&&(n=c));return l-t&&rMath.PI-t)?c=d&&(e&&c.x>=n.x&&c.x<=q.x||!e&&c.y>=n.y&&c.y<=q.y)?e?new mxPoint(c.x,n.y):new mxPoint(n.x,c.y):b==mxConstants.DIRECTION_NORTH?new mxPoint(f+k/2+l*Math.tan(r)/2,g+l):b==mxConstants.DIRECTION_SOUTH?new mxPoint(f+k/2-l*Math.tan(r)/2,g):b==mxConstants.DIRECTION_WEST?new mxPoint(f+k,g+l/2+k*Math.tan(r)/2):new mxPoint(f,g+ -l/2-k*Math.tan(r)/2):(d&&(d=new mxPoint(a,m),c.y>=g&&c.y<=g+l?(d.x=e?a:b==mxConstants.DIRECTION_WEST?f+k:f,d.y=c.y):c.x>=f&&c.x<=f+k&&(d.x=c.x,d.y=e?b==mxConstants.DIRECTION_NORTH?g+l:g:m),a=d.x,m=d.y),c=e&&c.x<=f+k/2||!e&&c.y<=g+l/2?mxUtils.intersection(c.x,c.y,a,m,n.x,n.y,p.x,p.y):mxUtils.intersection(c.x,c.y,a,m,p.x,p.y,q.x,q.y));null==c&&(c=new mxPoint(a,m));return c},HexagonPerimeter:function(a,b,c,d){var e=a.x,f=a.y,g=a.width,k=a.height,l=a.getCenterX();a=a.getCenterY();var m=c.x,n=c.y,p=-Math.atan2(n- -a,m-l),q=Math.PI,r=Math.PI/2;new mxPoint(l,a);b=null!=b?mxUtils.getValue(b.style,mxConstants.STYLE_DIRECTION,mxConstants.DIRECTION_EAST):mxConstants.DIRECTION_EAST;var t=b==mxConstants.DIRECTION_NORTH||b==mxConstants.DIRECTION_SOUTH;b=new mxPoint;var u=new mxPoint;if(mf+k||m>e+g&&ne+g&&n>f+k)d=!1;if(d){if(t){if(m==l){if(n<=f)return new mxPoint(l,f);if(n>=f+k)return new mxPoint(l,f+k)}else if(me+g){if(n==f+k/4)return new mxPoint(e+g,f+k/4);if(n==f+3*k/4)return new mxPoint(e+g,f+3*k/4)}else if(m==e){if(na)return new mxPoint(e,f+3*k/4)}else if(m==e+g){if(na)return new mxPoint(e+g,f+3*k/4)}if(n==f)return new mxPoint(l,f);if(n==f+k)return new mxPoint(l,f+k);mf+k/4&&nf+3*k/4&&(b=new mxPoint(e-Math.floor(.5*g),f+Math.floor(.5*k)),u=new mxPoint(e+g,f+Math.floor(1.25*k))):m>l&&(n>f+k/4&&nf+3*k/4&&(b=new mxPoint(e+Math.floor(1.5*g),f+Math.floor(.5*k)),u=new mxPoint(e,f+Math.floor(1.25*k))))}else{if(n==a){if(m<=e)return new mxPoint(e,f+k/2);if(m>=e+g)return new mxPoint(e+g,f+k/2)}else if(n< -f){if(m==e+g/4)return new mxPoint(e+g/4,f);if(m==e+3*g/4)return new mxPoint(e+3*g/4,f)}else if(n>f+k){if(m==e+g/4)return new mxPoint(e+g/4,f+k);if(m==e+3*g/4)return new mxPoint(e+3*g/4,f+k)}else if(n==f){if(ml)return new mxPoint(e+3*g/4,f)}else if(n==f+k){if(ma)return new mxPoint(e+3*g/4,f+k)}if(m==e)return new mxPoint(e,a);if(m==e+g)return new mxPoint(e+g,a);ne+g/4&&me+3*g/4&&(b=new mxPoint(e+Math.floor(.5*g),f-Math.floor(.5*k)),u=new mxPoint(e+Math.floor(1.25*g),f+k)):n>a&&(m>e+g/4&&me+3*g/4&&(b=new mxPoint(e+Math.floor(.5*g),f+Math.floor(1.5*k)),u=new mxPoint(e+Math.floor(1.25*g),f)))}d=l;p=a;m>=e&&m<= -e+g?(d=m,p=n=f&&n<=f+k&&(p=n,d=m-m?(b=new mxPoint(e+g,f),u=new mxPoint(e+g,f+ -k)):p>m&&pr&&pq-m&&p<=q||p<-q+m&&p>=-q?(b=new mxPoint(e,f),u=new mxPoint(e,f+k)):p<-m&&p>-r?(b=new mxPoint(e+Math.floor(1.5*g),f+Math.floor(.5*k)),u=new mxPoint(e,f+Math.floor(1.25*k))):p<-r&&p>-q+m&&(b=new mxPoint(e-Math.floor(.5*g),f+Math.floor(.5*k)),u=new mxPoint(e+g,f+Math.floor(1.25*k)))}else{m= -Math.atan2(k/2,g/4);if(p==m)return new mxPoint(e+Math.floor(.75*g),f);if(p==q-m)return new mxPoint(e+Math.floor(.25*g),f);if(p==q||p==-q)return new mxPoint(e,f+Math.floor(.5*k));if(0==p)return new mxPoint(e+g,f+Math.floor(.5*k));if(p==-m)return new mxPoint(e+Math.floor(.75*g),f+k);if(p==-q+m)return new mxPoint(e+Math.floor(.25*g),f+k);0m&&pq-m&& -pp&&p>-m?(b=new mxPoint(e+Math.floor(.5*g),f+Math.floor(1.5*k)),u=new mxPoint(e+Math.floor(1.25*g),f)):p<-m&&p>-q+m?(b=new mxPoint(e,f+k),u=new mxPoint(e+g,f+k)):p<-q+m&&p>-q&&(b=new mxPoint(e-Math.floor(.25*g),f),u=new mxPoint(e+Math.floor(.5*g),f+Math.floor(1.5*k)))}c=mxUtils.intersection(l,a,c.x,c.y,b.x,b.y,u.x,u.y)}return null==c?new mxPoint(l,a):c}}; -function mxPrintPreview(a,b,c,d,e,f,g,k,l){this.graph=a;this.scale=null!=b?b:1/a.pageScale;this.border=null!=d?d:0;this.pageFormat=mxRectangle.fromRectangle(null!=c?c:a.pageFormat);this.title=null!=k?k:"Printer-friendly version";this.x0=null!=e?e:0;this.y0=null!=f?f:0;this.borderColor=g;this.pageSelector=null!=l?l:!0}mxPrintPreview.prototype.graph=null;mxPrintPreview.prototype.pageFormat=null;mxPrintPreview.prototype.scale=null;mxPrintPreview.prototype.border=0; -mxPrintPreview.prototype.marginTop=0;mxPrintPreview.prototype.marginBottom=0;mxPrintPreview.prototype.x0=0;mxPrintPreview.prototype.y0=0;mxPrintPreview.prototype.autoOrigin=!0;mxPrintPreview.prototype.printOverlays=!1;mxPrintPreview.prototype.printControls=!1;mxPrintPreview.prototype.printBackgroundImage=!1;mxPrintPreview.prototype.backgroundColor="#ffffff";mxPrintPreview.prototype.borderColor=null;mxPrintPreview.prototype.title=null;mxPrintPreview.prototype.pageSelector=null; -mxPrintPreview.prototype.wnd=null;mxPrintPreview.prototype.targetWindow=null;mxPrintPreview.prototype.pageCount=0;mxPrintPreview.prototype.clipping=!0;mxPrintPreview.prototype.getWindow=function(){return this.wnd}; -mxPrintPreview.prototype.getDoctype=function(){var a="";5==document.documentMode?a='':8==document.documentMode?a='':8'):("CSS1Compat"===document.compatMode&&k.writeln(""),k.writeln(""));k.writeln("");this.writeHead(k,a);k.writeln("");k.writeln('')}var m=this.graph.getGraphBounds().clone(),n=this.graph.getView().getScale(),p=n/this.scale,q=this.graph.getView().getTranslate();this.autoOrigin||(this.x0-=q.x*this.scale,this.y0-= -q.y*this.scale,m.width+=m.x,m.height+=m.y,m.x=0,this.border=m.y=0);var r=this.pageFormat.width-2*this.border,t=this.pageFormat.height-2*this.border;this.pageFormat.height+=this.marginTop+this.marginBottom;m.width/=p;m.height/=p;var u=Math.max(1,Math.ceil((m.width+this.x0)/r)),x=Math.max(1,Math.ceil((m.height+this.y0)/t));this.pageCount=u*x;var y=mxUtils.bind(this,function(){if(this.pageSelector&&(1");a.writeln("");a.close();mxEvent.release(a.body)}}catch(b){}}; -mxPrintPreview.prototype.writeHead=function(a,b){null!=this.title&&a.writeln(""+this.title+"");mxClient.IS_VML&&a.writeln('');mxClient.link("stylesheet",mxClient.basePath+"/css/common.css",a);a.writeln('")};mxPrintPreview.prototype.writePostfix=function(a){}; -mxPrintPreview.prototype.createPageSelector=function(a,b){var c=this.wnd.document,d=c.createElement("table");d.className="mxPageSelector";d.setAttribute("border","0");for(var e=c.createElement("tbody"),f=0;f":"";mxCellEditor.prototype.escapeCancelsEditing=!0;mxCellEditor.prototype.textNode="";mxCellEditor.prototype.zIndex=5;mxCellEditor.prototype.minResize=new mxRectangle(0,20); -mxCellEditor.prototype.wordWrapPadding=mxClient.IS_QUIRKS?2:mxClient.IS_IE11?0:1;mxCellEditor.prototype.blurEnabled=!1;mxCellEditor.prototype.initialValue=null;mxCellEditor.prototype.align=null;mxCellEditor.prototype.init=function(){this.textarea=document.createElement("div");this.textarea.className="mxCellEditor mxPlainTextEditor";this.textarea.contentEditable=!0;mxClient.IS_GC&&(this.textarea.style.minHeight="1em");this.textarea.style.position=this.isLegacyEditor()?"absolute":"relative";this.installListeners(this.textarea)}; -mxCellEditor.prototype.applyValue=function(a,b){this.graph.labelChanged(a.cell,b,this.trigger)};mxCellEditor.prototype.setAlign=function(a){null!=this.textarea&&(this.textarea.style.textAlign=a);this.align=a;this.resize()}; -mxCellEditor.prototype.getInitialValue=function(a,b){var c=mxUtils.htmlEntities(this.graph.getEditingValue(a.cell,b),!1);mxClient.IS_QUIRKS||8==document.documentMode||9==document.documentMode||10==document.documentMode||(c=mxUtils.replaceTrailingNewlines(c,"

"));return c.replace(/\n/g,"
")};mxCellEditor.prototype.getCurrentValue=function(a){return mxUtils.extractTextWithWhitespace(this.textarea.childNodes)}; -mxCellEditor.prototype.isCancelEditingKeyEvent=function(a){return this.escapeCancelsEditing||mxEvent.isShiftDown(a)||mxEvent.isControlDown(a)||mxEvent.isMetaDown(a)}; -mxCellEditor.prototype.installListeners=function(a){mxEvent.addListener(a,"dragstart",mxUtils.bind(this,function(a){this.graph.stopEditing(!1);mxEvent.consume(a)}));mxEvent.addListener(a,"blur",mxUtils.bind(this,function(a){this.blurEnabled&&this.focusLost(a)}));mxEvent.addListener(a,"keydown",mxUtils.bind(this,function(a){mxEvent.isConsumed(a)||(this.isStopEditingEvent(a)?(this.graph.stopEditing(!1),mxEvent.consume(a)):27==a.keyCode&&(this.graph.stopEditing(this.isCancelEditingKeyEvent(a)),mxEvent.consume(a)))})); -var b=mxUtils.bind(this,function(b){null!=this.editingCell&&this.clearOnChange&&a.innerHTML==this.getEmptyLabelText()&&(!mxClient.IS_FF||8!=b.keyCode&&46!=b.keyCode)&&(this.clearOnChange=!1,a.innerHTML="")});mxEvent.addListener(a,"keypress",b);mxEvent.addListener(a,"paste",b);b=mxUtils.bind(this,function(a){null!=this.editingCell&&(0==this.textarea.innerHTML.length||"
"==this.textarea.innerHTML?(this.textarea.innerHTML=this.getEmptyLabelText(),this.clearOnChange=0e&&(this.textarea.style.width=this.textarea.scrollWidth+"px");else if("block"==a.style[mxConstants.STYLE_OVERFLOW]|| -"width"==a.style[mxConstants.STYLE_OVERFLOW]){if(-.5==d.y||"width"==a.style[mxConstants.STYLE_OVERFLOW])this.textarea.style.maxHeight=this.bounds.height+"px";this.textarea.style.width=e+"px"}else this.textarea.style.maxWidth=e+"px";else this.textarea.style.whiteSpace="nowrap",this.textarea.style.width="";8==document.documentMode&&(this.textarea.style.zoom="1",this.textarea.style.height="auto");8==document.documentMode?(a=this.textarea.scrollWidth,e=this.textarea.scrollHeight,this.textarea.style.left= -Math.max(0,Math.ceil((this.bounds.x-d.x*(this.bounds.width-(a+1)*c)+a*(c-1)*0+2*(d.x+.5))/c))+"px",this.textarea.style.top=Math.max(0,Math.ceil((this.bounds.y-d.y*(this.bounds.height-(e+.5)*c)+e*(c-1)*0+1*Math.abs(d.y+.5))/c))+"px",this.textarea.style.width=Math.round(a*c)+"px",this.textarea.style.height=Math.round(e*c)+"px"):mxClient.IS_QUIRKS?(a=this.textarea.scrollWidth,e=this.textarea.scrollHeight,this.textarea.style.left=Math.max(0,Math.ceil(this.bounds.x-d.x*(this.bounds.width-(a+1)*c)+a*(c- -1)*0+2*(d.x+.5)))+"px",this.textarea.style.top=Math.max(0,Math.ceil(this.bounds.y-d.y*(this.bounds.height-(e+.5)*c)+e*(c-1)*0+1*Math.abs(d.y+.5)))+"px"):(this.textarea.style.left=Math.max(0,Math.round(this.bounds.x-d.x*(this.bounds.width-2))+1)+"px",this.textarea.style.top=Math.max(0,Math.round(this.bounds.y-d.y*(this.bounds.height-4)+(-1==d.y?3:0))+1)+"px")}else this.bounds=this.getEditorBounds(a),this.textarea.style.width=Math.round(this.bounds.width/c)+"px",this.textarea.style.height=Math.round(this.bounds.height/ -c)+"px",8==document.documentMode||mxClient.IS_QUIRKS?(this.textarea.style.left=Math.round(this.bounds.x)+"px",this.textarea.style.top=Math.round(this.bounds.y)+"px"):(this.textarea.style.left=Math.max(0,Math.round(this.bounds.x+1))+"px",this.textarea.style.top=Math.max(0,Math.round(this.bounds.y+1))+"px"),this.graph.isWrapping(a.cell)&&(2<=this.bounds.width||2<=this.bounds.height)&&this.textarea.innerHTML!=this.getEmptyLabelText()?(this.textarea.style.wordWrap=mxConstants.WORD_WRAP,this.textarea.style.whiteSpace= -"normal","fill"!=a.style[mxConstants.STYLE_OVERFLOW]&&(this.textarea.style.width=Math.round(this.bounds.width/c)+this.wordWrapPadding+"px")):(this.textarea.style.whiteSpace="nowrap","fill"!=a.style[mxConstants.STYLE_OVERFLOW]&&(this.textarea.style.width=""));mxClient.IS_VML?this.textarea.style.zoom=c:(mxUtils.setPrefixedStyle(this.textarea.style,"transformOrigin","0px 0px"),mxUtils.setPrefixedStyle(this.textarea.style,"transform","scale("+c+","+c+")"+(null==d?"":" translate("+100*d.x+"%,"+100*d.y+ -"%)")))}};mxCellEditor.prototype.focusLost=function(){this.stopEditing(!this.graph.isInvokesStopCellEditing())};mxCellEditor.prototype.getBackgroundColor=function(a){return null};mxCellEditor.prototype.isLegacyEditor=function(){if(mxClient.IS_VML)return!0;var a=!1;if(mxClient.IS_SVG){var b=this.graph.view.getDrawPane().ownerSVGElement;null!=b&&(b=mxUtils.getCurrentStyle(b),null!=b&&(a="absolute"==b.position))}return!a}; -mxCellEditor.prototype.startEditing=function(a,b){this.stopEditing(!0);this.align=null;null==this.textarea&&this.init();null!=this.graph.tooltipHandler&&this.graph.tooltipHandler.hideTooltip();var c=this.graph.getView().getState(a);if(null!=c){this.graph.getView();var d=mxUtils.getValue(c.style,mxConstants.STYLE_FONTSIZE,mxConstants.DEFAULT_FONTSIZE),e=mxUtils.getValue(c.style,mxConstants.STYLE_FONTFAMILY,mxConstants.DEFAULT_FONTFAMILY),f=mxUtils.getValue(c.style,mxConstants.STYLE_FONTCOLOR,"black"), -g=mxUtils.getValue(c.style,mxConstants.STYLE_ALIGN,mxConstants.ALIGN_LEFT),k=(mxUtils.getValue(c.style,mxConstants.STYLE_FONTSTYLE,0)&mxConstants.FONT_BOLD)==mxConstants.FONT_BOLD,l=(mxUtils.getValue(c.style,mxConstants.STYLE_FONTSTYLE,0)&mxConstants.FONT_ITALIC)==mxConstants.FONT_ITALIC,m=[];(mxUtils.getValue(c.style,mxConstants.STYLE_FONTSTYLE,0)&mxConstants.FONT_UNDERLINE)==mxConstants.FONT_UNDERLINE&&m.push("underline");(mxUtils.getValue(c.style,mxConstants.STYLE_FONTSTYLE,0)&mxConstants.FONT_STRIKETHROUGH)== -mxConstants.FONT_STRIKETHROUGH&&m.push("line-through");this.textarea.style.lineHeight=mxConstants.ABSOLUTE_LINE_HEIGHT?Math.round(d*mxConstants.LINE_HEIGHT)+"px":mxConstants.LINE_HEIGHT;this.textarea.style.backgroundColor=this.getBackgroundColor(c);this.textarea.style.textDecoration=m.join(" ");this.textarea.style.fontWeight=k?"bold":"normal";this.textarea.style.fontStyle=l?"italic":"";this.textarea.style.fontSize=Math.round(d)+"px";this.textarea.style.zIndex=this.zIndex;this.textarea.style.fontFamily= -e;this.textarea.style.textAlign=g;this.textarea.style.outline="none";this.textarea.style.color=f;d=this.textDirection=mxUtils.getValue(c.style,mxConstants.STYLE_TEXT_DIRECTION,mxConstants.DEFAULT_TEXT_DIRECTION);d==mxConstants.TEXT_DIRECTION_AUTO&&(null==c||null==c.text||c.text.dialect==mxConstants.DIALECT_STRICTHTML||mxUtils.isNode(c.text.value)||(d=c.text.getAutoDirection()));d==mxConstants.TEXT_DIRECTION_LTR||d==mxConstants.TEXT_DIRECTION_RTL?this.textarea.setAttribute("dir",d):this.textarea.removeAttribute("dir"); -this.textarea.innerHTML=this.getInitialValue(c,b)||"";this.initialValue=this.textarea.innerHTML;0==this.textarea.innerHTML.length||"
"==this.textarea.innerHTML?(this.textarea.innerHTML=this.getEmptyLabelText(),this.clearOnChange=!0):this.clearOnChange=this.textarea.innerHTML==this.getEmptyLabelText();this.graph.container.appendChild(this.textarea);this.editingCell=a;this.trigger=b;this.textNode=null;null!=c.text&&this.isHideLabel(c)&&(this.textNode=c.text.node,this.textNode.style.visibility="hidden"); -this.autoSize&&(this.graph.model.isEdge(c.cell)||"fill"!=c.style[mxConstants.STYLE_OVERFLOW])&&window.setTimeout(mxUtils.bind(this,function(){this.resize()}),0);this.resize();try{this.textarea.focus(),this.isSelectText()&&0=n.x:null!=c&&(k=(null!=m?m.x:c.x+c.width)<(null!=l?l.x:b.x))}if(null!=l)b=new mxCellState,b.x=l.x,b.y=l.y;else if(null!=b){var p=mxUtils.getPortConstraints(b,a,!0,mxConstants.DIRECTION_MASK_NONE);p!=mxConstants.DIRECTION_MASK_NONE&& -p!=mxConstants.DIRECTION_MASK_WEST+mxConstants.DIRECTION_MASK_EAST&&(k=p==mxConstants.DIRECTION_MASK_WEST)}else return;n=!0;null!=c&&(g=g.getCellGeometry(c.cell),g.relative?n=.5>=g.x:null!=b&&(n=(null!=l?l.x:b.x+b.width)<(null!=m?m.x:c.x)));null!=m?(c=new mxCellState,c.x=m.x,c.y=m.y):null!=c&&(p=mxUtils.getPortConstraints(c,a,!1,mxConstants.DIRECTION_MASK_NONE),p!=mxConstants.DIRECTION_MASK_NONE&&p!=mxConstants.DIRECTION_MASK_WEST+mxConstants.DIRECTION_MASK_EAST&&(n=p==mxConstants.DIRECTION_MASK_WEST)); -null!=b&&null!=c&&(a=k?b.x:b.x+b.width,b=f.getRoutingCenterY(b),l=n?c.x:c.x+c.width,c=f.getRoutingCenterY(c),f=new mxPoint(a+(k?-d:d),b),g=new mxPoint(l+(n?-d:d),c),k==n?(d=k?Math.min(a,l)-d:Math.max(a,l)+d,e.push(new mxPoint(d,b)),e.push(new mxPoint(d,c))):(f.xb.x+b.width?null!=c?(d=c.x,m=Math.max(Math.abs(l-c.y),m)):a==mxConstants.DIRECTION_NORTH?l=b.y-2*k:a==mxConstants.DIRECTION_SOUTH?l=b.y+b.height+2*k:d=a==mxConstants.DIRECTION_EAST?b.x-2*m:b.x+b.width+2*m:null!=c&&(d=f.getRoutingCenterX(b),k=Math.max(Math.abs(d-c.x),m),l=c.y,m=0);e.push(new mxPoint(d-k,l-m));e.push(new mxPoint(d+k,l+m))}},ElbowConnector:function(a,b,c,d,e){var f=null!=d&&0n,k=f.xm;else l=Math.max(b.x,c.x),m=Math.min(b.x+b.width,c.x+c.width),g=l==m,g||(k=Math.max(b.y,c.y),n=Math.min(b.y+b.height,c.y+c.height),k=k==n);k||!g&&a.style[mxConstants.STYLE_ELBOW]!=mxConstants.ELBOW_VERTICAL?mxEdgeStyle.SideToSide(a,b,c,d,e):mxEdgeStyle.TopToBottom(a,b,c,d,e)},SideToSide:function(a,b,c,d,e){var f=a.view;d=null!=d&&0=b.y&&d.y<=b.y+b.height&&(k=d.y),d.y>=c.y&&d.y<=c.y+c.height&&(f=d.y)),mxUtils.contains(c,a,k)||mxUtils.contains(b,a,k)||e.push(new mxPoint(a, -k)),mxUtils.contains(c,a,f)||mxUtils.contains(b,a,f)||e.push(new mxPoint(a,f)),1==e.length&&(null!=d?mxUtils.contains(c,a,d.y)||mxUtils.contains(b,a,d.y)||e.push(new mxPoint(a,d.y)):(f=Math.max(b.y,c.y),e.push(new mxPoint(a,f+(Math.min(b.y+b.height,c.y+c.height)-f)/2)))))},TopToBottom:function(a,b,c,d,e){var f=a.view;d=null!=d&&0=b.x&&d.x<=b.x+b.width&&(a=d.x),k=null!=d?d.y:Math.round(g+(k-g)/2),mxUtils.contains(c,a,k)||mxUtils.contains(b,a,k)||e.push(new mxPoint(a,k)),a=null!=d&&d.x>=c.x&&d.x<=c.x+c.width?d.x:f.getRoutingCenterX(c),mxUtils.contains(c,a,k)||mxUtils.contains(b,a,k)||e.push(new mxPoint(a,k)),1==e.length&&(null!=d&&1==e.length?mxUtils.contains(c,d.x,k)||mxUtils.contains(b,d.x,k)|| -e.push(new mxPoint(d.x,k)):(f=Math.max(b.x,c.x),e.push(new mxPoint(f+(Math.min(b.x+b.width,c.x+c.width)-f)/2,k)))))},SegmentConnector:function(a,b,c,d,e){function f(b){b.x=Math.round(b.x*a.view.scale*10)/10;b.y=Math.round(b.y*a.view.scale*10)/10;if(null==k||1<=Math.abs(k.x-b.x)||Math.abs(k.y-b.y)>=Math.max(1,a.view.scale))e.push(b),k=b;return k}var g=mxEdgeStyle.scalePointArray(a.absolutePoints,a.view.scale);b=mxEdgeStyle.scaleCellState(b,a.view.scale);c=mxEdgeStyle.scaleCellState(c,a.view.scale); -var k=0Math.abs(q[0].x-n.x)&&(q[0].x=n.x),1>Math.abs(q[0].y-n.y)&&(q[0].y=n.y));t=g[p];null!=t&&null!=q[q.length-1]&&(1>Math.abs(q[q.length-1].x-t.x)&&(q[q.length-1].x= -t.x),1>Math.abs(q[q.length-1].y-t.y)&&(q[q.length-1].y=t.y));var m=q[0],u=b;d=g[0];var x=!1,y=!1,x=m;null!=d&&(u=null);for(r=0;2>r;r++){var B=null!=d&&d.x==x.x,A=null!=d&&d.y==x.y,z=null!=u&&x.y>=u.y&&x.y<=u.y+u.height,u=null!=u&&x.x>=u.x&&x.x<=u.x+u.width,x=A||null==d&&z,y=B||null==d&&u;if(0!=r||!(x&&y||B&&A)){if(null!=d&&!A&&!B&&(z||u)){l=z?!1:!0;break}if(y||x){l=x;1==r&&(l=0==q.length%2?x:y);break}}u=c;d=g[p];null!=d&&(u=null);x=q[q.length-1];B&&A&&(q=q.slice(1))}l&&(null!=g[0]&&g[0].y!=m.y||null== -g[0]&&null!=b&&(m.yb.y+b.height))?f(new mxPoint(n.x,m.y)):!l&&(null!=g[0]&&g[0].x!=m.x||null==g[0]&&null!=b&&(m.xb.x+b.width))&&f(new mxPoint(m.x,n.y));l?n.y=m.y:n.x=m.x;for(r=0;rc.y+c.height))?f(new mxPoint(n.x,m.y)):!l&&(null!= -g[p]&&g[p].x!=m.x||null==g[p]&&null!=c&&(m.xc.x+c.width))&&f(new mxPoint(m.x,n.y)));if(null==g[0]&&null!=b)for(;1=Math.abs(t.x-e[e.length-1].x)&&1>=Math.abs(t.y-e[e.length-1].y)&&(e.splice(e.length-1,1),null!=e[e.length-1]&&(1>Math.abs(e[e.length-1].x- -t.x)&&(e[e.length-1].x=t.x),1>Math.abs(e[e.length-1].y-t.y)&&(e[e.length-1].y=t.y)))},orthBuffer:10,orthPointsFallback:!0,dirVectors:[[-1,0],[0,-1],[1,0],[0,1],[-1,0],[0,-1],[1,0]],wayPoints1:[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],routePatterns:[[[513,2308,2081,2562],[513,1090,514,2184,2114,2561],[513,1090,514,2564,2184,2562],[513,2308,2561,1090,514,2568,2308]],[[514,1057,513,2308,2081,2562],[514,2184,2114,2561],[514,2184,2562,1057,513,2564,2184],[514,1057,513,2568, -2308,2561]],[[1090,514,1057,513,2308,2081,2562],[2114,2561],[1090,2562,1057,513,2564,2184],[1090,514,1057,513,2308,2561,2568]],[[2081,2562],[1057,513,1090,514,2184,2114,2561],[1057,513,1090,514,2184,2562,2564],[1057,2561,1090,514,2568,2308]]],inlineRoutePatterns:[[null,[2114,2568],null,null],[null,[514,2081,2114,2568],null,null],[null,[2114,2561],null,null],[[2081,2562],[1057,2114,2568],[2184,2562],null]],vertexSeperations:[],limits:[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]],LEFT_MASK:32,TOP_MASK:64, -RIGHT_MASK:128,BOTTOM_MASK:256,LEFT:1,TOP:2,RIGHT:4,BOTTOM:8,SIDE_MASK:480,CENTER_MASK:512,SOURCE_MASK:1024,TARGET_MASK:2048,VERTEX_MASK:3072,getJettySize:function(a,b){var c=mxUtils.getValue(a.style,b?mxConstants.STYLE_SOURCE_JETTY_SIZE:mxConstants.STYLE_TARGET_JETTY_SIZE,mxUtils.getValue(a.style,mxConstants.STYLE_JETTY_SIZE,mxEdgeStyle.orthBuffer));"auto"==c&&(mxUtils.getValue(a.style,b?mxConstants.STYLE_STARTARROW:mxConstants.STYLE_ENDARROW,mxConstants.NONE)!=mxConstants.NONE?(c=mxUtils.getNumber(a.style, -b?mxConstants.STYLE_STARTSIZE:mxConstants.STYLE_ENDSIZE,mxConstants.DEFAULT_MARKERSIZE),c=Math.max(2,Math.ceil((c+mxEdgeStyle.orthBuffer)/mxEdgeStyle.orthBuffer))*mxEdgeStyle.orthBuffer):c=2*mxEdgeStyle.orthBuffer);return c},scalePointArray:function(a,b){var c=[];if(null!=a)for(var d=0;dv;v++)mxEdgeStyle.limits[v][1]=q[v][0]-z[v],mxEdgeStyle.limits[v][2]= -q[v][1]-z[v],mxEdgeStyle.limits[v][4]=q[v][0]+q[v][2]+z[v],mxEdgeStyle.limits[v][8]=q[v][1]+q[v][3]+z[v];z=q[0][1]+q[0][3]/2;r=q[1][1]+q[1][3]/2;v=q[0][0]+q[0][2]/2-(q[1][0]+q[1][2]/2);D=z-r;z=0;0>v?z=0>D?2:1:0>=D&&(z=3,0==v&&(z=2));r=null;null!=l&&(r=n);l=[[.5,.5],[.5,.5]];for(v=0;2>v;v++)null!=r&&(l[v][0]=(r.x-q[v][0])/q[v][2],1>=Math.abs(r.x-q[v][0])?b[v]=mxConstants.DIRECTION_MASK_WEST:1>=Math.abs(r.x-q[v][0]-q[v][2])&&(b[v]=mxConstants.DIRECTION_MASK_EAST),l[v][1]=(r.y-q[v][1])/q[v][3],1>=Math.abs(r.y- -q[v][1])?b[v]=mxConstants.DIRECTION_MASK_NORTH:1>=Math.abs(r.y-q[v][1]-q[v][3])&&(b[v]=mxConstants.DIRECTION_MASK_SOUTH)),r=null,null!=m&&(r=p);v=q[0][1]-(q[1][1]+q[1][3]);p=q[0][0]-(q[1][0]+q[1][2]);r=q[1][1]-(q[0][1]+q[0][3]);t=q[1][0]-(q[0][0]+q[0][2]);mxEdgeStyle.vertexSeperations[1]=Math.max(p-C,0);mxEdgeStyle.vertexSeperations[2]=Math.max(v-C,0);mxEdgeStyle.vertexSeperations[4]=Math.max(r-C,0);mxEdgeStyle.vertexSeperations[3]=Math.max(t-C,0);C=[];m=[];n=[];m[0]=p>=t?mxConstants.DIRECTION_MASK_WEST: -mxConstants.DIRECTION_MASK_EAST;n[0]=v>=r?mxConstants.DIRECTION_MASK_NORTH:mxConstants.DIRECTION_MASK_SOUTH;m[1]=mxUtils.reversePortConstraints(m[0]);n[1]=mxUtils.reversePortConstraints(n[0]);p=p>=t?p:t;r=v>=r?v:r;t=[[0,0],[0,0]];u=!1;for(v=0;2>v;v++)0==b[v]&&(0==(m[v]&c[v])&&(m[v]=mxUtils.reversePortConstraints(m[v])),0==(n[v]&c[v])&&(n[v]=mxUtils.reversePortConstraints(n[v])),t[v][0]=n[v],t[v][1]=m[v]);0v;v++)0==b[v]&&(0==(t[v][0]&c[v])&&(t[v][0]=t[v][1]),C[v]=t[v][0]&c[v],C[v]|=(t[v][1]&c[v])<<8,C[v]|=(t[1-v][v]&c[v])<<16,C[v]|=(t[1-v][1-v]&c[v])<<24,0==(C[v]&15)&&(C[v]<<=8),0==(C[v]&3840)&&(C[v]=C[v]&15|C[v]>>8),0==(C[v]&983040)&&(C[v]=C[v]&65535|(C[v]&251658240)>> -8),b[v]=C[v]&15,c[v]==mxConstants.DIRECTION_MASK_WEST||c[v]==mxConstants.DIRECTION_MASK_NORTH||c[v]==mxConstants.DIRECTION_MASK_EAST||c[v]==mxConstants.DIRECTION_MASK_SOUTH)&&(b[v]=c[v]);c=b[0]==mxConstants.DIRECTION_MASK_EAST?3:b[0];C=b[1]==mxConstants.DIRECTION_MASK_EAST?3:b[1];c-=z;C-=z;1>c&&(c+=4);1>C&&(C+=4);c=mxEdgeStyle.routePatterns[c-1][C-1];mxEdgeStyle.wayPoints1[0][0]=q[0][0];mxEdgeStyle.wayPoints1[0][1]=q[0][1];switch(b[0]){case mxConstants.DIRECTION_MASK_WEST:mxEdgeStyle.wayPoints1[0][0]-= -f;mxEdgeStyle.wayPoints1[0][1]+=l[0][1]*q[0][3];break;case mxConstants.DIRECTION_MASK_SOUTH:mxEdgeStyle.wayPoints1[0][0]+=l[0][0]*q[0][2];mxEdgeStyle.wayPoints1[0][1]+=q[0][3]+f;break;case mxConstants.DIRECTION_MASK_EAST:mxEdgeStyle.wayPoints1[0][0]+=q[0][2]+f;mxEdgeStyle.wayPoints1[0][1]+=l[0][1]*q[0][3];break;case mxConstants.DIRECTION_MASK_NORTH:mxEdgeStyle.wayPoints1[0][0]+=l[0][0]*q[0][2],mxEdgeStyle.wayPoints1[0][1]-=f}f=0;m=C=0<(b[0]&(mxConstants.DIRECTION_MASK_EAST|mxConstants.DIRECTION_MASK_WEST))? -0:1;for(v=0;v>5,r<<=z,15>=4),t=0<(c[v]&mxEdgeStyle.CENTER_MASK),(y||x)&&9>r?(u=y?0:1,r=t&&0==n?q[u][0]+l[u][0]*q[u][2]:t?q[u][1]+l[u][1]* -q[u][3]:mxEdgeStyle.limits[u][r],0==n?(r=(r-mxEdgeStyle.wayPoints1[f][0])*p[0],0e&&(e+=4);1>a&&(a+=4);b=routePatterns[e-1][a-1];0!=c&& -0!=d||null==inlineRoutePatterns[e-1][a-1]||(b=inlineRoutePatterns[e-1][a-1]);return b}},mxStyleRegistry={values:[],putValue:function(a,b){mxStyleRegistry.values[a]=b},getValue:function(a){return mxStyleRegistry.values[a]},getName:function(a){for(var b in mxStyleRegistry.values)if(mxStyleRegistry.values[b]==a)return b;return null}};mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ELBOW,mxEdgeStyle.ElbowConnector);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ENTITY_RELATION,mxEdgeStyle.EntityRelation); -mxStyleRegistry.putValue(mxConstants.EDGESTYLE_LOOP,mxEdgeStyle.Loop);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SIDETOSIDE,mxEdgeStyle.SideToSide);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_TOPTOBOTTOM,mxEdgeStyle.TopToBottom);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ORTHOGONAL,mxEdgeStyle.OrthConnector);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SEGMENT,mxEdgeStyle.SegmentConnector);mxStyleRegistry.putValue(mxConstants.PERIMETER_ELLIPSE,mxPerimeter.EllipsePerimeter); -mxStyleRegistry.putValue(mxConstants.PERIMETER_RECTANGLE,mxPerimeter.RectanglePerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_RHOMBUS,mxPerimeter.RhombusPerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_TRIANGLE,mxPerimeter.TrianglePerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_HEXAGON,mxPerimeter.HexagonPerimeter);function mxGraphView(a){this.graph=a;this.translate=new mxPoint;this.graphBounds=new mxRectangle;this.states=new mxDictionary}mxGraphView.prototype=new mxEventSource; -mxGraphView.prototype.constructor=mxGraphView;mxGraphView.prototype.EMPTY_POINT=new mxPoint;mxGraphView.prototype.doneResource="none"!=mxClient.language?"done":"";mxGraphView.prototype.updatingDocumentResource="none"!=mxClient.language?"updatingDocument":"";mxGraphView.prototype.allowEval=!1;mxGraphView.prototype.captureDocumentGesture=!0;mxGraphView.prototype.optimizeVmlReflows=!0;mxGraphView.prototype.rendering=!0;mxGraphView.prototype.graph=null;mxGraphView.prototype.currentRoot=null; -mxGraphView.prototype.graphBounds=null;mxGraphView.prototype.scale=1;mxGraphView.prototype.translate=null;mxGraphView.prototype.states=null;mxGraphView.prototype.updateStyle=!1;mxGraphView.prototype.lastNode=null;mxGraphView.prototype.lastHtmlNode=null;mxGraphView.prototype.lastForegroundNode=null;mxGraphView.prototype.lastForegroundHtmlNode=null;mxGraphView.prototype.getGraphBounds=function(){return this.graphBounds};mxGraphView.prototype.setGraphBounds=function(a){this.graphBounds=a}; -mxGraphView.prototype.getBounds=function(a){var b=null;if(null!=a&&0 -c.length||null==c[0]||null==c[c.length-1])?this.clear(a.cell,!0):(this.updateEdgeBounds(a),this.updateEdgeLabelOffset(a)))}; -mxGraphView.prototype.updateVertexLabelOffset=function(a){var b=mxUtils.getValue(a.style,mxConstants.STYLE_LABEL_POSITION,mxConstants.ALIGN_CENTER);if(b==mxConstants.ALIGN_LEFT)b=mxUtils.getValue(a.style,mxConstants.STYLE_LABEL_WIDTH,null),b=null!=b?b*this.scale:a.width,a.absoluteOffset.x-=b;else if(b==mxConstants.ALIGN_RIGHT)a.absoluteOffset.x+=a.width;else if(b==mxConstants.ALIGN_CENTER&&(b=mxUtils.getValue(a.style,mxConstants.STYLE_LABEL_WIDTH,null),null!=b)){var c=mxUtils.getValue(a.style,mxConstants.STYLE_ALIGN, -mxConstants.ALIGN_CENTER),d=0;c==mxConstants.ALIGN_CENTER?d=.5:c==mxConstants.ALIGN_RIGHT&&(d=1);0!=d&&(a.absoluteOffset.x-=(b*this.scale-a.width)*d)}b=mxUtils.getValue(a.style,mxConstants.STYLE_VERTICAL_LABEL_POSITION,mxConstants.ALIGN_MIDDLE);b==mxConstants.ALIGN_TOP?a.absoluteOffset.y-=a.height:b==mxConstants.ALIGN_BOTTOM&&(a.absoluteOffset.y+=a.height)};mxGraphView.prototype.resetValidationState=function(){this.lastForegroundHtmlNode=this.lastForegroundNode=this.lastHtmlNode=this.lastNode=null}; -mxGraphView.prototype.stateValidated=function(a){var b=this.graph.getModel().isEdge(a.cell)&&this.graph.keepEdgesInForeground||this.graph.getModel().isVertex(a.cell)&&this.graph.keepEdgesInBackground;a=this.graph.cellRenderer.insertStateAfter(a,b?this.lastForegroundNode||this.lastNode:this.lastNode,b?this.lastForegroundHtmlNode||this.lastHtmlNode:this.lastHtmlNode);b?(this.lastForegroundHtmlNode=a[1],this.lastForegroundNode=a[0]):(this.lastHtmlNode=a[1],this.lastNode=a[0])}; -mxGraphView.prototype.updateFixedTerminalPoints=function(a,b,c){this.updateFixedTerminalPoint(a,b,!0,this.graph.getConnectionConstraint(a,b,!0));this.updateFixedTerminalPoint(a,c,!1,this.graph.getConnectionConstraint(a,c,!1))};mxGraphView.prototype.updateFixedTerminalPoint=function(a,b,c,d){a.setAbsoluteTerminalPoint(this.getFixedTerminalPoint(a,b,c,d),c)}; -mxGraphView.prototype.getFixedTerminalPoint=function(a,b,c,d){var e=null;null!=d&&(e=this.graph.getConnectionPoint(b,d,!1));if(null==e&&null==b){b=this.scale;d=this.translate;var f=a.origin,e=this.graph.getCellGeometry(a.cell).getTerminalPoint(c);null!=e&&(e=new mxPoint(b*(d.x+e.x+f.x),b*(d.y+e.y+f.y)))}return e}; -mxGraphView.prototype.updateBoundsFromStencil=function(a){var b=null;if(null!=a&&null!=a.shape&&null!=a.shape.stencil&&"fixed"==a.shape.stencil.aspect){var b=mxRectangle.fromRectangle(a),c=a.shape.stencil.computeAspect(a.style,a.x,a.y,a.width,a.height);a.setRect(c.x,c.y,a.shape.stencil.w0*c.width,a.shape.stencil.h0*c.height)}return b}; -mxGraphView.prototype.updatePoints=function(a,b,c,d){if(null!=a){var e=[];e.push(a.absolutePoints[0]);var f=this.getEdgeStyle(a,b,c,d);if(null!=f){c=this.getTerminalPort(a,c,!0);d=this.getTerminalPort(a,d,!1);var g=this.updateBoundsFromStencil(c),k=this.updateBoundsFromStencil(d);f(a,c,d,b,e);null!=g&&c.setRect(g.x,g.y,g.width,g.height);null!=k&&d.setRect(k.x,k.y,k.width,k.height)}else if(null!=b)for(f=0;fb.length)||mxUtils.getValue(a.style,mxConstants.STYLE_ORTHOGONAL_LOOP,!1)&&(null!=e&&null!=e.point||null!=f&&null!=f.point)?!1:null!=c&&c==d}; -mxGraphView.prototype.getEdgeStyle=function(a,b,c,d){a=this.isLoopStyleEnabled(a,b,c,d)?mxUtils.getValue(a.style,mxConstants.STYLE_LOOP,this.graph.defaultLoopStyle):mxUtils.getValue(a.style,mxConstants.STYLE_NOEDGESTYLE,!1)?null:a.style[mxConstants.STYLE_EDGE];"string"==typeof a&&(b=mxStyleRegistry.getValue(a),null==b&&this.isAllowEval()&&(b=mxUtils.eval(a)),a=b);return"function"==typeof a?a:null}; -mxGraphView.prototype.updateFloatingTerminalPoints=function(a,b,c){var d=a.absolutePoints,e=d[0];null==d[d.length-1]&&null!=c&&this.updateFloatingTerminalPoint(a,c,b,!1);null==e&&null!=b&&this.updateFloatingTerminalPoint(a,b,c,!0)};mxGraphView.prototype.updateFloatingTerminalPoint=function(a,b,c,d){a.setAbsoluteTerminalPoint(this.getFloatingTerminalPoint(a,b,c,d),d)}; -mxGraphView.prototype.getFloatingTerminalPoint=function(a,b,c,d){b=this.getTerminalPort(a,b,d);var e=this.getNextPoint(a,c,d),f=this.graph.isOrthogonal(a);c=mxUtils.toRadians(Number(b.style[mxConstants.STYLE_ROTATION]||"0"));var g=new mxPoint(b.getCenterX(),b.getCenterY());if(0!=c)var k=Math.cos(-c),l=Math.sin(-c),e=mxUtils.getRotatedPoint(e,k,l,g);k=parseFloat(a.style[mxConstants.STYLE_PERIMETER_SPACING]||0);k+=parseFloat(a.style[d?mxConstants.STYLE_SOURCE_PERIMETER_SPACING:mxConstants.STYLE_TARGET_PERIMETER_SPACING]|| -0);a=this.getPerimeterPoint(b,e,0==c&&f,k);0!=c&&(k=Math.cos(c),l=Math.sin(c),a=mxUtils.getRotatedPoint(a,k,l,g));return a};mxGraphView.prototype.getTerminalPort=function(a,b,c){a=mxUtils.getValue(a.style,c?mxConstants.STYLE_SOURCE_PORT:mxConstants.STYLE_TARGET_PORT);null!=a&&(a=this.getState(this.graph.getModel().getCell(a)),null!=a&&(b=a));return b}; -mxGraphView.prototype.getPerimeterPoint=function(a,b,c,d){var e=null;if(null!=a){var f=this.getPerimeterFunction(a);if(null!=f&&null!=b&&(d=this.getPerimeterBounds(a,d),0=Math.round(k+g)&&l=f?0:f*f/(a*a+n*n));a>e&&(a=e);e=Math.sqrt(mxUtils.ptSegDistSq(g.x,g.y,k.x,k.y,b,c));-1==mxUtils.relativeCcw(g.x,g.y,k.x,k.y,b,c)&&(e=-e);return new mxPoint((d/2-m-a)/d*-2,e/this.scale)}}return new mxPoint}; -mxGraphView.prototype.updateEdgeLabelOffset=function(a){var b=a.absolutePoints;a.absoluteOffset.x=a.getCenterX();a.absoluteOffset.y=a.getCenterY();if(null!=b&&0c&&a.x>c+2&&a.x<=b)return!0;b=this.graph.container.offsetHeight;c=this.graph.container.clientHeight;return b>c&&a.y>c+2&&a.y<=b?!0:!1}; -mxGraphView.prototype.init=function(){this.installListeners();var a=this.graph;a.dialect==mxConstants.DIALECT_SVG?this.createSvg():a.dialect==mxConstants.DIALECT_VML?this.createVml():this.createHtml()}; -mxGraphView.prototype.installListeners=function(){var a=this.graph,b=a.container;if(null!=b){mxClient.IS_TOUCH&&(mxEvent.addListener(b,"gesturestart",mxUtils.bind(this,function(b){a.fireGestureEvent(b);mxEvent.consume(b)})),mxEvent.addListener(b,"gesturechange",mxUtils.bind(this,function(b){a.fireGestureEvent(b);mxEvent.consume(b)})),mxEvent.addListener(b,"gestureend",mxUtils.bind(this,function(b){a.fireGestureEvent(b);mxEvent.consume(b)})));var c=null;mxEvent.addGestureListeners(b,mxUtils.bind(this, -function(b){!this.isContainerEvent(b)||(mxClient.IS_IE||mxClient.IS_IE11||mxClient.IS_GC||mxClient.IS_OP||mxClient.IS_SF)&&this.isScrollEvent(b)||(a.fireMouseEvent(mxEvent.MOUSE_DOWN,new mxMouseEvent(b)),c=b.pointerId)}),mxUtils.bind(this,function(b){!this.isContainerEvent(b)||null!=c&&b.pointerId!=c||a.fireMouseEvent(mxEvent.MOUSE_MOVE,new mxMouseEvent(b))}),mxUtils.bind(this,function(b){this.isContainerEvent(b)&&a.fireMouseEvent(mxEvent.MOUSE_UP,new mxMouseEvent(b));c=null}));mxEvent.addListener(b, -"dblclick",mxUtils.bind(this,function(b){this.isContainerEvent(b)&&a.dblClick(b)}));var d=function(c){var d=null;mxClient.IS_TOUCH&&(d=mxEvent.getClientX(c),c=mxEvent.getClientY(c),c=mxUtils.convertPoint(b,d,c),d=a.view.getState(a.getCellAt(c.x,c.y)));return d};a.addMouseListener({mouseDown:function(b,c){a.popupMenuHandler.hideMenu()},mouseMove:function(){},mouseUp:function(){}});this.moveHandler=mxUtils.bind(this,function(b){null!=a.tooltipHandler&&a.tooltipHandler.isHideOnHover()&&a.tooltipHandler.hide(); -this.captureDocumentGesture&&a.isMouseDown&&null!=a.container&&!this.isContainerEvent(b)&&"none"!=a.container.style.display&&"hidden"!=a.container.style.visibility&&!mxEvent.isConsumed(b)&&a.fireMouseEvent(mxEvent.MOUSE_MOVE,new mxMouseEvent(b,d(b)))});this.endHandler=mxUtils.bind(this,function(b){this.captureDocumentGesture&&a.isMouseDown&&null!=a.container&&!this.isContainerEvent(b)&&"none"!=a.container.style.display&&"hidden"!=a.container.style.visibility&&a.fireMouseEvent(mxEvent.MOUSE_UP,new mxMouseEvent(b))}); -mxEvent.addGestureListeners(document,null,this.moveHandler,this.endHandler)}}; -mxGraphView.prototype.createHtml=function(){var a=this.graph.container;null!=a&&(this.canvas=this.createHtmlPane("100%","100%"),this.canvas.style.overflow="hidden",this.backgroundPane=this.createHtmlPane("1px","1px"),this.drawPane=this.createHtmlPane("1px","1px"),this.overlayPane=this.createHtmlPane("1px","1px"),this.decoratorPane=this.createHtmlPane("1px","1px"),this.canvas.appendChild(this.backgroundPane),this.canvas.appendChild(this.drawPane),this.canvas.appendChild(this.overlayPane),this.canvas.appendChild(this.decoratorPane), -a.appendChild(this.canvas),this.updateContainerStyle(a),mxClient.IS_QUIRKS&&(a=mxUtils.bind(this,function(a){a=this.getGraphBounds();this.updateHtmlCanvasSize(a.x+a.width+this.graph.border,a.y+a.height+this.graph.border)}),mxEvent.addListener(window,"resize",a)))}; -mxGraphView.prototype.updateHtmlCanvasSize=function(a,b){if(null!=this.graph.container){var c=this.graph.container.offsetHeight;this.canvas.style.width=this.graph.container.offsetWidth")}; -mxGraph.prototype.createHandlers=function(){this.tooltipHandler=this.createTooltipHandler();this.tooltipHandler.setEnabled(!1);this.selectionCellsHandler=this.createSelectionCellsHandler();this.connectionHandler=this.createConnectionHandler();this.connectionHandler.setEnabled(!1);this.graphHandler=this.createGraphHandler();this.panningHandler=this.createPanningHandler();this.panningHandler.panningEnabled=!1;this.popupMenuHandler=this.createPopupMenuHandler()}; -mxGraph.prototype.createTooltipHandler=function(){return new mxTooltipHandler(this)};mxGraph.prototype.createSelectionCellsHandler=function(){return new mxSelectionCellsHandler(this)};mxGraph.prototype.createConnectionHandler=function(){return new mxConnectionHandler(this)};mxGraph.prototype.createGraphHandler=function(){return new mxGraphHandler(this)};mxGraph.prototype.createPanningHandler=function(){return new mxPanningHandler(this)};mxGraph.prototype.createPopupMenuHandler=function(){return new mxPopupMenuHandler(this)}; -mxGraph.prototype.createSelectionModel=function(){return new mxGraphSelectionModel(this)};mxGraph.prototype.createStylesheet=function(){return new mxStylesheet};mxGraph.prototype.createGraphView=function(){return new mxGraphView(this)};mxGraph.prototype.createCellRenderer=function(){return new mxCellRenderer};mxGraph.prototype.createCellEditor=function(){return new mxCellEditor(this)};mxGraph.prototype.getModel=function(){return this.model};mxGraph.prototype.getView=function(){return this.view}; -mxGraph.prototype.getStylesheet=function(){return this.stylesheet};mxGraph.prototype.setStylesheet=function(a){this.stylesheet=a};mxGraph.prototype.getSelectionModel=function(){return this.selectionModel};mxGraph.prototype.setSelectionModel=function(a){this.selectionModel=a}; -mxGraph.prototype.getSelectionCellsForChanges=function(a,b){for(var c=new mxDictionary,d=[],e=mxUtils.bind(this,function(a){if(!c.get(a)&&this.model.contains(a))if(this.model.isEdge(a)||this.model.isVertex(a))c.put(a,!0),d.push(a);else for(var b=this.model.getChildCount(a),f=0;f"+b+""),d&&b.addListener(mxEvent.CLICK,mxUtils.bind(this,function(b,c){this.isEnabled()&&this.setSelectionCell(a)})),this.addCellOverlay(a,b);this.removeCellOverlays(a);return null};mxGraph.prototype.startEditing=function(a){this.startEditingAtCell(null,a)}; -mxGraph.prototype.startEditingAtCell=function(a,b){null!=b&&mxEvent.isMultiTouchEvent(b)||(null==a&&(a=this.getSelectionCell(),null==a||this.isCellEditable(a)||(a=null)),null!=a&&(this.fireEvent(new mxEventObject(mxEvent.START_EDITING,"cell",a,"event",b)),this.cellEditor.startEditing(a,b),this.fireEvent(new mxEventObject(mxEvent.EDITING_STARTED,"cell",a,"event",b))))};mxGraph.prototype.getEditingValue=function(a,b){return this.convertValueToString(a)}; -mxGraph.prototype.stopEditing=function(a){this.cellEditor.stopEditing(a);this.fireEvent(new mxEventObject(mxEvent.EDITING_STOPPED,"cancel",a))};mxGraph.prototype.labelChanged=function(a,b,c){this.model.beginUpdate();try{var d=a.value;this.cellLabelChanged(a,b,this.isAutoSizeCell(a));this.fireEvent(new mxEventObject(mxEvent.LABEL_CHANGED,"cell",a,"value",b,"old",d,"event",c))}finally{this.model.endUpdate()}return a}; -mxGraph.prototype.cellLabelChanged=function(a,b,c){this.model.beginUpdate();try{this.model.setValue(a,b),c&&this.cellSizeUpdated(a,!1)}finally{this.model.endUpdate()}};mxGraph.prototype.escape=function(a){this.fireEvent(new mxEventObject(mxEvent.ESCAPE,"event",a))}; -mxGraph.prototype.click=function(a){var b=a.getEvent(),c=a.getCell(),d=new mxEventObject(mxEvent.CLICK,"event",b,"cell",c);a.isConsumed()&&d.consume();this.fireEvent(d);if(this.isEnabled()&&!mxEvent.isConsumed(b)&&!d.isConsumed()){if(null!=c){if(this.isTransparentClickEvent(b)){var e=!1;a=this.getCellAt(a.graphX,a.graphY,null,null,null,mxUtils.bind(this,function(a){var b=this.isCellSelected(a.cell);e=e||b;return!e||b||a.cell!=c&&this.model.isAncestor(a.cell,c)}));null!=a&&(c=a)}}else if(this.isSwimlaneSelectionEnabled()&& -(c=this.getSwimlaneAt(a.getGraphX(),a.getGraphY()),!(null==c||this.isToggleEvent(b)&&mxEvent.isAltDown(b)))){d=c;for(a=[];null!=d;){var d=this.model.getParent(d),f=this.view.getState(d);this.isSwimlane(d)&&null!=f&&a.push(d)}if(0=e.scrollLeft&&b>=e.scrollTop&&a<=e.scrollLeft+e.clientWidth&&b<=e.scrollTop+e.clientHeight){var f=e.scrollLeft+e.clientWidth- -a;if(fthis.minPageBreakDist)?Math.ceil(d.height/f.height)+1:0,k=a?Math.ceil(d.width/f.width)+1:0,l=(k-1)*f.width,m=(g-1)*f.height;null==this.horizontalPageBreaks&&0this.model.getChildCount(b)&&c--;this.model.add(b,a[l],c+l);this.autoSizeCellsOnAdd&&this.autoSizeCell(a[l],!0);(null==k||k)&&this.isExtendParentsOnAdd(a[l])&&this.isExtendParent(a[l])&&this.extendParent(a[l]);(null==g||g)&&this.constrainChild(a[l]);null!=d&&this.cellConnected(a[l],d,!0);null!=e&&this.cellConnected(a[l],e,!1)}this.fireEvent(new mxEventObject(mxEvent.CELLS_ADDED,"cells",a,"parent",b,"index",c,"source", -d,"target",e,"absolute",f))}finally{this.model.endUpdate()}}};mxGraph.prototype.autoSizeCell=function(a,b){if(null!=b?b:1)for(var c=this.model.getChildCount(a),d=0;d"),f=mxUtils.getSizeForString(k,f,e[mxConstants.STYLE_FONTFAMILY],b,e[mxConstants.STYLE_FONTSTYLE]),d=f.width+g,c=f.height+c,mxUtils.getValue(e,mxConstants.STYLE_HORIZONTAL,!0)||(e=c,c=d,d=e),this.gridEnabled&&(d=this.snap(d+this.gridSize/2),c=this.snap(c+this.gridSize/2)),c=new mxRectangle(0,0,d,c)):(e=4*this.gridSize,c=new mxRectangle(0,0,e,e))}}return c};mxGraph.prototype.resizeCell=function(a,b,c){return this.resizeCells([a],[b],c)[0]}; -mxGraph.prototype.resizeCells=function(a,b,c){c=null!=c?c:this.isRecursiveResize();this.model.beginUpdate();try{var d=this.cellsResized(a,b,c);this.fireEvent(new mxEventObject(mxEvent.RESIZE_CELLS,"cells",a,"bounds",b,"previous",d))}finally{this.model.endUpdate()}return a}; -mxGraph.prototype.cellsResized=function(a,b,c){c=null!=c?c:!1;var d=[];if(null!=a&&null!=b&&a.length==b.length){this.model.beginUpdate();try{for(var e=0;ee.width&&(f=c.width-e.width,c.width-=f);d.x+d.width>e.x+e.width&&(f-=d.x+d.width-e.x-e.width-f);g=0;c.height>e.height&&(g=c.height-e.height,c.height-=g);d.y+d.height> -e.y+e.height&&(g-=d.y+d.height-e.y-e.height-g);d.xg&&(n=0),b>f&&(p=0),this.view.setTranslate(Math.floor(n/2-k.x),Math.floor(p/2-k.y)),this.container.scrollLeft= -(a-g)/2,this.container.scrollTop=(b-f)/2):this.view.setTranslate(a?Math.floor(l.x-k.x/m+n*c/m):l.x,b?Math.floor(l.y-k.y/m+p*d/m):l.y)}; -mxGraph.prototype.zoom=function(a,b){b=null!=b?b:this.centerZoom;var c=Math.round(this.view.scale*a*100)/100,d=this.view.getState(this.getSelectionCell());a=c/this.view.scale;if(this.keepSelectionVisibleOnZoom&&null!=d)d=new mxRectangle(d.x*a,d.y*a,d.width*a,d.height*a),this.view.scale=c,this.scrollRectToVisible(d)||(this.view.revalidate(),this.view.setScale(c));else if(d=mxUtils.hasScrollbars(this.container),b&&!d){var d=this.container.offsetWidth,e=this.container.offsetHeight;if(1b?(b=a.height/b,c=(b-a.height)/2,a.height=b,a.y-=Math.min(a.y,c),d=Math.min(this.container.scrollHeight,a.y+a.height),a.height=d-a.y):(b*=a.width,c=(b-a.width)/2,a.width=b,a.x-=Math.min(a.x,c),c=Math.min(this.container.scrollWidth, -a.x+a.width),a.width=c-a.x);b=this.container.clientWidth/a.width;c=this.view.scale*b;mxUtils.hasScrollbars(this.container)?(this.view.setScale(c),this.container.scrollLeft=Math.round(a.x*b),this.container.scrollTop=Math.round(a.y*b)):this.view.scaleAndTranslate(c,this.view.translate.x-a.x/this.view.scale,this.view.translate.y-a.y/this.view.scale)}; -mxGraph.prototype.scrollCellToVisible=function(a,b){var c=-this.view.translate.x,d=-this.view.translate.y,e=this.view.getState(a);null!=e&&(c=new mxRectangle(c+e.x,d+e.y,e.width,e.height),b&&null!=this.container&&(d=this.container.clientWidth,e=this.container.clientHeight,c.x=c.getCenterX()-d/2,c.width=d,c.y=c.getCenterY()-e/2,c.height=e),d=new mxPoint(this.view.translate.x,this.view.translate.y),this.scrollRectToVisible(c)&&(c=new mxPoint(this.view.translate.x,this.view.translate.y),this.view.translate.x= -d.x,this.view.translate.y=d.y,this.view.setTranslate(c.x,c.y)))}; -mxGraph.prototype.scrollRectToVisible=function(a){var b=!1;if(null!=a){var c=this.container.offsetWidth,d=this.container.offsetHeight,e=Math.min(c,a.width),f=Math.min(d,a.height);if(mxUtils.hasScrollbars(this.container)){c=this.container;a.x+=this.view.translate.x;a.y+=this.view.translate.y;var g=c.scrollLeft-a.x,d=Math.max(g-c.scrollLeft,0);0g+c&&(this.view.translate.x-=(a.x+e-c-g)/l,b=!0);a.y+f>k+d&&(this.view.translate.y-=(a.y+f-d-k)/l,b=!0);a.x")):this.setCellWarning(f,null);c=c&&null==g}d="";this.isCellCollapsed(a)&&!c&&(d+=(mxResources.get(this.containsValidationErrorsResource)||this.containsValidationErrorsResource)+"\n");d=this.model.isEdge(a)?d+ -(this.getEdgeValidationError(a,this.model.getTerminal(a,!0),this.model.getTerminal(a,!1))||""):d+(this.getCellValidationError(a)||"");e=this.validateCell(a,b);null!=e&&(d+=e);null==this.model.getParent(a)&&this.view.validate();return 0f.max||bf.max||c")),null==e&&null!=a.overlays&&a.overlays.visit(function(a,c){null!=e||b!=c.node&&b.parentNode!=c.node||(e=c.overlay.toString())}),null==e&&(c=this.selectionCellsHandler.getHandler(a.cell),null!=c&&"function"==typeof c.getTooltipForNode&&(e=c.getTooltipForNode(b))),null== -e&&(e=this.getTooltipForCell(a.cell)));return e};mxGraph.prototype.getTooltipForCell=function(a){return null!=a&&null!=a.getTooltip?a.getTooltip():this.convertValueToString(a)};mxGraph.prototype.getLinkForCell=function(a){return null};mxGraph.prototype.getCursorForMouseEvent=function(a){return this.getCursorForCell(a.getCell())};mxGraph.prototype.getCursorForCell=function(a){return null}; -mxGraph.prototype.getStartSize=function(a,b){var c=new mxRectangle,d=this.getCurrentCellStyle(a,b),e=parseInt(mxUtils.getValue(d,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_STARTSIZE));mxUtils.getValue(d,mxConstants.STYLE_HORIZONTAL,!0)?c.height=e:c.width=e;return c}; -mxGraph.prototype.getSwimlaneDirection=function(a){var b=mxUtils.getValue(a,mxConstants.STYLE_DIRECTION,mxConstants.DIRECTION_EAST),c=1==mxUtils.getValue(a,mxConstants.STYLE_FLIPH,0),d=1==mxUtils.getValue(a,mxConstants.STYLE_FLIPV,0);a=mxUtils.getValue(a,mxConstants.STYLE_HORIZONTAL,!0)?0:3;b==mxConstants.DIRECTION_NORTH?a--:b==mxConstants.DIRECTION_WEST?a+=2:b==mxConstants.DIRECTION_SOUTH&&(a+=1);b=mxUtils.mod(a,2);c&&1==b&&(a+=2);d&&0==b&&(a+=2);return[mxConstants.DIRECTION_NORTH,mxConstants.DIRECTION_EAST, -mxConstants.DIRECTION_SOUTH,mxConstants.DIRECTION_WEST][mxUtils.mod(a,4)]};mxGraph.prototype.getActualStartSize=function(a,b){var c=new mxRectangle;if(this.isSwimlane(a,b)){var d=this.getCurrentCellStyle(a,b),e=parseInt(mxUtils.getValue(d,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_STARTSIZE)),d=this.getSwimlaneDirection(d);d==mxConstants.DIRECTION_NORTH?c.y=e:d==mxConstants.DIRECTION_WEST?c.x=e:d==mxConstants.DIRECTION_SOUTH?c.height=e:c.width=e}return c}; -mxGraph.prototype.getImage=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_IMAGE]:null};mxGraph.prototype.isTransparentState=function(a){var b=!1;if(null!=a)var b=mxUtils.getValue(a.style,mxConstants.STYLE_STROKECOLOR,mxConstants.NONE),c=mxUtils.getValue(a.style,mxConstants.STYLE_FILLCOLOR,mxConstants.NONE),b=b==mxConstants.NONE&&c==mxConstants.NONE&&null==this.getImage(a);return b}; -mxGraph.prototype.getVerticalAlign=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_VERTICAL_ALIGN]||mxConstants.ALIGN_MIDDLE:null};mxGraph.prototype.getIndicatorColor=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_INDICATOR_COLOR]:null};mxGraph.prototype.getIndicatorGradientColor=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_INDICATOR_GRADIENTCOLOR]:null}; -mxGraph.prototype.getIndicatorShape=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_INDICATOR_SHAPE]:null};mxGraph.prototype.getIndicatorImage=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_INDICATOR_IMAGE]:null};mxGraph.prototype.getBorder=function(){return this.border};mxGraph.prototype.setBorder=function(a){this.border=a}; -mxGraph.prototype.isSwimlane=function(a,b){return null==a||this.model.getParent(a)==this.model.getRoot()||this.model.isEdge(a)?!1:this.getCurrentCellStyle(a,b)[mxConstants.STYLE_SHAPE]==mxConstants.SHAPE_SWIMLANE};mxGraph.prototype.isResizeContainer=function(){return this.resizeContainer};mxGraph.prototype.setResizeContainer=function(a){this.resizeContainer=a};mxGraph.prototype.isEnabled=function(){return this.enabled};mxGraph.prototype.setEnabled=function(a){this.enabled=a}; -mxGraph.prototype.isEscapeEnabled=function(){return this.escapeEnabled};mxGraph.prototype.setEscapeEnabled=function(a){this.escapeEnabled=a};mxGraph.prototype.isInvokesStopCellEditing=function(){return this.invokesStopCellEditing};mxGraph.prototype.setInvokesStopCellEditing=function(a){this.invokesStopCellEditing=a};mxGraph.prototype.isEnterStopsCellEditing=function(){return this.enterStopsCellEditing};mxGraph.prototype.setEnterStopsCellEditing=function(a){this.enterStopsCellEditing=a}; -mxGraph.prototype.isCellLocked=function(a){var b=this.model.getGeometry(a);return this.isCellsLocked()||null!=b&&this.model.isVertex(a)&&b.relative};mxGraph.prototype.isCellsLocked=function(){return this.cellsLocked};mxGraph.prototype.setCellsLocked=function(a){this.cellsLocked=a};mxGraph.prototype.getCloneableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.isCellCloneable(a)}))}; -mxGraph.prototype.isCellCloneable=function(a){a=this.getCurrentCellStyle(a);return this.isCellsCloneable()&&0!=a[mxConstants.STYLE_CLONEABLE]};mxGraph.prototype.isCellsCloneable=function(){return this.cellsCloneable};mxGraph.prototype.setCellsCloneable=function(a){this.cellsCloneable=a};mxGraph.prototype.getExportableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.canExportCell(a)}))};mxGraph.prototype.canExportCell=function(a){return this.exportEnabled}; -mxGraph.prototype.getImportableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.canImportCell(a)}))};mxGraph.prototype.canImportCell=function(a){return this.importEnabled};mxGraph.prototype.isCellSelectable=function(a){return this.isCellsSelectable()};mxGraph.prototype.isCellsSelectable=function(){return this.cellsSelectable};mxGraph.prototype.setCellsSelectable=function(a){this.cellsSelectable=a}; -mxGraph.prototype.getDeletableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.isCellDeletable(a)}))};mxGraph.prototype.isCellDeletable=function(a){a=this.getCurrentCellStyle(a);return this.isCellsDeletable()&&0!=a[mxConstants.STYLE_DELETABLE]};mxGraph.prototype.isCellsDeletable=function(){return this.cellsDeletable};mxGraph.prototype.setCellsDeletable=function(a){this.cellsDeletable=a}; -mxGraph.prototype.isLabelMovable=function(a){return!this.isCellLocked(a)&&(this.model.isEdge(a)&&this.edgeLabelsMovable||this.model.isVertex(a)&&this.vertexLabelsMovable)};mxGraph.prototype.isCellRotatable=function(a){return 0!=this.getCurrentCellStyle(a)[mxConstants.STYLE_ROTATABLE]};mxGraph.prototype.getMovableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.isCellMovable(a)}))}; -mxGraph.prototype.isCellMovable=function(a){var b=this.getCurrentCellStyle(a);return this.isCellsMovable()&&!this.isCellLocked(a)&&0!=b[mxConstants.STYLE_MOVABLE]};mxGraph.prototype.isCellsMovable=function(){return this.cellsMovable};mxGraph.prototype.setCellsMovable=function(a){this.cellsMovable=a};mxGraph.prototype.isGridEnabled=function(){return this.gridEnabled};mxGraph.prototype.setGridEnabled=function(a){this.gridEnabled=a};mxGraph.prototype.isPortsEnabled=function(){return this.portsEnabled}; -mxGraph.prototype.setPortsEnabled=function(a){this.portsEnabled=a};mxGraph.prototype.getGridSize=function(){return this.gridSize};mxGraph.prototype.setGridSize=function(a){this.gridSize=a};mxGraph.prototype.getTolerance=function(){return this.tolerance};mxGraph.prototype.setTolerance=function(a){this.tolerance=a};mxGraph.prototype.isVertexLabelsMovable=function(){return this.vertexLabelsMovable};mxGraph.prototype.setVertexLabelsMovable=function(a){this.vertexLabelsMovable=a}; -mxGraph.prototype.isEdgeLabelsMovable=function(){return this.edgeLabelsMovable};mxGraph.prototype.setEdgeLabelsMovable=function(a){this.edgeLabelsMovable=a};mxGraph.prototype.isSwimlaneNesting=function(){return this.swimlaneNesting};mxGraph.prototype.setSwimlaneNesting=function(a){this.swimlaneNesting=a};mxGraph.prototype.isSwimlaneSelectionEnabled=function(){return this.swimlaneSelectionEnabled};mxGraph.prototype.setSwimlaneSelectionEnabled=function(a){this.swimlaneSelectionEnabled=a}; -mxGraph.prototype.isMultigraph=function(){return this.multigraph};mxGraph.prototype.setMultigraph=function(a){this.multigraph=a};mxGraph.prototype.isAllowLoops=function(){return this.allowLoops};mxGraph.prototype.setAllowDanglingEdges=function(a){this.allowDanglingEdges=a};mxGraph.prototype.isAllowDanglingEdges=function(){return this.allowDanglingEdges};mxGraph.prototype.setConnectableEdges=function(a){this.connectableEdges=a};mxGraph.prototype.isConnectableEdges=function(){return this.connectableEdges}; -mxGraph.prototype.setCloneInvalidEdges=function(a){this.cloneInvalidEdges=a};mxGraph.prototype.isCloneInvalidEdges=function(){return this.cloneInvalidEdges};mxGraph.prototype.setAllowLoops=function(a){this.allowLoops=a};mxGraph.prototype.isDisconnectOnMove=function(){return this.disconnectOnMove};mxGraph.prototype.setDisconnectOnMove=function(a){this.disconnectOnMove=a};mxGraph.prototype.isDropEnabled=function(){return this.dropEnabled}; -mxGraph.prototype.setDropEnabled=function(a){this.dropEnabled=a};mxGraph.prototype.isSplitEnabled=function(){return this.splitEnabled};mxGraph.prototype.setSplitEnabled=function(a){this.splitEnabled=a};mxGraph.prototype.isCellResizable=function(a){var b=this.getCurrentCellStyle(a);return this.isCellsResizable()&&!this.isCellLocked(a)&&"0"!=mxUtils.getValue(b,mxConstants.STYLE_RESIZABLE,"1")};mxGraph.prototype.isCellsResizable=function(){return this.cellsResizable}; -mxGraph.prototype.setCellsResizable=function(a){this.cellsResizable=a};mxGraph.prototype.isTerminalPointMovable=function(a,b){return!0};mxGraph.prototype.isCellBendable=function(a){var b=this.getCurrentCellStyle(a);return this.isCellsBendable()&&!this.isCellLocked(a)&&0!=b[mxConstants.STYLE_BENDABLE]};mxGraph.prototype.isCellsBendable=function(){return this.cellsBendable};mxGraph.prototype.setCellsBendable=function(a){this.cellsBendable=a}; -mxGraph.prototype.isCellEditable=function(a){var b=this.getCurrentCellStyle(a);return this.isCellsEditable()&&!this.isCellLocked(a)&&0!=b[mxConstants.STYLE_EDITABLE]};mxGraph.prototype.isCellsEditable=function(){return this.cellsEditable};mxGraph.prototype.setCellsEditable=function(a){this.cellsEditable=a};mxGraph.prototype.isCellDisconnectable=function(a,b,c){return this.isCellsDisconnectable()&&!this.isCellLocked(a)};mxGraph.prototype.isCellsDisconnectable=function(){return this.cellsDisconnectable}; -mxGraph.prototype.setCellsDisconnectable=function(a){this.cellsDisconnectable=a};mxGraph.prototype.isValidSource=function(a){return null==a&&this.allowDanglingEdges||null!=a&&(!this.model.isEdge(a)||this.connectableEdges)&&this.isCellConnectable(a)};mxGraph.prototype.isValidTarget=function(a){return this.isValidSource(a)};mxGraph.prototype.isValidConnection=function(a,b){return this.isValidSource(a)&&this.isValidTarget(b)};mxGraph.prototype.setConnectable=function(a){this.connectionHandler.setEnabled(a)}; -mxGraph.prototype.isConnectable=function(){return this.connectionHandler.isEnabled()};mxGraph.prototype.setTooltips=function(a){this.tooltipHandler.setEnabled(a)};mxGraph.prototype.setPanning=function(a){this.panningHandler.panningEnabled=a};mxGraph.prototype.isEditing=function(a){if(null!=this.cellEditor){var b=this.cellEditor.getEditingCell();return null==a?null!=b:a==b}return!1};mxGraph.prototype.isAutoSizeCell=function(a){a=this.getCurrentCellStyle(a);return this.isAutoSizeCells()||1==a[mxConstants.STYLE_AUTOSIZE]}; -mxGraph.prototype.isAutoSizeCells=function(){return this.autoSizeCells};mxGraph.prototype.setAutoSizeCells=function(a){this.autoSizeCells=a};mxGraph.prototype.isExtendParent=function(a){return!this.getModel().isEdge(a)&&this.isExtendParents()};mxGraph.prototype.isExtendParents=function(){return this.extendParents};mxGraph.prototype.setExtendParents=function(a){this.extendParents=a};mxGraph.prototype.isExtendParentsOnAdd=function(a){return this.extendParentsOnAdd}; -mxGraph.prototype.setExtendParentsOnAdd=function(a){this.extendParentsOnAdd=a};mxGraph.prototype.isExtendParentsOnMove=function(){return this.extendParentsOnMove};mxGraph.prototype.setExtendParentsOnMove=function(a){this.extendParentsOnMove=a};mxGraph.prototype.isRecursiveResize=function(a){return this.recursiveResize};mxGraph.prototype.setRecursiveResize=function(a){this.recursiveResize=a};mxGraph.prototype.isConstrainChild=function(a){return this.isConstrainChildren()&&!this.getModel().isEdge(this.getModel().getParent(a))}; -mxGraph.prototype.isConstrainChildren=function(){return this.constrainChildren};mxGraph.prototype.setConstrainChildren=function(a){this.constrainChildren=a};mxGraph.prototype.isConstrainRelativeChildren=function(){return this.constrainRelativeChildren};mxGraph.prototype.setConstrainRelativeChildren=function(a){this.constrainRelativeChildren=a};mxGraph.prototype.isAllowNegativeCoordinates=function(){return this.allowNegativeCoordinates}; -mxGraph.prototype.setAllowNegativeCoordinates=function(a){this.allowNegativeCoordinates=a};mxGraph.prototype.getOverlap=function(a){return this.isAllowOverlapParent(a)?this.defaultOverlap:0};mxGraph.prototype.isAllowOverlapParent=function(a){return!1};mxGraph.prototype.getFoldableCells=function(a,b){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.isCellFoldable(a,b)}))}; -mxGraph.prototype.isCellFoldable=function(a,b){var c=this.getCurrentCellStyle(a);return 0mxUtils.indexOf(a,g);)g=this.model.getParent(g);return this.model.isLayer(c)||null!=g?null:c};mxGraph.prototype.getDefaultParent=function(){var a=this.getCurrentRoot();null==a&&(a=this.defaultParent,null==a&&(a=this.model.getRoot(),a=this.model.getChildAt(a,0)));return a};mxGraph.prototype.setDefaultParent=function(a){this.defaultParent=a};mxGraph.prototype.getSwimlane=function(a){for(;null!=a&&!this.isSwimlane(a);)a=this.model.getParent(a);return a}; -mxGraph.prototype.getSwimlaneAt=function(a,b,c){null==c&&(c=this.getCurrentRoot(),null==c&&(c=this.model.getRoot()));if(null!=c)for(var d=this.model.getChildCount(c),e=0;ea.width*e||0a.height*e)return!0}return!1};mxGraph.prototype.getChildVertices=function(a){return this.getChildCells(a,!0,!1)};mxGraph.prototype.getChildEdges=function(a){return this.getChildCells(a,!1,!0)}; -mxGraph.prototype.getChildCells=function(a,b,c){a=null!=a?a:this.getDefaultParent();a=this.model.getChildCells(a,null!=b?b:!1,null!=c?c:!1);b=[];for(c=0;c=a&&u.y+u.height<=p&&u.y>=b&&u.x+u.width<=n)&&f.push(t);x&&!l||this.getCells(a,b,c,d,t,f,g,k,l)}}}return f};mxGraph.prototype.getCellsBeyond=function(a,b,c,d,e){var f=[];if(d||e)if(null==c&&(c=this.getDefaultParent()),null!=c)for(var g=this.model.getChildCount(c),k=0;k=a)&&(!e||m.y>=b)&&f.push(l)}return f}; -mxGraph.prototype.findTreeRoots=function(a,b,c){b=null!=b?b:!1;c=null!=c?c:!1;var d=[];if(null!=a){for(var e=this.getModel(),f=e.getChildCount(a),g=null,k=0,l=0;lk&&(k=n,g=m)}}0==d.length&&null!=g&&d.push(g)}return d}; -mxGraph.prototype.traverse=function(a,b,c,d,e,f){if(null!=c&&null!=a&&(b=null!=b?b:!0,f=null!=f?f:!1,e=e||new mxDictionary,!e.get(a)&&(e.put(a,!0),d=c(a,d),null==d||d))&&(d=this.model.getEdgeCount(a),0b?f-1:b)),this.setSelectionCell(a)):this.getCurrentRoot()!=d&&this.setSelectionCell(d)};mxGraph.prototype.selectAll=function(a,b){a=a||this.getDefaultParent();var c=b?this.model.filterDescendants(mxUtils.bind(this,function(b){return b!=a&&null!=this.view.getState(b)}),a):this.model.getChildren(a);null!=c&&this.setSelectionCells(c)};mxGraph.prototype.selectVertices=function(a,b){this.selectCells(!0,!1,a,b)}; -mxGraph.prototype.selectEdges=function(a){this.selectCells(!1,!0,a)};mxGraph.prototype.selectCells=function(a,b,c,d){c=c||this.getDefaultParent();var e=mxUtils.bind(this,function(c){return null!=this.view.getState(c)&&((d||0==this.model.getChildCount(c))&&this.model.isVertex(c)&&a&&!this.model.isEdge(this.model.getParent(c))||this.model.isEdge(c)&&b)});c=this.model.filterDescendants(e,c);null!=c&&this.setSelectionCells(c)}; -mxGraph.prototype.selectCellForEvent=function(a,b){var c=this.isCellSelected(a);this.isToggleEvent(b)?c?this.removeSelectionCell(a):this.addSelectionCell(a):c&&1==this.getSelectionCount()||this.setSelectionCell(a)};mxGraph.prototype.selectCellsForEvent=function(a,b){this.isToggleEvent(b)?this.addSelectionCells(a):this.setSelectionCells(a)}; -mxGraph.prototype.createHandler=function(a){var b=null;if(null!=a)if(this.model.isEdge(a.cell))var b=a.getVisibleTerminalState(!0),c=a.getVisibleTerminalState(!1),d=this.getCellGeometry(a.cell),b=this.view.getEdgeStyle(a,null!=d?d.points:null,b,c),b=this.createEdgeHandler(a,b);else b=this.createVertexHandler(a);return b};mxGraph.prototype.createVertexHandler=function(a){return new mxVertexHandler(a)}; -mxGraph.prototype.createEdgeHandler=function(a,b){return b==mxEdgeStyle.Loop||b==mxEdgeStyle.ElbowConnector||b==mxEdgeStyle.SideToSide||b==mxEdgeStyle.TopToBottom?this.createElbowEdgeHandler(a):b==mxEdgeStyle.SegmentConnector||b==mxEdgeStyle.OrthConnector?this.createEdgeSegmentHandler(a):new mxEdgeHandler(a)};mxGraph.prototype.createEdgeSegmentHandler=function(a){return new mxEdgeSegmentHandler(a)};mxGraph.prototype.createElbowEdgeHandler=function(a){return new mxElbowEdgeHandler(a)}; -mxGraph.prototype.addMouseListener=function(a){null==this.mouseListeners&&(this.mouseListeners=[]);this.mouseListeners.push(a)};mxGraph.prototype.removeMouseListener=function(a){if(null!=this.mouseListeners)for(var b=0;bthis.doubleClickCounter){if(this.doubleClickCounter++,d=!1,a==mxEvent.MOUSE_UP?b.getCell()==this.lastTouchCell&&null!=this.lastTouchCell&&(this.lastTouchTime=0,d=this.lastTouchCell,this.lastTouchCell=null,mxClient.IS_QUIRKS&&b.getSource().fireEvent("ondblclick"),this.dblClick(b.getEvent(), -d),d=!0):(this.fireDoubleClick=!0,this.lastTouchTime=0),!mxClient.IS_QUIRKS||d){mxEvent.consume(b.getEvent());return}}else{if(null==this.lastTouchEvent||this.lastTouchEvent!=b.getEvent())this.lastTouchCell=b.getCell(),this.lastTouchX=b.getX(),this.lastTouchY=b.getY(),this.lastTouchTime=d,this.lastTouchEvent=b.getEvent(),this.doubleClickCounter=0}else if((this.isMouseDown||a==mxEvent.MOUSE_UP)&&this.fireDoubleClick){this.fireDoubleClick=!1;d=this.lastTouchCell;this.lastTouchCell=null;this.isMouseDown= -!1;(null!=d||(mxEvent.isTouchEvent(b.getEvent())||mxEvent.isPenEvent(b.getEvent()))&&(mxClient.IS_GC||mxClient.IS_SF))&&Math.abs(this.lastTouchX-b.getX())c.x&&(f-=c.x);0>c.y&&(g-=c.y);if(b.translate.x!=f||b.translate.y!=g)b.translate.x=f,b.translate.y=g,a=!0;var c=b.translate,d=this.source.getView().scale,f=d/b.scale,g=1/b.scale,k=this.source.container;this.bounds=new mxRectangle((c.x-e.x-this.source.panDx)/g,(c.y-e.y-this.source.panDy)/g,k.clientWidth/f,k.clientHeight/f);this.bounds.x+=this.source.container.scrollLeft*b.scale/d;this.bounds.y+=this.source.container.scrollTop*b.scale/d;c=this.selectionBorder.bounds;if(c.x!=this.bounds.x|| -c.y!=this.bounds.y||c.width!=this.bounds.width||c.height!=this.bounds.height)this.selectionBorder.bounds=this.bounds,this.selectionBorder.redraw();c=this.sizer.bounds;b=new mxRectangle(this.bounds.x+this.bounds.width-c.width/2,this.bounds.y+this.bounds.height-c.height/2,c.width,c.height);if(c.x!=b.x||c.y!=b.y||c.width!=b.width||c.height!=b.height)this.sizer.bounds=b,"hidden"!=this.sizer.node.style.visibility&&this.sizer.redraw();a&&this.outline.view.revalidate()}}}; -mxOutline.prototype.mouseDown=function(a,b){if(this.enabled&&this.showViewport){var c=mxEvent.isMouseEvent(b.getEvent())?0:this.source.tolerance,c=this.source.allowHandleBoundsCheck&&(mxClient.IS_IE||0=this.max)||!this.source&&(0==this.max||f>=this.max))&&(g+=this.countError+"\n"),null!=this.validNeighbors&&null!=this.typeError&&0this.graph.model.getChildCount(e),g=new mxDictionary;a=this.graph.getOpposites(this.graph.getEdges(this.cell),this.cell);for(b=0;b=this.cellCount&&!this.livePreviewActive&&this.allowLivePreview?this.cloning&&this.livePreviewActive||(this.livePreviewUsed=this.livePreviewActive=!0):this.livePreviewUsed||null!=this.shape||(this.shape=this.createPreviewShape(this.bounds))}; -mxGraphHandler.prototype.mouseMove=function(a,b){var c=this.graph;if(b.isConsumed()||!c.isMouseDown||null==this.cell||null==this.first||null==this.bounds||this.suspended)!this.isMoveEnabled()&&!this.isCloneEnabled()||!this.updateCursor||b.isConsumed()||null==b.getState()&&null==b.sourceState||c.isMouseDown||(d=c.getCursorForMouseEvent(b),null==d&&c.isEnabled()&&c.isCellMovable(b.getCell())&&(d=c.getModel().isEdge(b.getCell())?mxConstants.CURSOR_MOVABLE_EDGE:mxConstants.CURSOR_MOVABLE_VERTEX),null!= -d&&null!=b.sourceState&&b.sourceState.setCursor(d));else if(mxEvent.isMultiTouchEvent(b.getEvent()))this.reset();else{var d=this.getDelta(b),e=c.tolerance;if(null!=this.shape||this.livePreviewActive||Math.abs(d.x)>e||Math.abs(d.y)>e){null==this.highlight&&(this.highlight=new mxCellHighlight(this.graph,mxConstants.DROP_TARGET_COLOR,3));var e=c.isCloneEvent(b.getEvent())&&c.isCellsCloneable()&&this.isCloneEnabled(),f=c.isGridEnabledEvent(b.getEvent()),g=b.getCell(),k=!0,l=null;this.cloning=e;c.isDropEnabled()&& -this.highlightEnabled&&(l=c.getDropTarget(this.cells,b.getEvent(),g,e));var m=c.getView().getState(l),n=!1;null!=m&&(e||this.isValidDropTarget(l,b))?(this.target!=l&&(this.target=l,this.setHighlightColor(mxConstants.DROP_TARGET_COLOR)),n=!0):(this.target=null,this.connectOnDrop&&null!=g&&1==this.cells.length&&c.getModel().isVertex(g)&&c.isCellConnectable(g)&&(m=c.getView().getState(g),null!=m&&(g=null==c.getEdgeValidationError(null,this.cell,g)?mxConstants.VALID_COLOR:mxConstants.INVALID_CONNECT_TARGET_COLOR, -this.setHighlightColor(g),n=!0)));null!=m&&n?this.highlight.highlight(m):this.highlight.hide();null!=this.guide&&this.useGuidesForEvent(b)?(d=this.guide.move(this.bounds,d,f,e),k=!1):d=this.graph.snapDelta(d,this.bounds,!f,!1,!1);null!=this.guide&&k&&this.guide.hide();c.isConstrainedEvent(b.getEvent())&&(Math.abs(d.x)>Math.abs(d.y)?d.y=0:d.x=0);this.checkPreview();if(this.currentDx!=d.x||this.currentDy!=d.y)this.currentDx=d.x,this.currentDy=d.y,this.updatePreview()}this.updateHint(b);this.consumeMouseEvent(mxEvent.MOUSE_MOVE, -b);mxEvent.consume(b.getEvent())}};mxGraphHandler.prototype.updatePreview=function(a){this.livePreviewUsed&&!a?null!=this.cells&&(this.setHandlesVisibleForCells(this.graph.selectionCellsHandler.getHandledSelectionCells(),!1),this.updateLivePreview(this.currentDx,this.currentDy)):this.updatePreviewShape()}; -mxGraphHandler.prototype.updatePreviewShape=function(){null!=this.shape&&null!=this.pBounds&&(this.shape.bounds=new mxRectangle(Math.round(this.pBounds.x+this.currentDx),Math.round(this.pBounds.y+this.currentDy),this.pBounds.width,this.pBounds.height),this.shape.redraw())}; -mxGraphHandler.prototype.updateLivePreview=function(a,b){if(!this.suspended){var c=[];null!=this.allCells&&this.allCells.visit(mxUtils.bind(this,function(d,e){var f=this.graph.view.getState(e.cell);f!=e&&(e.destroy(),null!=f?this.allCells.put(e.cell,f):this.allCells.remove(e.cell),e=f);null!=e&&(f=e.clone(),c.push([e,f]),null!=e.shape&&(null==e.shape.originalPointerEvents&&(e.shape.originalPointerEvents=e.shape.pointerEvents),e.shape.pointerEvents=!1,null!=e.text&&(null==e.text.originalPointerEvents&& -(e.text.originalPointerEvents=e.text.pointerEvents),e.text.pointerEvents=!1)),this.graph.model.isVertex(e.cell))&&((e.x+=a,e.y+=b,this.cloning)?null!=e.text&&(e.text.updateBoundingBox(),null!=e.text.boundingBox&&(e.text.boundingBox.x+=a,e.text.boundingBox.y+=b),null!=e.text.unrotatedBoundingBox&&(e.text.unrotatedBoundingBox.x+=a,e.text.unrotatedBoundingBox.y+=b)):(e.view.graph.cellRenderer.redraw(e,!0),e.view.invalidate(e.cell),e.invalid=!1,null!=e.control&&null!=e.control.node&&(e.control.node.style.visibility= -"hidden")))}));if(0==c.length)this.reset();else{for(var d=this.graph.view.scale,e=0;ethis.graph.tolerance||Math.abs(this.dy)>this.graph.tolerance;!c&&this.active&&this.fireEvent(new mxEventObject(mxEvent.PAN_START, -"event",b))}(this.active||this.panningTrigger)&&b.consume()};mxPanningHandler.prototype.mouseUp=function(a,b){if(this.active){if(null!=this.dx&&null!=this.dy){if(!this.graph.useScrollbarsForPanning||!mxUtils.hasScrollbars(this.graph.container)){var c=this.graph.getView().scale,d=this.graph.getView().translate;this.graph.panGraph(0,0);this.panGraph(d.x+this.dx/c,d.y+this.dy/c)}b.consume()}this.fireEvent(new mxEventObject(mxEvent.PAN_END,"event",b))}this.reset()}; -mxPanningHandler.prototype.zoomGraph=function(a){var b=Math.round(this.initialScale*a.scale*100)/100;null!=this.minScale&&(b=Math.max(this.minScale,b));null!=this.maxScale&&(b=Math.min(this.maxScale,b));this.graph.view.scale!=b&&(this.graph.zoomTo(b),mxEvent.consume(a))};mxPanningHandler.prototype.reset=function(){this.panningTrigger=!1;this.mouseDownEvent=null;this.active=!1;this.dy=this.dx=null};mxPanningHandler.prototype.panGraph=function(a,b){this.graph.getView().setTranslate(a,b)}; -mxPanningHandler.prototype.destroy=function(){this.graph.removeMouseListener(this);this.graph.removeListener(this.forcePanningHandler);this.graph.removeListener(this.gestureHandler);mxEvent.removeListener(document,"mouseup",this.mouseUpListener)}; -function mxPopupMenuHandler(a,b){null!=a&&(this.graph=a,this.factoryMethod=b,this.graph.addMouseListener(this),this.gestureHandler=mxUtils.bind(this,function(a,b){this.inTolerance=!1}),this.graph.addListener(mxEvent.GESTURE,this.gestureHandler),this.init())}mxPopupMenuHandler.prototype=new mxPopupMenu;mxPopupMenuHandler.prototype.constructor=mxPopupMenuHandler;mxPopupMenuHandler.prototype.graph=null;mxPopupMenuHandler.prototype.selectOnPopup=!0; -mxPopupMenuHandler.prototype.clearSelectionOnBackground=!0;mxPopupMenuHandler.prototype.triggerX=null;mxPopupMenuHandler.prototype.triggerY=null;mxPopupMenuHandler.prototype.screenX=null;mxPopupMenuHandler.prototype.screenY=null;mxPopupMenuHandler.prototype.init=function(){mxPopupMenu.prototype.init.apply(this);mxEvent.addGestureListeners(this.div,mxUtils.bind(this,function(a){this.graph.tooltipHandler.hide()}))};mxPopupMenuHandler.prototype.isSelectOnPopup=function(a){return this.selectOnPopup}; -mxPopupMenuHandler.prototype.mouseDown=function(a,b){this.isEnabled()&&!mxEvent.isMultiTouchEvent(b.getEvent())&&(this.hideMenu(),this.triggerX=b.getGraphX(),this.triggerY=b.getGraphY(),this.screenX=mxEvent.getMainEvent(b.getEvent()).screenX,this.screenY=mxEvent.getMainEvent(b.getEvent()).screenY,this.popupTrigger=this.isPopupTrigger(b),this.inTolerance=!0)}; -mxPopupMenuHandler.prototype.mouseMove=function(a,b){this.inTolerance&&null!=this.screenX&&null!=this.screenY&&(Math.abs(mxEvent.getMainEvent(b.getEvent()).screenX-this.screenX)>this.graph.tolerance||Math.abs(mxEvent.getMainEvent(b.getEvent()).screenY-this.screenY)>this.graph.tolerance)&&(this.inTolerance=!1)}; -mxPopupMenuHandler.prototype.mouseUp=function(a,b){if(this.popupTrigger&&this.inTolerance&&null!=this.triggerX&&null!=this.triggerY){var c=this.getCellForPopupEvent(b);this.graph.isEnabled()&&this.isSelectOnPopup(b)&&null!=c&&!this.graph.isCellSelected(c)?this.graph.setSelectionCell(c):this.clearSelectionOnBackground&&null==c&&this.graph.clearSelection();this.graph.tooltipHandler.hide();var d=mxUtils.getScrollOrigin();this.popup(b.getX()+d.x+1,b.getY()+d.y+1,c,b.getEvent());b.consume()}this.inTolerance= -this.popupTrigger=!1};mxPopupMenuHandler.prototype.getCellForPopupEvent=function(a){return a.getCell()};mxPopupMenuHandler.prototype.destroy=function(){this.graph.removeMouseListener(this);this.graph.removeListener(this.gestureHandler);mxPopupMenu.prototype.destroy.apply(this)}; -function mxCellMarker(a,b,c,d){mxEventSource.call(this);null!=a&&(this.graph=a,this.validColor=null!=b?b:mxConstants.DEFAULT_VALID_COLOR,this.invalidColor=null!=c?c:mxConstants.DEFAULT_INVALID_COLOR,this.hotspot=null!=d?d:mxConstants.DEFAULT_HOTSPOT,this.highlight=new mxCellHighlight(a))}mxUtils.extend(mxCellMarker,mxEventSource);mxCellMarker.prototype.graph=null;mxCellMarker.prototype.enabled=!0;mxCellMarker.prototype.hotspot=mxConstants.DEFAULT_HOTSPOT;mxCellMarker.prototype.hotspotEnabled=!1; -mxCellMarker.prototype.validColor=null;mxCellMarker.prototype.invalidColor=null;mxCellMarker.prototype.currentColor=null;mxCellMarker.prototype.validState=null;mxCellMarker.prototype.markedState=null;mxCellMarker.prototype.setEnabled=function(a){this.enabled=a};mxCellMarker.prototype.isEnabled=function(){return this.enabled};mxCellMarker.prototype.setHotspot=function(a){this.hotspot=a};mxCellMarker.prototype.getHotspot=function(){return this.hotspot}; -mxCellMarker.prototype.setHotspotEnabled=function(a){this.hotspotEnabled=a};mxCellMarker.prototype.isHotspotEnabled=function(){return this.hotspotEnabled};mxCellMarker.prototype.hasValidState=function(){return null!=this.validState};mxCellMarker.prototype.getValidState=function(){return this.validState};mxCellMarker.prototype.getMarkedState=function(){return this.markedState};mxCellMarker.prototype.reset=function(){this.validState=null;null!=this.markedState&&(this.markedState=null,this.unmark())}; -mxCellMarker.prototype.process=function(a){var b=null;this.isEnabled()&&(b=this.getState(a),this.setCurrentState(b,a));return b};mxCellMarker.prototype.setCurrentState=function(a,b,c){var d=null!=a?this.isValidState(a):!1;c=null!=c?c:this.getMarkerColor(b.getEvent(),a,d);this.validState=d?a:null;if(a!=this.markedState||c!=this.currentColor)this.currentColor=c,null!=a&&null!=this.currentColor?(this.markedState=a,this.mark()):null!=this.markedState&&(this.markedState=null,this.unmark())}; -mxCellMarker.prototype.markCell=function(a,b){var c=this.graph.getView().getState(a);null!=c&&(this.currentColor=null!=b?b:this.validColor,this.markedState=c,this.mark())};mxCellMarker.prototype.mark=function(){this.highlight.setHighlightColor(this.currentColor);this.highlight.highlight(this.markedState);this.fireEvent(new mxEventObject(mxEvent.MARK,"state",this.markedState))};mxCellMarker.prototype.unmark=function(){this.mark()};mxCellMarker.prototype.isValidState=function(a){return!0}; -mxCellMarker.prototype.getMarkerColor=function(a,b,c){return c?this.validColor:this.invalidColor};mxCellMarker.prototype.getState=function(a){var b=this.graph.getView(),c=this.getCell(a),b=this.getStateToMark(b.getState(c));return null!=b&&this.intersects(b,a)?b:null};mxCellMarker.prototype.getCell=function(a){return a.getCell()};mxCellMarker.prototype.getStateToMark=function(a){return a}; -mxCellMarker.prototype.intersects=function(a,b){return this.hotspotEnabled?mxUtils.intersectsHotspot(a,b.getGraphX(),b.getGraphY(),this.hotspot,mxConstants.MIN_HOTSPOT_SIZE,mxConstants.MAX_HOTSPOT_SIZE):!0};mxCellMarker.prototype.destroy=function(){this.graph.getView().removeListener(this.resetHandler);this.graph.getModel().removeListener(this.resetHandler);this.highlight.destroy()}; -function mxSelectionCellsHandler(a){mxEventSource.call(this);this.graph=a;this.handlers=new mxDictionary;this.graph.addMouseListener(this);this.refreshHandler=mxUtils.bind(this,function(a,c){this.isEnabled()&&this.refresh()});this.graph.getSelectionModel().addListener(mxEvent.CHANGE,this.refreshHandler);this.graph.getModel().addListener(mxEvent.CHANGE,this.refreshHandler);this.graph.getView().addListener(mxEvent.SCALE,this.refreshHandler);this.graph.getView().addListener(mxEvent.TRANSLATE,this.refreshHandler); -this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE,this.refreshHandler);this.graph.getView().addListener(mxEvent.DOWN,this.refreshHandler);this.graph.getView().addListener(mxEvent.UP,this.refreshHandler)}mxUtils.extend(mxSelectionCellsHandler,mxEventSource);mxSelectionCellsHandler.prototype.graph=null;mxSelectionCellsHandler.prototype.enabled=!0;mxSelectionCellsHandler.prototype.refreshHandler=null;mxSelectionCellsHandler.prototype.maxHandlers=100; -mxSelectionCellsHandler.prototype.handlers=null;mxSelectionCellsHandler.prototype.isEnabled=function(){return this.enabled};mxSelectionCellsHandler.prototype.setEnabled=function(a){this.enabled=a};mxSelectionCellsHandler.prototype.getHandler=function(a){return this.handlers.get(a)};mxSelectionCellsHandler.prototype.isHandled=function(a){return null!=this.getHandler(a)};mxSelectionCellsHandler.prototype.reset=function(){this.handlers.visit(function(a,b){b.reset.apply(b)})}; -mxSelectionCellsHandler.prototype.getHandledSelectionCells=function(){return this.graph.getSelectionCells()}; -mxSelectionCellsHandler.prototype.refresh=function(){var a=this.handlers;this.handlers=new mxDictionary;for(var b=mxUtils.sortCells(this.getHandledSelectionCells(),!1),c=0;cthis.graph.tolerance||Math.abs(b.getGraphY()-this.first.y)>this.graph.tolerance)&&this.updateCurrentState(b,c);if(null!=this.first){var f=null,d=c;null!=this.constraintHandler.currentConstraint&&null!=this.constraintHandler.currentFocus&&null!=this.constraintHandler.currentPoint?(f=this.constraintHandler.currentConstraint, -d=this.constraintHandler.currentPoint.clone()):null!=this.previous&&!this.graph.isIgnoreTerminalEvent(b.getEvent())&&mxEvent.isShiftDown(b.getEvent())&&(Math.abs(this.previous.getCenterX()-c.x)this.graph.tolerance||g>this.graph.tolerance)&&(this.shape=this.createShape(),null!=this.edgeState&&this.shape.apply(this.edgeState),this.updateCurrentState(b,c));null!=this.shape&&(null!=this.edgeState?this.shape.points=this.edgeState.absolutePoints:(c=[e],null!=this.waypoints&&(c=c.concat(this.waypoints)),c.push(d),this.shape.points=c),this.drawPreview()); -null!=this.cursor&&(this.graph.container.style.cursor=this.cursor);mxEvent.consume(b.getEvent());b.consume()}else this.isEnabled()&&this.graph.isEnabled()?this.previous!=this.currentState&&null==this.edgeState?(this.destroyIcons(),null!=this.currentState&&null==this.error&&null==this.constraintHandler.currentConstraint&&(this.icons=this.createIcons(this.currentState),null==this.icons&&(this.currentState.setCursor(mxConstants.CURSOR_CONNECT),b.consume())),this.previous=this.currentState):this.previous!= -this.currentState||null==this.currentState||null!=this.icons||this.graph.isMouseDown||b.consume():this.constraintHandler.reset();if(!this.graph.isMouseDown&&null!=this.currentState&&null!=this.icons){c=!1;d=b.getSource();for(e=0;ethis.graph.tolerance||b>this.graph.tolerance))null==this.waypoints&&(this.waypoints=[]),c=this.graph.view.scale,b=new mxPoint(this.graph.snap(a.getGraphX()/c)*c,this.graph.snap(a.getGraphY()/c)*c),this.waypoints.push(b)}; -mxConnectionHandler.prototype.checkConstraints=function(a,b){return null==a||null==b||null==a.point||null==b.point||!a.point.equals(b.point)||a.dx!=b.dx||a.dy!=b.dy||a.perimeter!=b.perimeter}; -mxConnectionHandler.prototype.mouseUp=function(a,b){if(!b.isConsumed()&&this.isConnecting()){if(this.waypointsEnabled&&!this.isStopEvent(b)){this.addWaypointForEvent(b);b.consume();return}var c=this.sourceConstraint,d=this.constraintHandler.currentConstraint,e=null!=this.previous?this.previous.cell:null,f=null;null!=this.constraintHandler.currentConstraint&&null!=this.constraintHandler.currentFocus&&(f=this.constraintHandler.currentFocus.cell);null==f&&null!=this.currentState&&(f=this.currentState.cell); -null!=this.error||null!=e&&null!=f&&e==f&&!this.checkConstraints(c,d)?(null!=this.previous&&null!=this.marker.validState&&this.previous.cell==this.marker.validState.cell&&this.graph.selectCellForEvent(this.marker.source,b.getEvent()),null!=this.error&&0g||Math.abs(f)>g)null==this.div&&(this.div=this.createShape()),mxUtils.clearSelection(),this.update(d,c),b.consume()}}; -mxRubberband.prototype.createShape=function(){null==this.sharedDiv&&(this.sharedDiv=document.createElement("div"),this.sharedDiv.className="mxRubberband",mxUtils.setOpacity(this.sharedDiv,this.defaultOpacity));this.graph.container.appendChild(this.sharedDiv);var a=this.sharedDiv;mxClient.IS_SVG&&(!mxClient.IS_IE||10<=document.documentMode)&&this.fadeOut&&(this.sharedDiv=null);return a};mxRubberband.prototype.isActive=function(a,b){return null!=this.div&&"none"!=this.div.style.display}; -mxRubberband.prototype.mouseUp=function(a,b){var c=this.isActive();this.reset();c&&(this.execute(b.getEvent()),b.consume())};mxRubberband.prototype.execute=function(a){var b=new mxRectangle(this.x,this.y,this.width,this.height);this.graph.selectRegion(b,a)}; -mxRubberband.prototype.reset=function(){if(null!=this.div)if(mxClient.IS_SVG&&(!mxClient.IS_IE||10<=document.documentMode)&&this.fadeOut){var a=this.div;mxUtils.setPrefixedStyle(a.style,"transition","all 0.2s linear");a.style.pointerEvents="none";a.style.opacity=0;window.setTimeout(function(){a.parentNode.removeChild(a)},200)}else this.div.parentNode.removeChild(this.div);mxEvent.removeGestureListeners(document,null,this.dragHandler,this.dropHandler);this.dropHandler=this.dragHandler=null;this.currentY= -this.currentX=0;this.div=this.first=null};mxRubberband.prototype.update=function(a,b){this.currentX=a;this.currentY=b;this.repaint()}; -mxRubberband.prototype.repaint=function(){if(null!=this.div){var a=this.currentX-this.graph.panDx,b=this.currentY-this.graph.panDy;this.x=Math.min(this.first.x,a);this.y=Math.min(this.first.y,b);this.width=Math.max(this.first.x,a)-this.x;this.height=Math.max(this.first.y,b)-this.y;a=mxClient.IS_VML?this.graph.panDy:0;this.div.style.left=this.x+(mxClient.IS_VML?this.graph.panDx:0)+"px";this.div.style.top=this.y+a+"px";this.div.style.width=Math.max(1,this.width)+"px";this.div.style.height=Math.max(1, -this.height)+"px"}};mxRubberband.prototype.destroy=function(){this.destroyed||(this.destroyed=!0,this.graph.removeMouseListener(this),this.graph.removeListener(this.forceRubberbandHandler),this.graph.removeListener(this.panHandler),this.reset(),null!=this.sharedDiv&&(this.sharedDiv=null))};function mxHandle(a,b,c,d){this.graph=a.view.graph;this.state=a;this.cursor=null!=b?b:this.cursor;this.image=null!=c?c:this.image;this.shape=null!=d?d:null;this.init()}mxHandle.prototype.cursor="default"; -mxHandle.prototype.image=null;mxHandle.prototype.ignoreGrid=!1;mxHandle.prototype.getPosition=function(a){};mxHandle.prototype.setPosition=function(a,b,c){};mxHandle.prototype.execute=function(a){};mxHandle.prototype.copyStyle=function(a){this.graph.setCellStyles(a,this.state.style[a],[this.state.cell])}; -mxHandle.prototype.processEvent=function(a){var b=this.graph.view.scale,c=this.graph.view.translate,c=new mxPoint(a.getGraphX()/b-c.x,a.getGraphY()/b-c.y);null!=this.shape&&null!=this.shape.bounds&&(c.x-=this.shape.bounds.width/b/4,c.y-=this.shape.bounds.height/b/4);var b=-mxUtils.toRadians(this.getRotation()),d=-mxUtils.toRadians(this.getTotalRotation())-b,c=this.flipPoint(this.rotatePoint(this.snapPoint(this.rotatePoint(c,b),this.ignoreGrid||!this.graph.isGridEnabledEvent(a.getEvent())),d));this.setPosition(this.state.getPaintBounds(), -c,a);this.redraw()};mxHandle.prototype.positionChanged=function(){null!=this.state.text&&this.state.text.apply(this.state);null!=this.state.shape&&this.state.shape.apply(this.state);this.graph.cellRenderer.redraw(this.state,!0)};mxHandle.prototype.getRotation=function(){return null!=this.state.shape?this.state.shape.getRotation():0};mxHandle.prototype.getTotalRotation=function(){return null!=this.state.shape?this.state.shape.getShapeRotation():0}; -mxHandle.prototype.init=function(){var a=this.isHtmlRequired();null!=this.image?(this.shape=new mxImageShape(new mxRectangle(0,0,this.image.width,this.image.height),this.image.src),this.shape.preserveImageAspect=!1):null==this.shape&&(this.shape=this.createShape(a));this.initShape(a)};mxHandle.prototype.createShape=function(a){a=new mxRectangle(0,0,mxConstants.HANDLE_SIZE,mxConstants.HANDLE_SIZE);return new mxRectangleShape(a,mxConstants.HANDLE_FILLCOLOR,mxConstants.HANDLE_STROKECOLOR)}; -mxHandle.prototype.initShape=function(a){a&&this.shape.isHtmlAllowed()?(this.shape.dialect=mxConstants.DIALECT_STRICTHTML,this.shape.init(this.graph.container)):(this.shape.dialect=this.graph.dialect!=mxConstants.DIALECT_SVG?mxConstants.DIALECT_MIXEDHTML:mxConstants.DIALECT_SVG,null!=this.cursor&&this.shape.init(this.graph.getView().getOverlayPane()));mxEvent.redirectMouseEvents(this.shape.node,this.graph,this.state);this.shape.node.style.cursor=this.cursor}; -mxHandle.prototype.redraw=function(){if(null!=this.shape&&null!=this.state.shape){var a=this.getPosition(this.state.getPaintBounds());if(null!=a){var b=mxUtils.toRadians(this.getTotalRotation()),a=this.rotatePoint(this.flipPoint(a),b),b=this.graph.view.scale,c=this.graph.view.translate;this.shape.bounds.x=Math.floor((a.x+c.x)*b-this.shape.bounds.width/2);this.shape.bounds.y=Math.floor((a.y+c.y)*b-this.shape.bounds.height/2);this.shape.redraw()}}}; -mxHandle.prototype.isHtmlRequired=function(){return null!=this.state.text&&this.state.text.node.parentNode==this.graph.container};mxHandle.prototype.rotatePoint=function(a,b){var c=this.state.getCellBounds(),c=new mxPoint(c.getCenterX(),c.getCenterY());return mxUtils.getRotatedPoint(a,Math.cos(b),Math.sin(b),c)}; -mxHandle.prototype.flipPoint=function(a){if(null!=this.state.shape){var b=this.state.getCellBounds();this.state.shape.flipH&&(a.x=2*b.x+b.width-a.x);this.state.shape.flipV&&(a.y=2*b.y+b.height-a.y)}return a};mxHandle.prototype.snapPoint=function(a,b){b||(a.x=this.graph.snap(a.x),a.y=this.graph.snap(a.y));return a};mxHandle.prototype.setVisible=function(a){null!=this.shape&&null!=this.shape.node&&(this.shape.node.style.display=a?"":"none")}; -mxHandle.prototype.reset=function(){this.setVisible(!0);this.state.style=this.graph.getCellStyle(this.state.cell);this.positionChanged()};mxHandle.prototype.destroy=function(){null!=this.shape&&(this.shape.destroy(),this.shape=null)}; -function mxVertexHandler(a){null!=a&&(this.state=a,this.init(),this.escapeHandler=mxUtils.bind(this,function(a,c){this.livePreview&&null!=this.index&&(this.state.view.graph.cellRenderer.redraw(this.state,!0),this.state.view.invalidate(this.state.cell),this.state.invalid=!1,this.state.view.validate());this.reset()}),this.state.view.graph.addListener(mxEvent.ESCAPE,this.escapeHandler))}mxVertexHandler.prototype.graph=null;mxVertexHandler.prototype.state=null;mxVertexHandler.prototype.singleSizer=!1; -mxVertexHandler.prototype.index=null;mxVertexHandler.prototype.allowHandleBoundsCheck=!0;mxVertexHandler.prototype.handleImage=null;mxVertexHandler.prototype.handlesVisible=!0;mxVertexHandler.prototype.tolerance=0;mxVertexHandler.prototype.rotationEnabled=!1;mxVertexHandler.prototype.parentHighlightEnabled=!1;mxVertexHandler.prototype.rotationRaster=!0;mxVertexHandler.prototype.rotationCursor="crosshair";mxVertexHandler.prototype.livePreview=!1;mxVertexHandler.prototype.movePreviewToFront=!1; -mxVertexHandler.prototype.manageSizers=!1;mxVertexHandler.prototype.constrainGroupByChildren=!1;mxVertexHandler.prototype.rotationHandleVSpacing=-16;mxVertexHandler.prototype.horizontalOffset=0;mxVertexHandler.prototype.verticalOffset=0; -mxVertexHandler.prototype.init=function(){this.graph=this.state.view.graph;this.selectionBounds=this.getSelectionBounds(this.state);this.bounds=new mxRectangle(this.selectionBounds.x,this.selectionBounds.y,this.selectionBounds.width,this.selectionBounds.height);this.selectionBorder=this.createSelectionShape(this.bounds);this.selectionBorder.dialect=this.graph.dialect!=mxConstants.DIALECT_SVG?mxConstants.DIALECT_VML:mxConstants.DIALECT_SVG;this.selectionBorder.pointerEvents=!1;this.selectionBorder.rotation= -Number(this.state.style[mxConstants.STYLE_ROTATION]||"0");this.selectionBorder.init(this.graph.getView().getOverlayPane());mxEvent.redirectMouseEvents(this.selectionBorder.node,this.graph,this.state);this.graph.isCellMovable(this.state.cell)&&this.selectionBorder.setCursor(mxConstants.CURSOR_MOVABLE_VERTEX);if(0>=mxGraphHandler.prototype.maxCells||this.graph.getSelectionCount()this.state.width&&2>this.state.height&&(this.labelShape=this.createSizer(mxConstants.CURSOR_MOVABLE_VERTEX,mxEvent.LABEL_HANDLE, -null,mxConstants.LABEL_HANDLE_FILLCOLOR),this.sizers.push(this.labelShape))}this.isRotationHandleVisible()&&(this.rotationShape=this.createSizer(this.rotationCursor,mxEvent.ROTATION_HANDLE,mxConstants.HANDLE_SIZE+3,mxConstants.HANDLE_FILLCOLOR),this.sizers.push(this.rotationShape));this.customHandles=this.createCustomHandles();this.redraw();this.constrainGroupByChildren&&this.updateMinBounds()}; -mxVertexHandler.prototype.isRotationHandleVisible=function(){return this.graph.isEnabled()&&this.rotationEnabled&&this.graph.isCellRotatable(this.state.cell)&&(0>=mxGraphHandler.prototype.maxCells||this.graph.getSelectionCount()this.graph.tolerance||Math.abs(a.getGraphY()-this.startY)>this.graph.tolerance)&&(this.inTolerance=!1)};mxVertexHandler.prototype.updateHint=function(a){};mxVertexHandler.prototype.removeHint=function(){}; -mxVertexHandler.prototype.roundAngle=function(a){return Math.round(10*a)/10};mxVertexHandler.prototype.roundLength=function(a){return Math.round(100*a)/100}; -mxVertexHandler.prototype.mouseMove=function(a,b){b.isConsumed()||null==this.index?this.graph.isMouseDown||null==this.getHandleForEvent(b)||b.consume(!1):(this.checkTolerance(b),this.inTolerance||(this.index<=mxEvent.CUSTOM_HANDLE?null!=this.customHandles&&(this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].processEvent(b),this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].active=!0,null!=this.ghostPreview?(this.ghostPreview.apply(this.state),this.ghostPreview.strokewidth=this.getSelectionStrokeWidth()/ -this.ghostPreview.scale/this.ghostPreview.scale,this.ghostPreview.isDashed=this.isSelectionDashed(),this.ghostPreview.stroke=this.getSelectionColor(),this.ghostPreview.redraw(),null!=this.selectionBounds&&(this.selectionBorder.node.style.display="none")):(this.movePreviewToFront&&this.moveToFront(),this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].positionChanged())):this.index==mxEvent.LABEL_HANDLE?this.moveLabel(b):(this.index==mxEvent.ROTATION_HANDLE?this.rotateVertex(b):this.resizeVertex(b), -this.updateHint(b))),b.consume())};mxVertexHandler.prototype.isGhostPreview=function(){return 0d?180:0;0a-this.startDist?15:25>a-this.startDist?5: -1,this.currentAlpha=Math.round(this.currentAlpha/raster)*raster):this.currentAlpha=this.roundAngle(this.currentAlpha);this.selectionBorder.rotation=this.currentAlpha;this.selectionBorder.redraw();this.livePreviewActive&&this.redrawHandles()}; -mxVertexHandler.prototype.resizeVertex=function(a){var b=new mxPoint(this.state.getCenterX(),this.state.getCenterY()),c=mxUtils.toRadians(this.state.style[mxConstants.STYLE_ROTATION]||"0"),d=new mxPoint(a.getGraphX(),a.getGraphY()),e=this.graph.view.translate,f=this.graph.view.scale,g=Math.cos(-c),k=Math.sin(-c),l=d.x-this.startX,m=d.y-this.startY,d=k*l+g*m,l=g*l-k*m,m=d,g=this.graph.getCellGeometry(this.state.cell);this.unscaledBounds=this.union(g,l/f,m/f,this.index,this.graph.isGridEnabledEvent(a.getEvent()), -1,new mxPoint(0,0),this.isConstrainedEvent(a),this.isCenteredEvent(this.state,a));g.relative||(k=this.graph.getMaximumGraphBounds(),null!=k&&null!=this.parentState&&(k=mxRectangle.fromRectangle(k),k.x-=(this.parentState.x-e.x*f)/f,k.y-=(this.parentState.y-e.y*f)/f),this.graph.isConstrainChild(this.state.cell)&&(d=this.graph.getCellContainmentArea(this.state.cell),null!=d&&(l=this.graph.getOverlap(this.state.cell),0k.x+k.width&&(this.unscaledBounds.width-=this.unscaledBounds.x+this.unscaledBounds.width-k.x-k.width),this.unscaledBounds.y+this.unscaledBounds.height> -k.y+k.height&&(this.unscaledBounds.height-=this.unscaledBounds.y+this.unscaledBounds.height-k.y-k.height)));d=this.bounds;this.bounds=new mxRectangle((null!=this.parentState?this.parentState.x:e.x*f)+this.unscaledBounds.x*f,(null!=this.parentState?this.parentState.y:e.y*f)+this.unscaledBounds.y*f,this.unscaledBounds.width*f,this.unscaledBounds.height*f);g.relative&&null!=this.parentState&&(this.bounds.x+=this.state.x-this.parentState.x,this.bounds.y+=this.state.y-this.parentState.y);g=Math.cos(c); -k=Math.sin(c);c=new mxPoint(this.bounds.getCenterX(),this.bounds.getCenterY());l=c.x-b.x;m=c.y-b.y;b=g*l-k*m-l;c=k*l+g*m-m;l=this.bounds.x-this.state.x;m=this.bounds.y-this.state.y;e=g*l-k*m;g=k*l+g*m;this.bounds.x+=b;this.bounds.y+=c;this.unscaledBounds.x=this.roundLength(this.unscaledBounds.x+b/f);this.unscaledBounds.y=this.roundLength(this.unscaledBounds.y+c/f);this.unscaledBounds.width=this.roundLength(this.unscaledBounds.width);this.unscaledBounds.height=this.roundLength(this.unscaledBounds.height); -this.graph.isCellCollapsed(this.state.cell)||0==b&&0==c?this.childOffsetY=this.childOffsetX=0:(this.childOffsetX=this.state.x-this.bounds.x+e,this.childOffsetY=this.state.y-this.bounds.y+g);d.equals(this.bounds)||(this.livePreviewActive&&this.updateLivePreview(a),null!=this.preview?this.drawPreview():this.updateParentHighlight())}; -mxVertexHandler.prototype.updateLivePreview=function(a){var b=this.graph.view.scale,c=this.graph.view.translate;a=this.state.clone();this.state.x=this.bounds.x;this.state.y=this.bounds.y;this.state.origin=new mxPoint(this.state.x/b-c.x,this.state.y/b-c.y);this.state.width=this.bounds.width;this.state.height=this.bounds.height;b=this.state.absoluteOffset;new mxPoint(b.x,b.y);this.state.absoluteOffset.x=0;this.state.absoluteOffset.y=0;b=this.graph.getCellGeometry(this.state.cell);null!=b&&(c=b.offset|| -this.EMPTY_POINT,null==c||b.relative||(this.state.absoluteOffset.x=this.state.view.scale*c.x,this.state.absoluteOffset.y=this.state.view.scale*c.y),this.state.view.updateVertexLabelOffset(this.state));this.state.view.graph.cellRenderer.redraw(this.state,!0);this.state.view.invalidate(this.state.cell);this.state.invalid=!1;this.state.view.validate();this.redrawHandles();this.movePreviewToFront&&this.moveToFront();null!=this.state.control&&null!=this.state.control.node&&(this.state.control.node.style.visibility= -"hidden");this.state.setState(a)}; -mxVertexHandler.prototype.moveToFront=function(){if(null!=this.state.text&&null!=this.state.text.node&&null!=this.state.text.node.nextSibling||null!=this.state.shape&&null!=this.state.shape.node&&null!=this.state.shape.node.nextSibling&&(null==this.state.text||this.state.shape.node.nextSibling!=this.state.text.node))null!=this.state.shape&&null!=this.state.shape.node&&this.state.shape.node.parentNode.appendChild(this.state.shape.node),null!=this.state.text&&null!=this.state.text.node&&this.state.text.node.parentNode.appendChild(this.state.text.node)}; -mxVertexHandler.prototype.mouseUp=function(a,b){if(null!=this.index&&null!=this.state){var c=new mxPoint(b.getGraphX(),b.getGraphY()),d=this.index;this.index=null;null==this.ghostPreview&&(this.state.view.invalidate(this.state.cell,!1,!1),this.state.view.validate());this.graph.getModel().beginUpdate();try{if(d<=mxEvent.CUSTOM_HANDLE){if(null!=this.customHandles){var e=this.state.view.graph.getCellStyle(this.state.cell);this.customHandles[mxEvent.CUSTOM_HANDLE-d].active=!1;this.customHandles[mxEvent.CUSTOM_HANDLE- -d].execute(b);null!=this.customHandles&&null!=this.customHandles[mxEvent.CUSTOM_HANDLE-d]&&(this.state.style=e,this.customHandles[mxEvent.CUSTOM_HANDLE-d].positionChanged())}}else if(d==mxEvent.ROTATION_HANDLE)if(null!=this.currentAlpha){var f=this.currentAlpha-(this.state.style[mxConstants.STYLE_ROTATION]||0);0!=f&&this.rotateCell(this.state.cell,f)}else this.rotateClick();else{var g=this.graph.isGridEnabledEvent(b.getEvent()),k=mxUtils.toRadians(this.state.style[mxConstants.STYLE_ROTATION]||"0"), -l=Math.cos(-k),m=Math.sin(-k),n=c.x-this.startX,p=c.y-this.startY,c=m*n+l*p,n=l*n-m*p,p=c,q=this.graph.view.scale,r=this.isRecursiveResize(this.state,b);this.resizeCell(this.state.cell,this.roundLength(n/q),this.roundLength(p/q),d,g,this.isConstrainedEvent(b),r)}}finally{this.graph.getModel().endUpdate()}b.consume();this.reset();this.redrawHandles()}};mxVertexHandler.prototype.isRecursiveResize=function(a,b){return this.graph.isRecursiveResize(this.state)};mxVertexHandler.prototype.rotateClick=function(){}; -mxVertexHandler.prototype.rotateCell=function(a,b,c){if(0!=b){var d=this.graph.getModel();if(d.isVertex(a)||d.isEdge(a)){if(!d.isEdge(a)){var e=(this.graph.getCurrentCellStyle(a)[mxConstants.STYLE_ROTATION]||0)+b;this.graph.setCellStyles(mxConstants.STYLE_ROTATION,e,[a])}e=this.graph.getCellGeometry(a);if(null!=e){var f=this.graph.getCellGeometry(c);null==f||d.isEdge(c)||(e=e.clone(),e.rotate(b,new mxPoint(f.width/2,f.height/2)),d.setGeometry(a,e));if(d.isVertex(a)&&!e.relative||d.isEdge(a))for(c= -d.getChildCount(a),e=0;ed&&(a+=c,a=e?this.graph.snap(a/f)*f:Math.round(a/f)*f);if(0==d|| -3==d||5==d)p+=b,p=e?this.graph.snap(p/f)*f:Math.round(p/f)*f;else if(2==d||4==d||7==d)q+=b,q=e?this.graph.snap(q/f)*f:Math.round(q/f)*f;e=q-p;c=r-a;k&&(k=this.graph.getCellGeometry(this.state.cell),null!=k&&(k=k.width/k.height,1==d||2==d||7==d||6==d?e=c*k:c=e/k,0==d&&(p=q-e,a=r-c)));l&&(e+=e-m,c+=c-n,p+=t-(p+e/2),a+=u-(a+c/2));0>e&&(p+=e,e=Math.abs(e));0>c&&(a+=c,c=Math.abs(c));d=new mxRectangle(p+g.x*f,a+g.y*f,e,c);null!=this.minBounds&&(d.width=Math.max(d.width,this.minBounds.x*f+this.minBounds.width* -f+Math.max(0,this.x0*f-d.x)),d.height=Math.max(d.height,this.minBounds.y*f+this.minBounds.height*f+Math.max(0,this.y0*f-d.y)));return d};mxVertexHandler.prototype.redraw=function(a){this.selectionBounds=this.getSelectionBounds(this.state);this.bounds=new mxRectangle(this.selectionBounds.x,this.selectionBounds.y,this.selectionBounds.width,this.selectionBounds.height);this.drawPreview();a||this.redrawHandles()}; -mxVertexHandler.prototype.getHandlePadding=function(){var a=new mxPoint(0,0),b=this.tolerance;null!=this.sizers&&0=mxGraphHandler.prototype.maxCells)this.bends=this.createBends(),this.isVirtualBendsEnabled()&&(this.virtualBends=this.createVirtualBends());this.label=new mxPoint(this.state.absoluteOffset.x,this.state.absoluteOffset.y);this.labelShape=this.createLabelHandleShape();this.initBend(this.labelShape);this.labelShape.setCursor(mxConstants.CURSOR_LABEL_HANDLE);this.customHandles=this.createCustomHandles();this.updateParentHighlight();this.redraw()};mxEdgeHandler.prototype.isParentHighlightVisible=mxVertexHandler.prototype.isParentHighlightVisible; -mxEdgeHandler.prototype.updateParentHighlight=mxVertexHandler.prototype.updateParentHighlight;mxEdgeHandler.prototype.createCustomHandles=function(){return null};mxEdgeHandler.prototype.isVirtualBendsEnabled=function(a){return this.virtualBendsEnabled&&(null==this.state.style[mxConstants.STYLE_EDGE]||this.state.style[mxConstants.STYLE_EDGE]==mxConstants.NONE||1==this.state.style[mxConstants.STYLE_NOEDGESTYLE])&&"arrow"!=mxUtils.getValue(this.state.style,mxConstants.STYLE_SHAPE,null)}; -mxEdgeHandler.prototype.isCellEnabled=function(a){return!0};mxEdgeHandler.prototype.isAddPointEvent=function(a){return mxEvent.isShiftDown(a)};mxEdgeHandler.prototype.isRemovePointEvent=function(a){return mxEvent.isShiftDown(a)};mxEdgeHandler.prototype.getSelectionPoints=function(a){return a.absolutePoints}; -mxEdgeHandler.prototype.createParentHighlightShape=function(a){a=new mxRectangleShape(mxRectangle.fromRectangle(a),null,this.getSelectionColor());a.strokewidth=this.getSelectionStrokeWidth();a.isDashed=this.isSelectionDashed();return a};mxEdgeHandler.prototype.createSelectionShape=function(a){a=new this.state.shape.constructor;a.outline=!0;a.apply(this.state);a.isDashed=this.isSelectionDashed();a.stroke=this.getSelectionColor();a.isShadow=!1;return a};mxEdgeHandler.prototype.getSelectionColor=function(){return mxConstants.EDGE_SELECTION_COLOR}; -mxEdgeHandler.prototype.getSelectionStrokeWidth=function(){return mxConstants.EDGE_SELECTION_STROKEWIDTH};mxEdgeHandler.prototype.isSelectionDashed=function(){return mxConstants.EDGE_SELECTION_DASHED};mxEdgeHandler.prototype.isConnectableCell=function(a){return!0};mxEdgeHandler.prototype.getCellAt=function(a,b){return this.outlineConnect?null:this.graph.getCellAt(a,b)}; -mxEdgeHandler.prototype.createMarker=function(){var a=new mxCellMarker(this.graph),b=this;a.getCell=function(a){var c=mxCellMarker.prototype.getCell.apply(this,arguments);c!=b.state.cell&&null!=c||null==b.currentPoint||(c=b.graph.getCellAt(b.currentPoint.x,b.currentPoint.y));if(null!=c&&!this.graph.isCellConnectable(c)){var e=this.graph.getModel().getParent(c);this.graph.getModel().isVertex(e)&&this.graph.isCellConnectable(e)&&(c=e)}e=b.graph.getModel();if(this.graph.isSwimlane(c)&&null!=b.currentPoint&& -this.graph.hitsSwimlaneContent(c,b.currentPoint.x,b.currentPoint.y)||!b.isConnectableCell(c)||c==b.state.cell||null!=c&&!b.graph.connectableEdges&&e.isEdge(c)||e.isAncestor(b.state.cell,c))c=null;this.graph.isCellConnectable(c)||(c=null);return c};a.isValidState=function(a){var c=b.graph.getModel(),c=b.graph.view.getTerminalPort(a,b.graph.view.getState(c.getTerminal(b.state.cell,!b.isSource)),!b.isSource),c=null!=c?c.cell:null;b.error=b.validateConnection(b.isSource?a.cell:c,b.isSource?c:a.cell); -return null==b.error};return a};mxEdgeHandler.prototype.validateConnection=function(a,b){return this.graph.getEdgeValidationError(this.state.cell,a,b)}; -mxEdgeHandler.prototype.createBends=function(){for(var a=this.state.cell,b=[],c=0;c -mxEvent.VIRTUAL_HANDLE&&null!=this.customHandles)for(c=0;cmxEvent.VIRTUAL_HANDLE&&(c[this.index-1]=d)}return null!=e?e:c}; -mxEdgeHandler.prototype.isOutlineConnectEvent=function(a){var b=mxUtils.getOffset(this.graph.container),c=a.getEvent(),d=mxEvent.getClientX(c),c=mxEvent.getClientY(c),e=document.documentElement,f=this.currentPoint.x-this.graph.container.scrollLeft+b.x-((window.pageXOffset||e.scrollLeft)-(e.clientLeft||0)),b=this.currentPoint.y-this.graph.container.scrollTop+b.y-((window.pageYOffset||e.scrollTop)-(e.clientTop||0));return this.outlineConnect&&!mxEvent.isShiftDown(a.getEvent())&&(a.isSource(this.marker.highlight.shape)|| -mxEvent.isAltDown(a.getEvent())&&null!=a.getState()||this.marker.highlight.isHighlightAt(d,c)||(f!=d||b!=c)&&null==a.getState()&&this.marker.highlight.isHighlightAt(f,b))}; -mxEdgeHandler.prototype.updatePreviewState=function(a,b,c,d,e){var f=this.isSource?c:this.state.getVisibleTerminalState(!0),g=this.isTarget?c:this.state.getVisibleTerminalState(!1),k=this.graph.getConnectionConstraint(a,f,!0),l=this.graph.getConnectionConstraint(a,g,!1),m=this.constraintHandler.currentConstraint;null==m&&e&&(null!=c?(d.isSource(this.marker.highlight.shape)&&(b=new mxPoint(d.getGraphX(),d.getGraphY())),m=this.graph.getOutlineConstraint(b,c,d),this.constraintHandler.setFocus(d,c,this.isSource), -this.constraintHandler.currentConstraint=m,this.constraintHandler.currentPoint=b):m=new mxConnectionConstraint);if(this.outlineConnect&&null!=this.marker.highlight&&null!=this.marker.highlight.shape){var n=this.graph.view.scale;null!=this.constraintHandler.currentConstraint&&null!=this.constraintHandler.currentFocus?(this.marker.highlight.shape.stroke=e?mxConstants.OUTLINE_HIGHLIGHT_COLOR:"transparent",this.marker.highlight.shape.strokewidth=mxConstants.OUTLINE_HIGHLIGHT_STROKEWIDTH/n/n,this.marker.highlight.repaint()): -this.marker.hasValidState()&&(this.marker.highlight.shape.stroke=this.graph.isCellConnectable(d.getCell())&&this.marker.getValidState()!=d.getState()?"transparent":mxConstants.DEFAULT_VALID_COLOR,this.marker.highlight.shape.strokewidth=mxConstants.HIGHLIGHT_STROKEWIDTH/n/n,this.marker.highlight.repaint())}this.isSource?k=m:this.isTarget&&(l=m);if(this.isSource||this.isTarget)null!=m&&null!=m.point?(a.style[this.isSource?mxConstants.STYLE_EXIT_X:mxConstants.STYLE_ENTRY_X]=m.point.x,a.style[this.isSource? -mxConstants.STYLE_EXIT_Y:mxConstants.STYLE_ENTRY_Y]=m.point.y):(delete a.style[this.isSource?mxConstants.STYLE_EXIT_X:mxConstants.STYLE_ENTRY_X],delete a.style[this.isSource?mxConstants.STYLE_EXIT_Y:mxConstants.STYLE_ENTRY_Y]);a.setVisibleTerminalState(f,!0);a.setVisibleTerminalState(g,!1);this.isSource&&null==f||a.view.updateFixedTerminalPoint(a,f,!0,k);this.isTarget&&null==g||a.view.updateFixedTerminalPoint(a,g,!1,l);(this.isSource||this.isTarget)&&null==c&&(a.setAbsoluteTerminalPoint(b,this.isSource), -null==this.marker.getMarkedState()&&(this.error=this.graph.allowDanglingEdges?null:""));a.view.updatePoints(a,this.points,f,g);a.view.updateFloatingTerminalPoints(a,f,g)}; -mxEdgeHandler.prototype.mouseMove=function(a,b){if(null!=this.index&&null!=this.marker){this.currentPoint=this.getPointForEvent(b);this.error=null;!this.graph.isIgnoreTerminalEvent(b.getEvent())&&mxEvent.isShiftDown(b.getEvent())&&null!=this.snapPoint&&(Math.abs(this.snapPoint.x-this.currentPoint.x)mxEvent.VIRTUAL_HANDLE)null!= -this.customHandles&&(this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].processEvent(b),this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].positionChanged(),null!=this.shape&&null!=this.shape.node&&(this.shape.node.style.display="none"));else if(this.isLabel)this.label.x=this.currentPoint.x,this.label.y=this.currentPoint.y;else{this.points=this.getPreviewPoints(this.currentPoint,b);var c=this.isSource||this.isTarget?this.getPreviewTerminalState(b):null;if(null!=this.constraintHandler.currentConstraint&& -null!=this.constraintHandler.currentFocus&&null!=this.constraintHandler.currentPoint)this.currentPoint=this.constraintHandler.currentPoint.clone();else if(this.outlineConnect){var d=this.isSource||this.isTarget?this.isOutlineConnectEvent(b):!1;d?c=this.marker.highlight.state:null!=c&&c!=b.getState()&&this.graph.isCellConnectable(b.getCell())&&null!=this.marker.highlight.shape&&(this.marker.highlight.shape.stroke="transparent",this.marker.highlight.repaint(),c=null)}null==c||this.isCellEnabled(c.cell)|| -(c=null,this.marker.reset());var e=this.clonePreviewState(this.currentPoint,null!=c?c.cell:null);this.updatePreviewState(e,this.currentPoint,c,b,d);this.setPreviewColor(null==this.error?this.marker.validColor:this.marker.invalidColor);this.abspoints=e.absolutePoints;this.active=!0;this.updateHint(b,this.currentPoint)}this.drawPreview();mxEvent.consume(b.getEvent());b.consume()}else mxClient.IS_IE&&null!=this.getHandleForEvent(b)&&b.consume(!1)}; -mxEdgeHandler.prototype.mouseUp=function(a,b){if(null!=this.index&&null!=this.marker){null!=this.shape&&null!=this.shape.node&&(this.shape.node.style.display="");var c=this.state.cell,d=this.index;this.index=null;if(b.getX()!=this.startX||b.getY()!=this.startY){var e=!this.graph.isIgnoreTerminalEvent(b.getEvent())&&this.graph.isCloneEvent(b.getEvent())&&this.cloneEnabled&&this.graph.isCellsCloneable();if(null!=this.error)0mxEvent.VIRTUAL_HANDLE){if(null!=this.customHandles){var f=this.graph.getModel();f.beginUpdate();try{this.customHandles[mxEvent.CUSTOM_HANDLE-d].execute(b),null!=this.shape&&null!=this.shape.node&&(this.shape.apply(this.state),this.shape.redraw())}finally{f.endUpdate()}}}else if(this.isLabel)this.moveLabel(this.state,this.label.x,this.label.y);else if(this.isSource||this.isTarget)if(d=null,null!=this.constraintHandler.currentConstraint&&null!=this.constraintHandler.currentFocus&&(d=this.constraintHandler.currentFocus.cell), -null==d&&this.marker.hasValidState()&&null!=this.marker.highlight&&null!=this.marker.highlight.shape&&"transparent"!=this.marker.highlight.shape.stroke&&"white"!=this.marker.highlight.shape.stroke&&(d=this.marker.validState.cell),null!=d){var f=this.graph.getModel(),g=f.getParent(c);f.beginUpdate();try{if(e){var k=f.getGeometry(c),e=this.graph.cloneCell(c);f.add(g,e,f.getChildCount(g));null!=k&&(k=k.clone(),f.setGeometry(e,k));var l=f.getTerminal(c,!this.isSource);this.graph.connectCell(e,l,!this.isSource); -c=e}c=this.connect(c,d,this.isSource,e,b)}finally{f.endUpdate()}}else this.graph.isAllowDanglingEdges()&&(f=this.abspoints[this.isSource?0:this.abspoints.length-1],f.x=this.roundLength(f.x/this.graph.view.scale-this.graph.view.translate.x),f.y=this.roundLength(f.y/this.graph.view.scale-this.graph.view.translate.y),k=this.graph.getView().getState(this.graph.getModel().getParent(c)),null!=k&&(f.x-=k.origin.x,f.y-=k.origin.y),f.x-=this.graph.panDx/this.graph.view.scale,f.y-=this.graph.panDy/this.graph.view.scale, -c=this.changeTerminalPoint(c,f,this.isSource,e));else this.active?c=this.changePoints(c,this.points,e):(this.graph.getView().invalidate(this.state.cell),this.graph.getView().validate(this.state.cell))}else this.graph.isToggleEvent(b.getEvent())&&this.graph.selectCellForEvent(this.state.cell,b.getEvent());null!=this.marker&&(this.reset(),c!=this.state.cell&&this.graph.setSelectionCell(c));b.consume()}}; -mxEdgeHandler.prototype.reset=function(){this.active&&this.refresh();this.snapPoint=this.points=this.label=this.index=this.error=null;this.active=this.isTarget=this.isSource=this.isLabel=!1;if(this.livePreview&&null!=this.sizers)for(var a=0;a");this.div.style.visibility="";mxUtils.fit(this.div)}}; -mxTooltipHandler.prototype.destroy=function(){this.destroyed||(this.graph.removeMouseListener(this),mxEvent.release(this.div),null!=this.div&&null!=this.div.parentNode&&this.div.parentNode.removeChild(this.div),this.destroyed=!0,this.div=null)};function mxCellTracker(a,b,c){mxCellMarker.call(this,a,b);this.graph.addMouseListener(this);null!=c&&(this.getCell=c);mxClient.IS_IE&&mxEvent.addListener(window,"unload",mxUtils.bind(this,function(){this.destroy()}))}mxUtils.extend(mxCellTracker,mxCellMarker); -mxCellTracker.prototype.mouseDown=function(a,b){};mxCellTracker.prototype.mouseMove=function(a,b){this.isEnabled()&&this.process(b)};mxCellTracker.prototype.mouseUp=function(a,b){};mxCellTracker.prototype.destroy=function(){this.destroyed||(this.destroyed=!0,this.graph.removeMouseListener(this),mxCellMarker.prototype.destroy.apply(this))}; -function mxCellHighlight(a,b,c,d){null!=a&&(this.graph=a,this.highlightColor=null!=b?b:mxConstants.DEFAULT_VALID_COLOR,this.strokeWidth=null!=c?c:mxConstants.HIGHLIGHT_STROKEWIDTH,this.dashed=null!=d?d:!1,this.opacity=mxConstants.HIGHLIGHT_OPACITY,this.repaintHandler=mxUtils.bind(this,function(){if(null!=this.state){var a=this.graph.view.getState(this.state.cell);null==a?this.hide():(this.state=a,this.repaint())}}),this.graph.getView().addListener(mxEvent.SCALE,this.repaintHandler),this.graph.getView().addListener(mxEvent.TRANSLATE, -this.repaintHandler),this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE,this.repaintHandler),this.graph.getModel().addListener(mxEvent.CHANGE,this.repaintHandler),this.resetHandler=mxUtils.bind(this,function(){this.hide()}),this.graph.getView().addListener(mxEvent.DOWN,this.resetHandler),this.graph.getView().addListener(mxEvent.UP,this.resetHandler))}mxCellHighlight.prototype.keepOnTop=!1;mxCellHighlight.prototype.graph=null;mxCellHighlight.prototype.state=null; -mxCellHighlight.prototype.spacing=2;mxCellHighlight.prototype.resetHandler=null;mxCellHighlight.prototype.setHighlightColor=function(a){this.highlightColor=a;null!=this.shape&&(this.shape.stroke=a)};mxCellHighlight.prototype.drawHighlight=function(){this.shape=this.createShape();this.repaint();this.keepOnTop||this.shape.node.parentNode.firstChild==this.shape.node||this.shape.node.parentNode.insertBefore(this.shape.node,this.shape.node.parentNode.firstChild)}; -mxCellHighlight.prototype.createShape=function(){var a=this.graph.cellRenderer.createShape(this.state);a.svgStrokeTolerance=this.graph.tolerance;a.points=this.state.absolutePoints;a.apply(this.state);a.stroke=this.highlightColor;a.opacity=this.opacity;a.isDashed=this.dashed;a.isShadow=!1;a.dialect=this.graph.dialect!=mxConstants.DIALECT_SVG?mxConstants.DIALECT_VML:mxConstants.DIALECT_SVG;a.init(this.graph.getView().getOverlayPane());mxEvent.redirectMouseEvents(a.node,this.graph,this.state);this.graph.dialect!= -mxConstants.DIALECT_SVG?a.pointerEvents=!1:a.svgPointerEvents="stroke";return a};mxCellHighlight.prototype.getStrokeWidth=function(a){return this.strokeWidth}; -mxCellHighlight.prototype.repaint=function(){if(null!=this.state&&null!=this.shape){this.shape.scale=this.state.view.scale;this.graph.model.isEdge(this.state.cell)?(this.shape.strokewidth=this.getStrokeWidth(),this.shape.points=this.state.absolutePoints,this.shape.outline=!1):(this.shape.bounds=new mxRectangle(this.state.x-this.spacing,this.state.y-this.spacing,this.state.width+2*this.spacing,this.state.height+2*this.spacing),this.shape.rotation=Number(this.state.style[mxConstants.STYLE_ROTATION]|| -"0"),this.shape.strokewidth=this.getStrokeWidth()/this.state.view.scale,this.shape.outline=!0);null!=this.state.shape&&this.shape.setCursor(this.state.shape.getCursor());if(mxClient.IS_QUIRKS||8==document.documentMode)"transparent"==this.shape.stroke?(this.shape.stroke="white",this.shape.opacity=1):this.shape.opacity=this.opacity;this.shape.redraw()}};mxCellHighlight.prototype.hide=function(){this.highlight(null)}; -mxCellHighlight.prototype.highlight=function(a){this.state!=a&&(null!=this.shape&&(this.shape.destroy(),this.shape=null),this.state=a,null!=this.state&&this.drawHighlight())};mxCellHighlight.prototype.isHighlightAt=function(a,b){var c=!1;if(null!=this.shape&&null!=document.elementFromPoint&&!mxClient.IS_QUIRKS)for(var d=document.elementFromPoint(a,b);null!=d;){if(d==this.shape.node){c=!0;break}d=d.parentNode}return c}; -mxCellHighlight.prototype.destroy=function(){this.graph.getView().removeListener(this.resetHandler);this.graph.getView().removeListener(this.repaintHandler);this.graph.getModel().removeListener(this.repaintHandler);null!=this.shape&&(this.shape.destroy(),this.shape=null)}; -var mxCodecRegistry={codecs:[],aliases:[],register:function(a){if(null!=a){var b=a.getName();mxCodecRegistry.codecs[b]=a;var c=mxUtils.getFunctionName(a.template.constructor);c!=b&&mxCodecRegistry.addAlias(c,b)}return a},addAlias:function(a,b){mxCodecRegistry.aliases[a]=b},getCodec:function(a){var b=null;if(null!=a){var b=mxUtils.getFunctionName(a),c=mxCodecRegistry.aliases[b];null!=c&&(b=c);b=mxCodecRegistry.codecs[b];if(null==b)try{b=new mxObjectCodec(new a),mxCodecRegistry.register(b)}catch(d){}}return b}}; -function mxCodec(a){this.document=a||mxUtils.createXmlDocument();this.objects=[]}mxCodec.prototype.document=null;mxCodec.prototype.objects=null;mxCodec.prototype.elements=null;mxCodec.prototype.encodeDefaults=!1;mxCodec.prototype.putObject=function(a,b){return this.objects[a]=b};mxCodec.prototype.getObject=function(a){var b=null;null!=a&&(b=this.objects[a],null==b&&(b=this.lookup(a),null==b&&(a=this.getElementById(a),null!=a&&(b=this.decode(a)))));return b};mxCodec.prototype.lookup=function(a){return null}; -mxCodec.prototype.getElementById=function(a){this.updateElements();return this.elements[a]};mxCodec.prototype.updateElements=function(){null==this.elements&&(this.elements={},null!=this.document.documentElement&&this.addElement(this.document.documentElement))}; -mxCodec.prototype.addElement=function(a){if(a.nodeType==mxConstants.NODETYPE_ELEMENT){var b=a.getAttribute("id");if(null!=b)if(null==this.elements[b])this.elements[b]=a;else if(this.elements[b]!=a)throw Error(b+": Duplicate ID");}for(a=a.firstChild;null!=a;)this.addElement(a),a=a.nextSibling};mxCodec.prototype.getId=function(a){var b=null;null!=a&&(b=this.reference(a),null==b&&a instanceof mxCell&&(b=a.getId(),null==b&&(b=mxCellPath.create(a),0==b.length&&(b="root"))));return b}; -mxCodec.prototype.reference=function(a){return null};mxCodec.prototype.encode=function(a){var b=null;if(null!=a&&null!=a.constructor){var c=mxCodecRegistry.getCodec(a.constructor);null!=c?b=c.encode(this,a):mxUtils.isNode(a)?b=mxUtils.importNode(this.document,a,!0):mxLog.warn("mxCodec.encode: No codec for "+mxUtils.getFunctionName(a.constructor))}return b}; -mxCodec.prototype.decode=function(a,b){this.updateElements();var c=null;if(null!=a&&a.nodeType==mxConstants.NODETYPE_ELEMENT){c=null;try{c=window[a.nodeName]}catch(d){}c=mxCodecRegistry.getCodec(c);null!=c?c=c.decode(this,a,b):(c=a.cloneNode(!0),c.removeAttribute("as"))}return c};mxCodec.prototype.encodeCell=function(a,b,c){b.appendChild(this.encode(a));if(null==c||c){c=a.getChildCount();for(var d=0;d - - - - - diff --git a/src/main/webapp/app.html b/src/main/webapp/app.html deleted file mode 100644 index 32753a90..00000000 --- a/src/main/webapp/app.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/main/webapp/cache.manifest b/src/main/webapp/cache.manifest deleted file mode 100644 index 0271e829..00000000 --- a/src/main/webapp/cache.manifest +++ /dev/null @@ -1,64 +0,0 @@ -CACHE MANIFEST - -# THIS FILE WAS GENERATED. DO NOT MODIFY! -# 02/17/2020 01:02 pm - -app.html -index.html?offline=1 -index.html?offline=1&ui=min -index.html?offline=1&https=0 -offline.html -open.html -js/app.min.js -js/shapes.min.js -js/stencils.min.js -js/extensions.min.js -js/diagramly/ElectronApp.js -styles/grapheditor.css -styles/atlas.css -styles/dark.css -favicon.ico -mxgraph/css/common.css -mxgraph/images/maximize.gif -mxgraph/images/minimize.gif -mxgraph/images/close.gif -mxgraph/images/resize.gif -mxgraph/images/separator.gif -mxgraph/images/window.gif -mxgraph/images/window-title.gif -mxgraph/images/button.gif -mxgraph/images/point.gif -resources/dia.txt -images/delete.png -images/droptarget.png -images/help.png -images/download.png -images/drawlogo.svg -images/drawlogo-gray.svg -images/drawlogo-text-bottom.svg -images/logo-flat.png -images/osa_drive-harddisk.png -images/osa_database.png -images/glyphicons_star.png -images/logo-confluence.png -images/logo-jira.png -images/clear.gif -images/spin.gif -images/checkmark.gif -images/favicon-16x16.png -images/favicon-32x32.png -images/android-chrome-192x192.png -images/android-chrome-512x512.png -images/glyphicons_google.png -images/glyphicons_facebook.png -images/glyphicons_twitter.png -images/glyphicons_github.png -images/hs.png - -# Redirect app to app.html which redirects to index.html?offline=1 -# this is required to get the URL parameters into the index page. -FALLBACK: -app app.html - -NETWORK: -* diff --git a/src/main/webapp/connect/att_common/att-editor.js b/src/main/webapp/connect/att_common/att-editor.js deleted file mode 100644 index fc411668..00000000 --- a/src/main/webapp/connect/att_common/att-editor.js +++ /dev/null @@ -1,570 +0,0 @@ -function AttViewerEditor(onSubmit, getFileInfoFn, idSuffix, notStandalone, drawioOnly, genImage) -{ - idSuffix = idSuffix || ''; - var isDrawio = false; - - var opts = - { - lines: 12, // The number of lines to draw - length: 8, // The length of each line - width: 3, // The line thickness - radius: 5, // The radius of the inner circle - rotate: 0, // The rotation offset - color: '#000', // #rgb or #rrggbb - speed: 1, // Rounds per second - trail: 60, // Afterglow percentage - shadow: false, // Whether to render a shadow - hwaccel: false, // Whether to use hardware acceleration - className: 'spinner', // The CSS class to assign to the spinner - zIndex: 2e9 // The z-index (defaults to 2000000000) - }; - - var spinner = new Spinner(opts); - this.spinner = spinner; - spinner.spin(AC.$('#spinner-container' + idSuffix)); - - var head = document.getElementsByTagName('head')[0]; - - // Handles timeouts - var acceptResponse = true; - - var timeoutHandler = function() - { - acceptResponse = false; - spinner.stop(); - alert('The connection has timed out'); - }; - - var timeoutThread = window.setTimeout(timeoutHandler, 25000); - - var selectedFile = null, selFileContent = null, editedFile = null; - var curViewer = null; - - function showError(elem, errMsg) - { - elem.innerHTML = ' ' + - AC.htmlEntities(errMsg); - }; - - function prevDrawioFile(doc, prevDiv, filename, aspect) - { - spinner.stop(); - - var container = document.createElement('div'); - // NOTE: Height must be specified with default value "auto" to force automatic fit in viewer - container.style.cssText = 'position:absolute;width:auto;left:0px;right:0px;height:auto;bottom:0px;top:0px;border:1px solid transparent;'; - prevDiv.appendChild(container); - - var pageId, layerIds; - - if (aspect != null) - { - var aspectArray = aspect.split(' '); - - if (aspectArray.length > 1) - { - pageId = aspectArray[0]; - layerIds = aspectArray.slice(1); - } - } - - Graph.prototype.shadowId = 'attachmentDropShadow'; - var viewer = new GraphViewer(container, doc.documentElement, - {highlight: '#3572b0', border: 8, 'auto-fit': true, - resize: false, nav: true, lightbox: false, title: filename, - 'toolbar-nohide': true, 'toolbar-position': 'top', toolbar: 'pages layers', - pageId: pageId, layerIds: layerIds}); - - viewer.graph.addListener('size', function() - { - var root = this.view.getDrawPane().ownerSVGElement; - - if (root != null) - { - root.style.minHeight = ''; - } - }); - - curViewer = viewer; - - if (typeof AP != 'undefined') - { - AP.dialog.getButton('submit').enable(); - var altSubmitBtn = AP.dialog.getButton('altSubmitBtn'); - - if (altSubmitBtn) altSubmitBtn.enable(); - } - }; - - function prevImageFile(url, prevDiv, success, error) - { - var img = new Image(); - - img.onload = function() - { - var s = Math.min(prevDiv.offsetWidth / img.width, prevDiv.offsetHeight / img.height); - - if (s < 1) - { - img.width = s * img.width; - img.height = s * img.height; - } - - img.style.verticalAlign = 'middle'; - prevDiv.style.lineHeight = prevDiv.offsetHeight + 'px'; - prevDiv.appendChild(img); - - if (typeof AP != 'undefined') - { - AP.dialog.getButton('submit').enable(); - var altSubmitBtn = AP.dialog.getButton('altSubmitBtn'); - - if (altSubmitBtn) altSubmitBtn.enable(); - } - - spinner.stop(); - - if (success) - { - success(img); - } - }; - - img.onerror = function() - { - if (error) - { - error(); - } - - spinner.stop(); - }; - - img.src = url; - curViewer = null; - }; - - function genericOnSubmit() - { - var hasError = false; - //this cannot happen as the submit button is disabled until a file is selected - if (editedFile == null && selectedFile == null) - { - AC.$('#filenameError' + idSuffix).innerHTML = 'Please select a file'; - hasError = true; - } - - var width = parseInt(AC.$('#width' + idSuffix).value); - var height = parseInt(AC.$('#height' + idSuffix).value); - var autoSize = AC.$('#autoSize' + idSuffix).checked; - - if (!autoSize && (isNaN(width) || width <= 0)) - { - AC.$('#widthError' + idSuffix).innerHTML = 'Width must be greater than zero'; - hasError = true; - } - - if (!autoSize && (isNaN(height) || height <= 0)) - { - AC.$('#heightError' + idSuffix).innerHTML = 'Height must be greater than zero'; - hasError = true; - } - - if (hasError) - { - return; - } - - var aspect = null; - - if (curViewer != null) - { - var layerIds = []; - - var model = curViewer.graph.getModel(); - var childCount = model.getChildCount(model.root); - - // Get visible layers - for (var i = 0; i < childCount; i++) - { - var layer = model.getChildAt(model.root, i); - - if (model.isVisible(layer)) - { - layerIds.push(layer.id); - } - } - - aspect = curViewer.diagrams[curViewer.currentPage].getAttribute('id') + ' ' + layerIds.join(' '); - - if (autoSize) - { - var bounds = curViewer.graph.view.graphBounds; - width = Math.round(bounds.width) || null; - height = Math.round(bounds.height) || null; - } - } - - if (typeof AP != 'undefined') - { - AP.dialog.getButton('submit').disable(); - var altSubmitBtn = AP.dialog.getButton('altSubmitBtn'); - - if (altSubmitBtn) altSubmitBtn.disable(); - } - - spinner.spin(AC.$('#preview' + idSuffix)); - - - var image = null; - - function finalize() - { - onSubmit(selectedFile, selFileContent, editedFile, width, height, autoSize, isDrawio, aspect, function() - { - if (typeof AP != 'undefined') - { - AP.dialog.getButton('submit').enable(); - var altSubmitBtn = AP.dialog.getButton('altSubmitBtn'); - - if (altSubmitBtn) altSubmitBtn.enable(); - } - - showError(AC.$('#errorMsg' + idSuffix), 'Uploading file failed'); - spinner.stop(); - }, image); - }; - - if (genImage && curViewer.editor.isExportToCanvas()) - { - curViewer.editor.exportToCanvas(function(canvas) - { - var data = canvas.toDataURL('image/png'); - image = data.substring(data.lastIndexOf(',') + 1); - finalize(); - } - , null, null, null, finalize); - } - else - { - finalize() - } - } - - this.doSubmit = genericOnSubmit; - - function main() - { - window.clearTimeout(timeoutThread); - spinner.stop(); - - AC.$('#filePicker' + idSuffix).addEventListener('click', function(evt) - { - AC.$('#fileupload' + idSuffix).click(); - evt.preventDefault(); - }); - - AC.$('#fileupload' + idSuffix).addEventListener('change', function(evt) - { - if (this.files != null) - { - var file = this.files[0]; - - if (this.files.length == 1 && file != null) - { - AC.$('#filenameError' + idSuffix).innerHTML = ''; - AC.$('#filename' + idSuffix).value = file.name; - - var prevDiv = AC.$('#preview' + idSuffix); - prevDiv.innerHTML = ''; - spinner.spin(prevDiv); - - if (typeof convertVSDXtoMX != 'undefined' && /\.v(dx|sdx?)$/i.test(file.name)) - { - convertVSDXtoMX(file, file.name, function(xml) - { - selFileContent = xml; - isDrawio = true; - prevDrawioFile(mxUtils.parseXml(xml), prevDiv, file.name); - }, function() - { - showError(prevDiv, 'Unsupported vsdx file'); - }); - } - else - { - var reader = new FileReader(); - - reader.onload = function(e) - { - var data = e.target.result; - var potentialDraw = true; - var isImage = false; - isDrawio = false; - - if (file.type == 'image/svg+xml' && data.substring(0, 26) == 'data:image/svg+xml;base64,') - { - var base64 = data.substring(data.indexOf(',') + 1); - - // Workaround for invalid character error in Safari - data = (window.atob && !mxClient.IS_SF) ? atob(base64) : Base64.decode(base64, true); - } - else if (!drawioOnly && file.type.indexOf('image') == 0) - { - isImage = true; - var pngData = null; - - if (file.type == 'image/png') - { - pngData = AC.extractGraphModelFromPng(data); - } - - if (pngData == null) - { - potentialDraw = false; - } - else - { - data = pngData; - } - } - - selFileContent = data; - - if (potentialDraw) - { - try - { - var doc = mxUtils.parseXml(data); - - if (new Editor().extractGraphModel(doc.documentElement) != null) - { - isDrawio = true; - isImage = false - prevDrawioFile(doc, prevDiv, file.name); - } - } - catch(e) {} - } - - if (isImage) - { - prevImageFile(data, prevDiv, null, function() - { - showError(prevDiv, 'Unsupported image file'); - selectedFile = null; - }); - } - else if (!isDrawio) - { - showError(prevDiv, 'Unsupported file format'); - selectedFile = null; - spinner.stop(); - } - } - - if (file.type.indexOf('image') == 0) - { - reader.readAsDataURL(file); - } - else - { - reader.readAsText(file); - } - } - - selectedFile = file; - editedFile = null; - } - else - { - AC.$('#filenameError' + idSuffix).innerHTML = 'Please select a single file only'; - } - } - - // Resets input to force change event for same file (type reset required for IE) - this.type = ''; - this.type = 'file'; - this.value = ''; - evt.preventDefault(); - }); - - function removeErrMsg() - { - AC.$('#' + this.id + 'Error' + idSuffix).innerHTML = ''; - }; - - AC.$('#width' + idSuffix).addEventListener('change', removeErrMsg); - AC.$('#height' + idSuffix).addEventListener('change', removeErrMsg); - - if (getFileInfoFn) - { - var prevDiv = AC.$('#preview' + idSuffix); - prevDiv.innerHTML = ''; - spinner.spin(prevDiv); - - getFileInfoFn(function(fileInfo, fileContent) - { - var altSubmitBtn = AP.dialog.createButton({ - text: fileInfo? 'Save' : 'Insert', - identifier: 'altSubmitBtn' - }); - altSubmitBtn.bind(genericOnSubmit); - altSubmitBtn.disable(); - var autoSize = true; - - if (fileInfo && fileInfo.attId) - { - autoSize = fileInfo.autoSize == '1'; - AC.$('#width' + idSuffix).value = fileInfo.width; - AC.$('#height' + idSuffix).value = fileInfo.height; - AC.$('#filename' + idSuffix).value = fileInfo.filename; - - editedFile = fileInfo; - - if (fileInfo.isDrawio == '1') - { - if (fileInfo.mimeType == 'image/png') - { - fileContent = AC.extractGraphModelFromPng(fileContent); - } - - var doc = mxUtils.parseXml(fileContent); - - try - { - prevDrawioFile(doc, prevDiv, fileInfo.filename, fileInfo.aspect); - } - catch(e) - { - showError(prevDiv, 'Attachment file "' + fileInfo.filename + '" is corrupted'); - } - } - else - { - prevImageFile(fileContent, prevDiv, null, function() - { - showError(prevDiv, 'Attachment file "' + fileInfo.filename + '" is corrupted'); - }); - } - } - else - { - spinner.stop(); - } - - AC.$('#autoSize' + idSuffix).checked = autoSize; - autoSizeChanged(autoSize); - }, function(fileInfo) - { - if (fileInfo != null && fileInfo.filename == null) - { - prevDiv.innerHTML = 'Choose a file...' - - prevDiv.getElementsByTagName('a')[0].addEventListener('click', function(evt) - { - document.getElementById('filePicker').click(); - evt.preventDefault(); - }); - } - else - { - showError(prevDiv, fileInfo? 'Failed to load attachment file "' + fileInfo.filename + '"' : 'Unexpected Error'); - } - }); - } - }; - - //This function expects having the downloadUrl in the fileInfo - this.loadDrawioFile = function(fileInfo) - { - editedFile = fileInfo; - AC.$('#filename' + idSuffix).value = fileInfo.diagramDisplayName; - AC.$('#autoSize' + idSuffix).checked = true; - var prevDiv = AC.$('#preview' + idSuffix); - prevDiv.innerHTML = ''; - spinner.spin(prevDiv); - - var req = new XMLHttpRequest(); - req.open('GET', fileInfo.downloadUrl); - - req.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - selFileContent = req.responseText; - var doc = mxUtils.parseXml(selFileContent); - - try - { - prevDrawioFile(doc, prevDiv, fileInfo.diagramDisplayName, fileInfo.aspect); - } - catch(e) - { - showError(prevDiv, 'Attachment file "' + fileInfo.diagramName + '" is corrupted'); - } - } - else - { - showError(prevDiv, 'Cannot read attachment file "' + fileInfo.diagramName + '".'); - } - } - }; - - req.send(); - }; - - function autoSizeChanged(isChecked) - { - if(isChecked) - { - AC.$('#width' + idSuffix).setAttribute('disabled', 'disabled'); - AC.$('#height' + idSuffix).setAttribute('disabled', 'disabled'); - } - else - { - AC.$('#width' + idSuffix).removeAttribute('disabled'); - AC.$('#height' + idSuffix).removeAttribute('disabled'); - } - }; - - AC.$('#autoSize' + idSuffix).addEventListener('change', function(evt) - { - autoSizeChanged(this.checked); - }); - - function loadAtlassianApi() - { - var script = document.createElement('script'); - - script.onload = function() - { - AP.dialog.disableCloseOnSubmit(); - - //TODO when conf bug of submit is fixed, re-enable this and remove the button above - AP.dialog.getButton('submit').hide(); - - AP.events.on('dialog.submit', genericOnSubmit); - AP.dialog.getButton('submit').disable(); - main(); - }; - - script.src = 'https://connect-cdn.atl-paas.net/all.js'; - script.setAttribute('data-options', 'resize:false;margin:false'); - head.appendChild(script); - }; - - // Loads APIs - if (!notStandalone) - { - loadAtlassianApi(); - } - else - { - main(); - } -}; - diff --git a/src/main/webapp/connect/bitbucket/connect-dev.json b/src/main/webapp/connect/bitbucket/connect-dev.json deleted file mode 100644 index b339020c..00000000 --- a/src/main/webapp/connect/bitbucket/connect-dev.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "key": "com.mxgraph.bitbucket.plugins.diagramly", - "name": "Draw.io Viewer", - "description": "Viewer for files created with draw.io", - "baseUrl": "https://8d3077df.ngrok.io", - "modules": { - "fileViews": [ - { - "key": "diagram", - "name": { - "value": "Diagram" - }, - "url": "/viewer.html?repo={repo_uuid}&cset={file_cset}&path={file_path}&name={file_name}", - "file_matches": { - "extensions": ["xml"] - } - } - ], - "oauthConsumer": { - "clientId": "Ss8dQHwm4RaeMqCaak" - } - }, - "scopes": [ - "repository" - ], - "contexts": [ - "personal" - ] -} \ No newline at end of file diff --git a/src/main/webapp/connect/bitbucket/viewer.html b/src/main/webapp/connect/bitbucket/viewer.html deleted file mode 100644 index ff4b227e..00000000 --- a/src/main/webapp/connect/bitbucket/viewer.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - -Draw.io Viewer - - - - - - - - - diff --git a/src/main/webapp/connect/common/images/reader/checkmark.gif b/src/main/webapp/connect/common/images/reader/checkmark.gif deleted file mode 100644 index 3a40c089..00000000 Binary files a/src/main/webapp/connect/common/images/reader/checkmark.gif and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/closeLargeView.gif b/src/main/webapp/connect/common/images/reader/closeLargeView.gif deleted file mode 100644 index 877e1281..00000000 Binary files a/src/main/webapp/connect/common/images/reader/closeLargeView.gif and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/edit.png b/src/main/webapp/connect/common/images/reader/edit.png deleted file mode 100644 index 84adb14a..00000000 Binary files a/src/main/webapp/connect/common/images/reader/edit.png and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/grid.gif b/src/main/webapp/connect/common/images/reader/grid.gif deleted file mode 100644 index f4e7063e..00000000 Binary files a/src/main/webapp/connect/common/images/reader/grid.gif and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/largeView.png b/src/main/webapp/connect/common/images/reader/largeView.png deleted file mode 100644 index 12ffe387..00000000 Binary files a/src/main/webapp/connect/common/images/reader/largeView.png and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/remove.png b/src/main/webapp/connect/common/images/reader/remove.png deleted file mode 100644 index 0fda0040..00000000 Binary files a/src/main/webapp/connect/common/images/reader/remove.png and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/zoomActual.png b/src/main/webapp/connect/common/images/reader/zoomActual.png deleted file mode 100644 index 7ef23dcc..00000000 Binary files a/src/main/webapp/connect/common/images/reader/zoomActual.png and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/zoomFit.gif b/src/main/webapp/connect/common/images/reader/zoomFit.gif deleted file mode 100644 index fbf42f77..00000000 Binary files a/src/main/webapp/connect/common/images/reader/zoomFit.gif and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/zoomIn.gif b/src/main/webapp/connect/common/images/reader/zoomIn.gif deleted file mode 100644 index 56ccdc1e..00000000 Binary files a/src/main/webapp/connect/common/images/reader/zoomIn.gif and /dev/null differ diff --git a/src/main/webapp/connect/common/images/reader/zoomOut.gif b/src/main/webapp/connect/common/images/reader/zoomOut.gif deleted file mode 100644 index 7ece5baa..00000000 Binary files a/src/main/webapp/connect/common/images/reader/zoomOut.gif and /dev/null differ diff --git a/src/main/webapp/connect/common/js/mxProperties.js b/src/main/webapp/connect/common/js/mxProperties.js deleted file mode 100644 index 54d53765..00000000 --- a/src/main/webapp/connect/common/js/mxProperties.js +++ /dev/null @@ -1,115 +0,0 @@ -var ATLAS_RESOURCE_BASE = '../..'; -var RESOURCES_PATH = ATLAS_RESOURCE_BASE + '/resources'; -var RESOURCE_BASE = RESOURCES_PATH + '/dia'; -var STENCIL_PATH = ATLAS_RESOURCE_BASE + '/stencils'; -var SHAPES_PATH = ATLAS_RESOURCE_BASE + '/shapes'; -var IMAGE_PATH = '../../images'; -var GRAPH_IMAGE_PATH = ATLAS_RESOURCE_BASE + '/img'; -var STYLE_PATH = '../../styles'; -var CSS_PATH = STYLE_PATH; -var OPEN_FORM = ATLAS_RESOURCE_BASE + '/html/open.html'; -var TEMPLATE_PATH = ATLAS_RESOURCE_BASE + '/templates'; - -var mxBasePath = ATLAS_RESOURCE_BASE + '/mxgraph'; -var mxLoadResources = false; - -var umlDomain = false; -var collab = null; - -// Specifies connection mode for touch devices (at least one should be true) -var isLocalStorage = typeof(Storage) != 'undefined'; -var uiTheme = 'atlas'; - -var urlParams = (function(url) { - var result = new Object(); - var idx = url.lastIndexOf('?'); - - if (idx > 0) { - var params = url.substring(idx + 1).split('&'); - - for ( var i = 0; i < params.length; i++) { - idx = params[i].indexOf('='); - - if (idx > 0) { - result[params[i].substring(0, idx)] = params[i].substring(idx + 1); - } - } - } - - return result; -})(window.location.href); - -function getLanguage() -{ - var lang = urlParams['lang']; - - if (lang == null) - { - // Cannot use mxSettings here - if (isLocalStorage) - { - try - { - var value = localStorage.getItem('.drawio-config'); - - if (value != null) - { - lang = JSON.parse(value).language || null; - } - } - catch (e) - { - // cookies are disabled, attempts to use local storage will cause - // a DOM error at a minimum on Chrome - isLocalStorage = false; - } - } - } - - return lang; -}; - -var mxLanguage = getLanguage(); - -// Add new languages here. First entry is translated to [Automatic] -// in the menu defintion in Diagramly.js. -var mxLanguageMap = {'i18n': '', 'id' : 'Bahasa Indonesia', 'ms' : 'Bahasa Melayu', 'bs' : 'Bosanski', 'ca' : 'Català', 'cs' : 'ÄŒeÅ¡tina', 'da' : 'Dansk', 'de' : 'Deutsch', 'et' : 'Eesti', 'en' : 'English', 'es' : 'Español', - 'fil' : 'Filipino', 'fr' : 'Français', 'gl' : 'Galego', 'it' : 'Italiano', 'hu' : 'Magyar', 'nl' : 'Nederlands', 'no' : 'Norsk', - 'pl' : 'Polski', 'pt-br' : 'Português (Brasil)', 'pt' : 'Português (Portugal)', 'ro' : 'Română', 'fi' : 'Suomi', 'sv' : 'Svenska', 'vi' : 'Tiếng Việt', 'tr' : 'Türkçe', - 'el' : 'Ελληνικά', 'ru' : 'РуÑÑкий', 'sr' : 'СрпÑки', 'uk' : 'УкраїнÑька', 'he' : 'עברית', - 'ar' : 'العربية', 'th' : 'ไทย', 'ko' : '한국어', 'ja' : '日本語', 'zh' : '简体中文', 'zh-tw' : 'ç¹é«”中文'}; - -var mxLanguages = []; - -// Populates the list of supported special language bundles -for (var lang in mxLanguageMap) -{ - // Empty means default (ie. browser language), "en" means English (default for unsupported languages) - // Since "en" uses no extension this must not be added to the array of supported language bundles. - if (lang != 'en') - { - mxLanguages.push(lang); - } -} - -function mxscript(src) -{ - document.write(' - - - - - -
-

Gliffy Import

-

Click the "Start Import" button to import all Gliffy diagrams to draw.io.
- Please note that the import procedure will take some time and the browser window must remain open until the import is completed.
-

- -
-

-
- - - diff --git a/src/main/webapp/connect/confluence/admin.js b/src/main/webapp/connect/confluence/admin.js deleted file mode 100644 index 39009f90..00000000 --- a/src/main/webapp/connect/confluence/admin.js +++ /dev/null @@ -1,1142 +0,0 @@ -function guid() -{ - function s4() - { - return Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); - } - - return s4() + s4() + '-' + s4() + '-' + s4() + '-' + - s4() + '-' + s4() + s4() + s4(); -}; - -var drawioMacroParams = ['diagramName', 'contentId', 'contentVer', 'revision', 'width', 'height', 'tempPreview', 'zoom', 'lbox', - 'diagramDisplayName', 'tbstyle', 'links', 'simple', 'hiResPreview', 'inComment', 'aspect', 'pageId', 'baseUrl', - //inc-drawio macro specific params - 'diagramUrl', 'includedDiagram', 'aspectHash', 'imgPageId', 'attVer', 'custContentId', - 'pCenter' -]; - -function getMacroRegExps(macroName, attParams) -{ - //RegExp that will be used - var findMacrosRegEx = new RegExp('\\]+?(?=ac\\:name\\=)ac\\:name\\=\\"' + macroName + '\\".*?(?=\\<\\/ac\\:structured\\-macro\\>)\\<\\/ac\\:structured\\-macro\\>', 'g'); - var findMacroIdRegEx = new RegExp('ac\\:macro\\-id\\=\\"([^\\"]+)'); - - var findOldMacrosRegEx = new RegExp('\\]+?(?=ac\\:name\\=)ac\\:name\\=\\"' + macroName + '\\".*?(?=\\<\\/ac\\:macro\\>)\\<\\/ac\\:macro\\>', 'g'); - - var findAttParamsRegExs = []; - - for (var i = 0; i < attParams.length; i++) - { - findAttParamsRegExs.push(new RegExp('\\([^\\<]+)')); - } - - return {findMacrosRegEx: findMacrosRegEx, findMacroIdRegEx: findMacroIdRegEx, findOldMacrosRegEx: findOldMacrosRegEx, findAttParamsRegExs: findAttParamsRegExs}; -}; - -function replacePageMacro(page, regExps, processAttFn, pageUpdateSuccess, pageUpdateError, alwaysCallSuccess) -{ - var originalBody = page.body.storage.value; - - var pageXml = originalBody; - - var foundMacros = pageXml.match(regExps.findMacrosRegEx); - var foundOldMacros = pageXml.match(regExps.findOldMacrosRegEx); - - var macrosParsed = 0; - var drawIoMacros = {}; - var foundMarcosIds = []; - var spaceKey = AC.getSpaceKey(page._expandable.space); - var macrosCount = (foundMacros? foundMacros.length : 0) + (foundOldMacros? foundOldMacros.length : 0); - - - function attProcessedFn(attInfo, skipErrorFlag) - { - //Replace found macro with a draw.io one and use the same preview image - if (skipErrorFlag) - { - drawIoMacros[attInfo.macroId] = skipErrorFlag; - } - else - { - //generate draw.io macro HTML - var drawIoMacro = '' + baseUrl - + '' + AC.htmlEntities(attInfo.name) - + '' + (attInfo.zoom ? attInfo.zoom : '1') - + '' + (attInfo.pageId || page.id) - + '' + (attInfo.lbox == 'false' || attInfo.lbox == '0'? '0' : '1') - + (attInfo.width? ('' + attInfo.width) : '') - + (attInfo.height? ('' + attInfo.height) : '') - + (!attInfo.isInc && attInfo.revision? ('' + attInfo.revision) : '') - + (attInfo.previewPng? ('' + AC.htmlEntities(attInfo.previewPng)) : '') - + (attInfo.contentId? ('' + attInfo.contentId) : '') - + (!attInfo.isInc && attInfo.contentVer? ('' + attInfo.contentVer) : '') - + (attInfo.diagramDisplayName? ('' + attInfo.diagramDisplayName) : '') - + (attInfo.tbstyle? ('' + attInfo.tbstyle) : '') - + (attInfo.links? ('' + attInfo.links) : '') - + (attInfo.simple? ('' + attInfo.simple) : '') - + (attInfo.hiResPreview? ('' + attInfo.hiResPreview) : '') - + (attInfo.inComment? ('' + attInfo.inComment) : '') - + (attInfo.aspect? ('' + attInfo.aspect) : '') - + (attInfo.diagramUrl? ('' + attInfo.diagramUrl) : '') - + (attInfo.aspectHash? ('' + attInfo.aspectHash) : '') - + (attInfo.imgPageId? ('' + attInfo.imgPageId) : '') - + (attInfo.attVer? ('' + attInfo.attVer) : '') - + (attInfo.isInc? ('1') : '') - + (attInfo.pCenter? ('' + attInfo.pCenter) : '') - + ''; - - drawIoMacros[attInfo.macroId] = drawIoMacro; - } - - macrosParsed++; - - if (macrosCount == macrosParsed) - { - var successfullyConverted = 0; - var skippedCount = 0; - - for (var j = 0; j < macrosParsed; j++) - { - var id = foundMarcosIds[j].id; - - if (isFinite(drawIoMacros[id])) - { - if (drawIoMacros[id] == 2) - { - successfullyConverted++; //skipping is successful - skippedCount++; - } - } - else - { - var macroTxt = foundMarcosIds[j].macroTxt; - - originalBody = originalBody.replace(macroTxt, drawIoMacros[id]); - successfullyConverted++; - } - } - - //If all macros are skipped, no need to change the page - if (skippedCount == successfullyConverted) - { - pageUpdateSuccess(successfullyConverted, macrosParsed); - } - else - { - //update page contents - AP.request({ - type: 'PUT', - data: JSON.stringify({ - "body": { - "storage": { - "value": originalBody, - "representation": "storage", - "embeddedContent": [] - } - }, - "version": { - "number": page.version.number + 1 - }, - "type": page.type, - "title": page.title, - "status": "current" - }), - url: "/rest/api/content/"+ page.id, - contentType: 'application/json;charset=UTF-8', - success: function(resp) { - //update page object for next phase - page.body.storage.value = originalBody; - pageUpdateSuccess(successfullyConverted, macrosParsed); - }, - error: pageUpdateError - }); - } - } - }; - - if (foundMacros && foundMacros.length > 0) - { - var doneIndex = 0; - var PARTITION_SIZE = 5; - - //Process macros 5 (PARTITION_SIZE) at a time to throttle the process - function processPartition(limit) - { - function partitionDone() - { - doneIndex++; - - if (foundMacros.length != limit && doneIndex == limit) - { - processPartition(limit + PARTITION_SIZE); - } - }; - - - limit = Math.min(foundMacros.length, limit); - - for (var i = doneIndex; i < limit; i++) - { - var potentialId = foundMacros[i].match(regExps.findMacroIdRegEx); - var macroId = potentialId? potentialId[1] : guid(); - - foundMarcosIds.push({id: macroId, macroTxt: foundMacros[i]}); - - var params = []; - - for (var j = 0; j < regExps.findAttParamsRegExs.length; j++) - { - var paramFound = foundMacros[i].match(regExps.findAttParamsRegExs[j]); - - params.push(paramFound != null && paramFound[1] != null? AC.fromHtmlEntities(paramFound[1]) : null); - } - - //get the attachment content - processAttFn(page.id, page.type, spaceKey, params, macroId, function(attInfo) - { - attProcessedFn(attInfo); - partitionDone(); - }, - function(attInfo) - { - attProcessedFn(attInfo, 1); - partitionDone(); - }, - function(attInfo) - { - attProcessedFn(attInfo, 2); - partitionDone(); - }); - }; - } - - processPartition(PARTITION_SIZE); - } - - if (foundOldMacros && foundOldMacros.length > 0) - { - for (var i = 0; i < foundOldMacros.length; i++) - { - //these macros has no id, so generate a unique id - var macroId = guid(); - - foundMarcosIds.push({id: macroId, macroTxt: foundOldMacros[i]}); - - var params = []; - - for (var j = 0; j < regExps.findAttParamsRegExs.length; j++) - { - var paramFound = foundOldMacros[i].match(regExps.findAttParamsRegExs[j]); - - params.push(paramFound? AC.fromHtmlEntities(paramFound[1]) : null); - } - - //get the attachment content - processAttFn(page.id, page.type, spaceKey, params, macroId, attProcessedFn, - function(attInfo) - { - attProcessedFn(attInfo, 1); - }, - function(attInfo) - { - attProcessedFn(attInfo, 2); - }); - }; - } - - if (macrosCount == 0 && alwaysCallSuccess) - { - pageUpdateSuccess(0, 0); - } - - return macrosCount; -}; - -var MassDiagramsProcessor = function(macroName, readableName, attParams, processAttFn, logDiv, doneFn) -{ - var start = 0, limit = 100; - var regExps = getMacroRegExps(macroName, attParams); - - var pagesCount = 0, pagesIndex = 0; - var pagesList = [], pagesMap = {}; - - function searchContentForMacro(onSuccess, onError) - { - //keeping the block of AP.require to minimize the number of changes! - { - AP.request({ - type: 'GET', - url : '/rest/api/content/search?cql=' + encodeURIComponent('macro="' + macroName + '"') + '&start=' + start + '&limit=' + limit, - contentType: 'application/json;charset=UTF-8', - success: function(resp) { - var resp = JSON.parse(resp); - var list = resp.results; - - //Ensure pages list is unique since search api return duplicates - for (var i = 0; i < list.length; i++) - { - if (!pagesMap[list[i].id] && list[i].status != 'trashed') //remove duplicates & trashed pages - { - pagesList.push(list[i]); - pagesMap[list[i].id] = true; - pagesCount++; - } - } - - //Support pageing - if (resp._links && resp._links.next) - { - start += resp.limit; //Sometimes the limit is changed by the server - searchContentForMacro(onSuccess, onError); - } - else - { - //Done - onSuccess(); - } - }, - error: onError - }); - }; - }; - - function getPageContent(pageId, success, error) - { - //keeping the block of AP.require to minimize the number of changes! - { - AP.request({ - type: 'GET', - url: '/rest/api/content/' + pageId + '/?expand=body.storage,version', - contentType: 'application/json;charset=UTF-8', - success: success, - error: error - }); - }; - }; - - //Process pages one at a time - function processPage() - { - if (pagesIndex >= pagesCount) - { - return true; //loop is finished - } - - var page = pagesList[pagesIndex]; - - logDiv.append($('
' + mxResources.get('confAPageFoundFetch', [AC.htmlEntities(page.title)]) + '...
')); - - getPageContent(page.id, loadPageSuccess, loadPageError); - - return false; - }; - - function pageProcessed() - { - pagesIndex++; - - if (processPage()) - { - logDiv.append($('
' + mxResources.get('confAAllDiagDone', [readableName]) + '
')); - - if (doneFn) - { - doneFn(); - } - } - }; - - function loadPageSuccess(page) - { - page = JSON.parse(page); - - logDiv.append($('
' + mxResources.get('confAStartedProcessing', [AC.htmlEntities(page.title)]) + '...
')); - - var macrosCount = replacePageMacro(page, regExps, processAttFn, function(successfullyConverted, macrosParsed) - { - if (successfullyConverted == macrosParsed) - { - logDiv.append($('
' + mxResources.get('confAAllDiagInPageDone', [readableName, AC.htmlEntities(page.title)]) + '
')); - } - else - { - logDiv.append($('
' + mxResources.get('confAPartialDiagDone', [successfullyConverted, macrosParsed, readableName, AC.htmlEntities(page.title)]) + '
')); - } - - pageProcessed(); - }, function(resp) - { - logDiv.append($('
' + mxResources.get('confAUpdatePageFailed', [AC.htmlEntities(page.title)]) + '
')); - pageProcessed(); - console.log(resp); - }); - - if (macrosCount == 0) - { - logDiv.append($('
' + mxResources.get('confANoDiagFoundInPage', [readableName, AC.htmlEntities(page.title)]) + '
')); - pageProcessed(); - } - }; - - function loadPageError(resp) - { - logDiv.append($('
' + mxResources.get('confAFetchPageFailed') + '
')); - console.log(resp); - pageProcessed(); - }; - - //Code starts execution here - searchContentForMacro(function success() - { - if (pagesCount == 0) - { - logDiv.append($('
' + mxResources.get('confANoDiagFound', [readableName]) + '
')); - - if (doneFn) - { - doneFn(); - } - } - else - { - processPage(); - } - }, function error(err) - { - logDiv.append($('
' + mxResources.get('confASearchFailed', [readableName]) + '
')); - console.log(err); - }); -}; - -var GliffyMassImporter = function(logDiv, doneFn) -{ - var link = document.createElement('a'); - link.href = location.href; - link.href = link.href; //to have 'host' populated under IE - var hostUrl = link.protocol + '//' + link.hostname; - var convertedDiagrams = {}; - - function importGliffyAtt(pageId, pageType, spaceKey, params, macroId, success, error, skip) - { - var attName = params[0]; - var linkedPageId = params[1]; - pageId = linkedPageId || pageId; - - if (!attName) - { //This is a draft diagram that is stored on Gliffy servers and only accessed by 'macroId' and requires authentication - error({macroId:macroId}); - return; - } - - var diagKey = pageId + '-' + attName; - logDiv.append($('
' + mxResources.get('confAGliffyDiagFound', [AC.htmlEntities(attName), 'Gliffy']) + '...
')); - - function localSuccess(info) - { - var attInfo = { - name: attName + ".drawio", - macroId: macroId, - contentId: info.contentId, - contentVer: info.contentVer, - //TODO get the actual width & height - //TODO It works with this hardcoded number, but it is better to get the actual value - width: 500, - height: 500 - }; - - if (linkedPageId != null) - { - attInfo.isInc = true; - attInfo.pageId = linkedPageId; - - logDiv.append($('
' + mxResources.get('confAGliffyDiagImported', [AC.htmlEntities(attName), 'Gliffy (Linked)']) + '
')); - } - else - { - attInfo.revision = info.revision; - attInfo.previewPng = attName + ".png"; - - logDiv.append($('
' + mxResources.get('confAGliffyDiagImported', [AC.htmlEntities(attName), 'Gliffy']) + '
')); - } - - success(attInfo); - }; - - function convertDiagram() - { - //Get the latest version (no version parameter) - AP.request({ - url: "/download/attachments/" + pageId + "/" - + encodeURIComponent(attName.trim()), //Conf removes spaces from attachments file names - success: function(resp) - { - var blob = new Blob([resp], {type : 'application/json'}); - - var formData = new FormData(); - formData.append('format', 'xml'); - formData.append("upfile", blob); - - var xhr = new XMLHttpRequest(); - xhr.open('POST', hostUrl + '/import'); - - xhr.onreadystatechange = function() - { - if (xhr.readyState == 4) - { - if (xhr.status >= 200 && xhr.status <= 299 && - xhr.responseText.substring(0, 13) == '' + mxResources.get('confASavingImpGliffyFailed', [AC.htmlEntities(attName), 'Gliffy']) + '')); - console.log(err); - error({macroId:macroId}); - }); - }, function(err) - { - logDiv.append($('
' + mxResources.get('confASavingImpGliffyFailed', [AC.htmlEntities(attName), 'Gliffy']) + '
')); - console.log(err); - error({macroId:macroId}); - }, false, 'application/vnd.jgraph.mxfile', mxResources.get('confAImportedFromByDraw', [attName])); - } - else - { - logDiv.append($('
' + mxResources.get('confAImportGliffyFailed', [AC.htmlEntities(attName), 'Gliffy']) + '
')); - console.log(xhr.status, xhr.responseText); - error({macroId:macroId}); - } - } - }; - - xhr.send(formData); - }, - error: function(resp) - { - logDiv.append($('
' + mxResources.get('confAFetchGliffyFailed', [AC.htmlEntities(attName), 'Gliffy']) + '
')); - console.log(resp); - error({macroId:macroId}); - } - }); - }; - - var info = convertedDiagrams[diagKey]; - - if (info === true) //Pending, wait - { - var trials = 0; - - function waitForConversion() - { - trials++; - info = convertedDiagrams[diagKey]; - - if (info !== true) - { - localSuccess(info) - } - else if (trials < 15) //4.5 second wait, during test. It took about 2 sec - { - setTimeout(waitForConversion, 300); - } - else - { - //Try conversion again in case an error occured - convertDiagram(); - } - } - - setTimeout(waitForConversion, 300); - } - else if (info != null) - { - //Diagram is already converted, so directly convert the macro - localSuccess(info); - } - else - { - convertedDiagrams[diagKey] = true; - convertDiagram(); - } - }; - - logDiv.html("
"); - - MassDiagramsProcessor('gliffy', 'Gliffy', ['name', 'pageid'], importGliffyAtt, logDiv, doneFn); -}; - -function cleanBrokenCustomContents(logDiv, callback, error) -{ - logDiv.append($('
' + mxResources.get('confACheckBrokenDiagLnk') + '
')); - - var customContent2Del = []; - var pagesAttachments = {}; - var itemsToProcess = 0; - var processedItems = 0; - var allChunksDone = false; - var pendingCallbacks = {}; - var pageCustomContents = {}; - var customContentsMap = {}; - - function checkDelDone() - { - processedItems++; - - if (processedItems == itemsToProcess) - { - callback(pageCustomContents, customContentsMap); - } - }; - - function addToPage(pageId, contentId, contentVer, diagramName) - { - if (pageCustomContents[pageId] == null) - { - var obj = {}; - obj[diagramName] = {id: contentId, ver: contentVer}; - pageCustomContents[pageId] = obj; - } - else if (pageCustomContents[pageId][diagramName] && pageCustomContents[pageId][diagramName].id != contentId) //Sometimes, search returns duplicate entries! - { - customContent2Del.push({id: contentId, name: diagramName, duplicate: true}); - return false; - } - else - { - pageCustomContents[pageId][diagramName] = {id: contentId, ver: contentVer}; - } - - return true; - }; - - function checkDone(panic) - { - function deleteAtt(id, name, duplicate) - { - logDiv.append($('
' + mxResources.get('confADelDiagLinkOf', [name]) + (duplicate? ' ' + mxResources.get('confADupLnk') : '') + '.
')); - - AP.request({ - type: 'DELETE', - url: '/rest/api/content/' + id, - contentType: 'application/json;charset=UTF-8', - success: checkDelDone, - error: function() - { - logDiv.append($('
' + mxResources.get('confADelDiagLnkFailed', [name]) + '
')); - checkDelDone(); //Consider error as done also as we cannot do something else - } - }); - }; - - if (panic || (allChunksDone && processedItems == itemsToProcess)) - { - processedItems = 0; - itemsToProcess = customContent2Del.length; - - if (itemsToProcess > 0) - { - //delete collected broken custom contents then callback - for (var i = 0; i < customContent2Del.length; i++) - { - var c2del = customContent2Del[i]; - deleteAtt(c2del.id, c2del.name, c2del.duplicate); - } - } - else - { - //if nothing needs to be deleted, callback directly - callback(pageCustomContents, customContentsMap); - } - } - }; - - function collectAtts(pageId, callback, error, start, atts) - { - //first call - if (start == null) - { - start = 0; - - if (typeof(pendingCallbacks[pageId]) === 'undefined') - { - atts = {}; - pendingCallbacks[pageId] = [callback]; - } - else //Another call for the same page before getting the response - { - pendingCallbacks[pageId].push(callback); //data race? - return; - } - } - - AP.request({ - type: 'GET', - url: '/rest/api/content/' + pageId + '/child/attachment?limit=100&expand=version&start=' + start, - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - for (var i = 0; i < resp.results.length; i++) - { - var obj = resp.results[i]; - atts[obj.title] = obj.version.number; - } - - //Support pageing - if (resp._links && resp._links.next) - { - start += resp.limit; //Sometimes the limit is changed by the server - collectAtts(pageId, callback, error, start, atts); - } - else - { - pagesAttachments[pageId] = atts; - - for (var i = 0; i < pendingCallbacks[pageId].length; i++) - { - pendingCallbacks[pageId][i](); - } - - delete pendingCallbacks[pageId]; - } - }, - error: function(err) - { - //If not found, mark this page as not found - if (err.status == 404) - { - pagesAttachments[pageId] = false; - - for (var i = 0; i < pendingCallbacks[pageId].length; i++) - { - pendingCallbacks[pageId][i](); - } - - delete pendingCallbacks[pageId]; - } - else - { - //All other errors are unexpected and will stop the process - error(err); - } - } - }); - }; - - function processChunk(start) - { - AP.request({ - url: '/rest/api/content/search?cql=' + encodeURIComponent('type="ac:com.mxgraph.confluence.plugins.diagramly:drawio-diagram"') + '&limit=50&expand=body.storage,version&start=' + start, - success: function(resp) - { - resp = JSON.parse(resp); - var list = resp.results; - - if (list) - { - list = list.filter(function(cc) - { - return cc.status != 'trashed'; //remove trashed custom content - }); - - itemsToProcess += list.length; - - //Check each item in the list - for (var i = 0; i < list.length; i++) - { - try - { - (function(attInfo, contentId, contentVer) - { - if (!addToPage(attInfo.pageId, contentId, contentVer, attInfo.diagramName)) - { - processedItems++; - checkDone(); - return; //No need to check as it is a duplicate - } - - - function checkAtt(pageAtts) - { - //not found or wrong version - if (pageAtts == false || pageAtts[attInfo.diagramName] == null || pageAtts[attInfo.diagramName] < attInfo.version) - { - customContent2Del.push({id: contentId, name: attInfo.diagramName}); - } - else - { - customContentsMap[contentId] = attInfo; - } - - processedItems++; - checkDone(); - }; - - var pageAtts = pagesAttachments[attInfo.pageId]; - - if (pageAtts != null) - { - checkAtt(pageAtts); - } - else - { - //fetch page attachments - collectAtts(attInfo.pageId, function() - { - checkAtt(pagesAttachments[attInfo.pageId]); - }, function(err) - { - logDiv.append($('
' + mxResources.get('confAUnexpErrProcessPage', [attInfo.pageId]) + '.
')); - console.log(err); - - checkDone(true); - }); - } - })(JSON.parse(decodeURIComponent(list[i]["body"]["storage"]["value"])), list[i].id, list[i].version.number); - } - catch(e) - { - //ignore, this should not happen! But, if it happens, it means a corrupted custom content. Just delete it - console.log(e); - customContent2Del.push({id: list[i].id, name: list[i].title}); - processedItems++; - checkDone(); - } - } - } - - checkDone(); - - //Support pageing - if (resp._links && resp._links.next) - { - start += resp.limit; //Sometimes the limit is changed by the server - processChunk(start); - } - else - { - allChunksDone = true; - checkDone(); - } - }, - error : error - }); - }; - - processChunk(0); -}; - -var DrawIoDiagramsIndexer = function(logDiv, doneFn) -{ - var pageCustomContents = {}, customContentsMap = {}; - - function fixDrawIoCustomContent(pageId, pageType, spaceKey, params, macroId, success, error, skip) - { - //['diagramName', 'contentId', 'contentVer', 'revision', 'width', 'height', 'tempPreview', 'zoom', 'lbox', 'diagramDisplayName', 'tbstyle', 'links', 'simple', 'hiResPreview', 'inComment', 'aspect', 'pageId', 'baseUrl', 'diagramUrl', 'includedDiagram', 'aspectHash', 'imgPageId', 'attVer', 'custContentId', 'pCenter'] - var attName = params[0]; - var contentId = params[1] || params[23]; - var contentVer = params[2]; - var revision = params[3]; - var width = params[4]; - var height = params[5]; - var tempPreview = params[6]; - var zoom = params[7]; - var lbox = params[8]; - var diagramDisplayName = params[9]; - var tbstyle = params[10]; - var links = params[11]; - var simple = params[12]; - var hiResPreview = params[13]; - var inComment = params[14]; - var aspect = params[15]; - var macroPageId = params[16]; - var macroBaseUrl = params[17]; - var pCenter = params[24]; - - logDiv.append($('
' + mxResources.get('confADiagFoundIndex', [AC.htmlEntities(attName)]) + '...
')); - - var attInfo = { - macroId: macroId, - name: attName, - contentId: contentId, - contentVer: contentVer, - revision: revision, - width: width, - height: height, - previewPng: tempPreview, - zoom: zoom, - lbox: lbox, - diagramDisplayName: diagramDisplayName, - tbstyle: tbstyle, - links: links, - simple: simple, - hiResPreview: hiResPreview, - inComment: inComment, - aspect: aspect, - pCenter: pCenter - }; - - function addNewCustomContent() - { - AC.saveCustomContent(spaceKey, pageId, pageType, attName, attName, revision, null, null, - function(responseText) - { - logDiv.append($('
' + mxResources.get('confADiagIndexSucc', [AC.htmlEntities(attName)]) + '
')); - - var content = JSON.parse(responseText); - - attInfo.contentId = content.id; - attInfo.contentVer = content.version.number; - - success(attInfo); - }, function(err) - { - logDiv.append($('
' + mxResources.get('confAIndexDiagFailed', [AC.htmlEntities(attName)]) + '
')); - console.log(err); - error(attInfo); - }); - }; - - var info = customContentsMap[contentId]; - - //Copy & Paste macros result in macros that belongs to another page. We can simply skip those macros - if (macroPageId != pageId) - { - logDiv.append($('
' + mxResources.get('confASkipDiagOtherPage', [AC.htmlEntities(attName)]) + '
')); - skip(attInfo); - } - else if (info == null && pageCustomContents[pageId] != null && pageCustomContents[pageId][attName] != null) //Reuse existing one in case the same diagram is used more than once - { - logDiv.append($('
' + mxResources.get('confADiagIndexSucc', [AC.htmlEntities(attName)]) + '
')); - var exiting = pageCustomContents[pageId][attName]; - attInfo.contentId = exiting.id; - attInfo.contentVer = exiting.ver; - success(attInfo); - } - else if (info == null || info.pageId != pageId || info.diagramName != attName || info.version != revision) //Invalid contentId (not found) or invalid content, add it - { - addNewCustomContent(); //Add a correct custom content - } - else if (macroBaseUrl != baseUrl) //This can happen when the Confluence domain is changed - { - logDiv.append($('
' + mxResources.get('confADiagIndexSucc', [AC.htmlEntities(attName)]) + '
')); - success(attInfo); - } - else - { - //nothing needs to be done, just skip - logDiv.append($('
' + mxResources.get('confADiagUptoDate', [AC.htmlEntities(attName)]) + '
')); - skip(attInfo); - } - }; - - logDiv.html("
"); - - //Remove existing custom contents that are broken - cleanBrokenCustomContents(logDiv, function(pageCustomContents_p, customContentsMap_p) - { - pageCustomContents = pageCustomContents_p; - customContentsMap = customContentsMap_p; - - logDiv.append($('
' + mxResources.get('done') + '.
')); - logDiv.append($('
' + mxResources.get('confACheckPagesWDraw') + '
')); - - MassDiagramsProcessor('drawio', 'draw.io', - drawioMacroParams, - fixDrawIoCustomContent, logDiv, doneFn); - }); -}; - -function getAndApplyTranslation(callback) -{ - AP.user.getLocale(function(locale) - { - if (locale != null) - { - var dash = locale.indexOf('_'); - - if (dash >= 0) - { - locale = locale.substring(0, dash); - } - - AC.initI18nAsync(locale, function() - { - //HTML elements localization - var i18nElems = document.querySelectorAll('*[data-i18n]'); //get all elements having data-i18n attribute, should be fine given a small html file - - for (var i = 0; i < i18nElems.length; i++) - { - var i18nKey = i18nElems[i].getAttribute('data-i18n'); - i18nElems[i].innerHTML = AC.htmlEntities(mxResources.get(i18nKey, null, i18nElems[i].innerHTML)); - } - - callback(); - }); - } - else - { - callback(); - } - }); -}; - -var LucidConnMassImporter = function(docsMap, importExtensionId, logDiv, doneFn) -{ - var link = document.createElement('a'); - link.href = location.href; - link.href = link.href; //to have 'host' populated under IE - var hostUrl = link.protocol + '//' + link.hostname; - - function importLucidDoc(pageId, pageType, spaceKey, params, macroId, success, error, skip) - { - var docId = params[0]; - var autoSize = params[1]; - var pageCount = params[2]; - var pages = params[3]; - var autoUpdate = params[4]; //TODO How can we get an old version based on the "updated" timestamp? - var width = params[5]; - var height = params[6]; - var align = params[7]; - var updated = params[8]; - - var docInfo = docsMap[docId]; - var docName = docInfo? docInfo.text : docId; - var diagramName = docName + '-' + docId + '.drawio'; - var diagramDisplayName = docName; - - logDiv.append($('
' + mxResources.get('confAGliffyDiagFound', [AC.htmlEntities(docName), 'Lucidchart']) + '...
')); - - chrome.runtime.sendMessage(importExtensionId, {msg: 'fileContent', docId: docId}, function(resp) - { - if (resp.error) - { - logDiv.append($('
' + mxResources.get('confAImportGliffyFailed', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - error({macroId:macroId}); - } - else - { - try - { - var drawXML = LucidImporter.importState(resp.content); - var pageIndex = pages? parseInt(pages) : 1; - var imgWidth = autoSize == 1? null : width; - var imageData = null, imageType = null; - - chrome.runtime.sendMessage(importExtensionId, - {msg: 'fileImage', docId: docId, pageId: pageIndex <= pageCount? (pageIndex - 1) : 0, width: imgWidth}, function(resp) - { - //If image failed, just warn. No need to skip this file - if (resp.error) - { - logDiv.append($('
' + mxResources.get('confASavingLucidDiagImgFailed', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - } - else - { - imageData = resp.content; - var p = resp.content.indexOf('base64,'); - imageData = resp.content.substring(p + 7); //7 is the length of "base64," - imageType = resp.content.substring(5, p-1); //5 is the length of "data:" - } - - AC.saveDiagram(pageId, diagramName, drawXML, - function(resp) - { - resp = JSON.parse(resp); - - var attInfo = { - name: diagramName, - diagramDisplayName: diagramDisplayName, - revision: resp.results[0].version.number, - macroId: macroId, - width: autoSize == 1? null : width, - height: autoSize == 1? null : height, - pCenter: align == 'center'? 1 : null, - aspect: pages? ((pageIndex - 1) + ' 1') : null - }; - - //Add custom content - AC.saveCustomContent(spaceKey, pageId, pageType, diagramName, diagramDisplayName, attInfo.revision, null, null, - function(responseText) - { - var content = JSON.parse(responseText); - - attInfo.contentId = content.id; - attInfo.contentVer = content.version.number; - - if (imageData != null) - { - AC.saveDiagram(pageId, diagramName + '.png', AC.b64toBlob(imageData, imageType), - function() - { - logDiv.append($('
' + mxResources.get('confALucidDiagImgImported', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - logDiv.append($('
' + mxResources.get('confAGliffyDiagImported', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - success(attInfo); - }, function() - { - logDiv.append($('
' + mxResources.get('confASavingLucidDiagImgFailed', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - success(attInfo); - }, false, 'image/png', mxResources.get('drawPrev')); - } - else - { - logDiv.append($('
' + mxResources.get('confAGliffyDiagImported', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - success(attInfo); - } - }, function(err) - { - logDiv.append($('
' + mxResources.get('confASavingImpGliffyFailed', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - console.log(err); - error({macroId:macroId}); - }); - - }, function(err) - { - logDiv.append($('
' + mxResources.get('confASavingImpGliffyFailed', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - console.log(err); - error({macroId:macroId}); - }, false, 'application/vnd.jgraph.mxfile', mxResources.get('confAImportedFromByDraw', [docName])); - }); - } - catch(e) - { - console.log(e); - logDiv.append($('
' + mxResources.get('confAImportGliffyFailed', [AC.htmlEntities(docName), 'Lucidchart']) + '
')); - error({macroId:macroId}); - } - } - }); - }; - - logDiv.html("
"); - - MassDiagramsProcessor('lucidchart', 'Lucidchart', - ['documentId', 'autoSize', 'pageCount', 'pages', 'autoUpdate', 'width', 'height', 'align', 'updated'], - importLucidDoc, logDiv, doneFn); -}; diff --git a/src/main/webapp/connect/confluence/config.html b/src/main/webapp/connect/confluence/config.html deleted file mode 100644 index 75fbcf5c..00000000 --- a/src/main/webapp/connect/confluence/config.html +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - -
- -
-
-

draw.io Configuration

-
- Working... -
- - - -
-
-
-

Current Custom Libraries

-
- - - - - - -
Library NameActiondraw.io Config ID
-

Click the "Add Library" button to upload a new library.
-
-
 
-
- - -
-
-
-
-
-

Custom Templates

-
-
- Custom Templates are draw.io diagrams saved in children pages of Templates page.
- For more details, please refer to this page. -
-
-
-

Select export target, then click the "Start Export" button to export all page IDs.
- Please note that the export procedure will take some time and the browser window must remain open until the export is completed.
-
-
- Export target:
- - - -
-
-
- - -
-
- -
-
-
-

After importing a space from another cloud/server instance or migrating from a cloud/server instance. Use "Page IDs Export" on that instance (the source), download the "pageIds.csv" file, then use this tool to complete the import process.

- Click "Start Import" button to upload the "pageIds.csv" file to this tool and start the import process. Please note that the import procedure will take some time and the browser window must remain open until the import is completed.
-
-
- - - -
-
-

-
-
-
-

Refresh draw.io Diagrams Index

-

Click the "Start Indexing" button to refresh draw.io diagrams index.
- Please note that the indexing procedure will take some time and the browser window must remain open until the indexing is completed.
-

- -
-

-
-
- - diff --git a/src/main/webapp/connect/confluence/config.js b/src/main/webapp/connect/confluence/config.js deleted file mode 100644 index 1b47a921..00000000 --- a/src/main/webapp/connect/confluence/config.js +++ /dev/null @@ -1,1750 +0,0 @@ -//Logs uncaught errors -window.onerror = function(message, url, linenumber, colno, err) -{ - message = 'Confluence Cloud Config: ' + ((message != null) ? message : ''); - - AC.logError(message, url, linenumber, colno, err); -}; - - -function restrictContentToAdmins(contentId) -{ - AP.user.getCurrentUser(function(user) - { - AP.request({ - type: 'PUT', - url: '/rest/api/content/' + contentId + '/restriction', - contentType: 'application/json;charset=UTF-8', - data: JSON.stringify([{ - "operation": "update", - "restrictions": { - "user": [ - { - "type": "known", - "accountId": user.atlassianAccountId - } - ], - "group": [ - { - "type": "group", - "name": "administrators" - }, - { - "type": "group", - "name": "site-admins" - } - ] - } - } - ]), - error: function(err) - { - AC.logError('Confluence Cloud Config: Error in setting restrictions ' + err.responseText); - } - }); - }); -}; - -var collectAllPages = function(callback, error) -{ - var start = 0, limit = 200; - var pages = []; - - function getChunck() - { - AP.request({ - type: 'GET', - url: '/rest/api/content?start=' + start + '&limit=' + limit, - contentType: 'application/json;charset=UTF-8', - success: function(resp) { - var resp = JSON.parse(resp); - - for (var i = 0; i < resp.results.length; i++) - { - pages.push({ - id: resp.results[i].id, - title: resp.results[i].title, - type: resp.results[i].type, - spaceKey: AC.getSpaceKey(resp.results[i]._expandable? resp.results[i]._expandable.space : '') - }); - } - - //Support pageing - if (resp._links && resp._links.next) - { - start += resp.limit; //Sometimes the limit is changed by the server - getChunck(); - } - else - { - callback(pages); - } - }, - error: error - }); - }; - - getChunck(); -}; - -var exportPageIds = function(exportTxt) -{ - $('#busyIcon').show(); - var idExportInfo = $('#idExportInfo'); - var errors = []; - var quoteCharRegex = /\"/g; - - function convertMimeType(doneFn) - { - idExportInfo.html('Processing draw.io diagrams...'); - - collectDrawAtts(function(attList) - { - var doneIndex = 0; - var PARTITION_SIZE = 5; - - //Process macros 5 (PARTITION_SIZE) at a time to throttle the process - function processPartition(limit) - { - function partitionDone() - { - doneIndex++; - - if (attList.length != limit && doneIndex == limit) - { - processPartition(limit + PARTITION_SIZE); - } - else if (attList.length == limit) - { - //Repeat twice since the API return duplicate entries!! - if (doneFn) - { - idExportInfo.html('Processing draw.io diagrams is done.'); - doneFn(mimeConversionDone); - } - } - }; - - - limit = Math.min(attList.length, limit); - - if (attList.length == 0) - { - partitionDone(); - } - - for (var i = doneIndex; i < limit; i++) - { - var att = attList[i]; - idExportInfo.html('Checking ' + att.title + '...'); - - att.metadata.mediaType = 'application/vnd.jgraph.mxfile'; - - AP.request({ - type: 'PUT', - url: '/rest/api/content/' + att.container.id + '/child/attachment/' + att.id, - data: JSON.stringify({ - id: att.id, - version: att.version, - type: 'attachment', - metadata: att.metadata - }), - contentType: 'application/json;charset=UTF-8', - success: partitionDone, - error: function() - { - errors.push(mxResources.get('confAErrCheckDrawDiag')); - partitionDone(); - } - }); - }; - } - - processPartition(PARTITION_SIZE); - }, - function() - { - errors.push(mxResources.get('confAErrFetchDrawList')); - }); - }; - - //Code adapted from EditorUi.prototype.doSaveLocalFile - function downloadTxtFile(data, filename) - { - var mimeType = 'text/plain'; - - // Newer versions of IE - if (window.Blob && navigator.msSaveOrOpenBlob) - { - var blob = new Blob([data], {type: mimeType}); - navigator.msSaveOrOpenBlob(blob, filename); - } - else - { - var a = document.createElement('a'); - - // Workaround for mxXmlRequest.simulate no longer working in PaleMoon - // if this is used (ie PNG export broken after XML export in PaleMoon) - // and for "WebKitBlobResource error 1" for all browsers on iOS. - var useDownload = (navigator.userAgent == null || - navigator.userAgent.indexOf("PaleMoon/") < 0) && - typeof a.download !== 'undefined'; - - // Workaround for Chromium 65 cross-domain anchor download issue - if (mxClient.IS_GC && navigator.userAgent != null) - { - var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./) - var vers = raw ? parseInt(raw[2], 10) : false; - useDownload = vers == 65 ? false : useDownload; - } - - if (useDownload) - { - a.href = URL.createObjectURL(new Blob([data], {type: mimeType})); - a.download = filename; - document.body.appendChild(a); - - try - { - window.setTimeout(function() - { - URL.revokeObjectURL(a.href); - }, 20000); - - a.click(); - a.parentNode.removeChild(a); - } - catch (e) - { - // ignore - } - } - else - { - alert('Your browser does not support file download'); - } - } - }; - - - function mimeConversionDone() - { - var exportStr = 'cloud;\nbaseUrl=' + baseUrl + ';\n'; - - function safe(str) - { - if (typeof str === 'undefined' || str === null) - return ''; - - str = str.replace(quoteCharRegex, '""'); - - var needsQuotes = str.indexOf('"') > -1 - || str.indexOf('\n') > -1 - || str.indexOf('\r') > -1 - || str.indexOf(';') > -1 - || str.indexOf(',') > -1 - || str.charAt(0) === ' ' - || str.charAt(str.length - 1) === ' '; - - return needsQuotes ? '"' + str + '"' : str; - } - - collectAllPages(function(pages) - { - for (var i = 0; i < pages.length; i++) - { - exportStr += pages[i].id + ',' + safe(pages[i].title) + ',' + pages[i].spaceKey + ';\n'; - } - - exportTxt.val(exportStr); - - $('#pageIdsDownload').show(); - $('#pageIdsDownload').click(function() - { - downloadTxtFile(exportStr, 'pageIds.csv'); - }); - - if (errors.length > 0) - { - $('#idExportErrors').html(errors.join('
')); - } - - $('#busyIcon').hide(); - }, function() - { - errors.push(mxResources.get('confAErrFetchPageList')); - exportTxt.val(exportStr + '\n\n' + mxResources.get('confAErrOccured')); - }); - }; - - //Cloud import doesn't need mimeType fixing - if ($('#expTrgCloud').is(':checked')) - { - mimeConversionDone(); - } - else - { - //Repeat twice since the API return duplicate entries!! - convertMimeType(convertMimeType); - } -}; - -function showError() -{ - $('#confError').show(); - $('#createSpace').hide(); -}; - -var configPageId = null; -var libsPageId = null; -var CONFIG_FILENAME = 'configuration.json'; - -function getConfigFile(callback, error) -{ - AP.request({ - url: '/download/attachments/' + configPageId + '/' + encodeURIComponent(CONFIG_FILENAME), - success: callback, - error : error - }); -}; - -function createAttFile(pageId, filename, mimeType, content, callback, error, checkExist) -{ - function doCreateFile() - { - var attFile = new Blob([content], {type : mimeType}); - attFile.name = filename; - - var reqData = {file: attFile, minorEdit: true}; - - AP.request({ - type: 'PUT', - data: reqData, - url: '/rest/api/content/' + pageId + '/child/attachment', - contentType: 'multipart/form-data', - success: callback, - error: error - }); - }; - - //check file exists - if (checkExist) - { - AP.request({ - type: 'GET', - url: '/rest/api/content/' + pageId + '/child/attachment', - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - resp = JSON.parse(resp); - var found = false; - - for (var i = 0; i < resp.results.length; i++) - { - var item = resp.results[i]; - - if (item.title == filename) - { - found = true; - break; - } - } - - if (!found) - { - doCreateFile(); - } - else - { - callback(true); - } - }, - error: error - }); - } - else - { - doCreateFile(); - } -}; - -var lastConfigVersion = 1; - -function checkConfigAndSave() -{ - var editor = document.querySelector('#configJSON'); - editor.parentNode.removeAttribute('data-line'); - var content = editor.textContent; - $('#jsonMsg').css('color', '#000000').html(' ' + mxResources.get('saving') + '...'); - - try - { - if (content != null && content.trim().length > 0) - { - var config = JSON.parse(content); - - // is user didn't set version manually or forgot to increase - increase it - if (!config.version || config.version <= lastConfigVersion) - { - lastConfigVersion = lastConfigVersion + 0.1; - config.version = Number(lastConfigVersion.toFixed(1)).toString(); - content = JSON.stringify(config); - } - } - else - { - content = ''; - } - - createAttFile(configPageId, CONFIG_FILENAME, 'application/json', content, function(resp) - { - $('#jsonMsg').css('color', '#00bb00').html(mxResources.get('savedSucc')); - }, function() - { - $('#jsonMsg').css('color', '#bb0000').html(mxResources.get('confASaveFailedErr')); - }); - } - catch(e) - { - var errMsg = e.message; - - try - { - var formatedErrMsg = errMsg, lineNum = -1; - - if (errMsg.indexOf('at position') > 0) - { - var errPos = parseInt(errMsg.match(/at position(:| )(\d+)/)[2]); - var txtBefore = content.substring(0, errPos); - var lineNum = (txtBefore.match(/\n/g) || []).length + 1; - var lastNL = txtBefore.lastIndexOf('\n'); - var linePos = errPos - (lastNL > 0? lastNL : 0); - - formatedErrMsg = errMsg + ' [' + mxResources.get('line') + ' ' + lineNum + ', ' + mxResources.get('character') + ' ' + linePos + ']'; - } - else if (errMsg.indexOf('at line ') > 0) - { - var lineNum = parseInt(errMsg.match(/at line (\d+)/)[1]); - } - - $('#jsonMsg').css('color', '#bb0000').html(formatedErrMsg); - - if (lineNum >= 0) - { - editor.parentNode.setAttribute('data-line', lineNum); - Prism.highlightElement(editor); - editor.parentNode.scrollTo(0, (lineNum - 1) * 20); - } - } - catch(e2) - { - $('#jsonMsg').css('color', '#bb0000').html(errMsg); - } - } -}; - -var fixMissingComponents = function(existingPages) -{ - var doneCount = 0; - - function checkAllDone() - { - doneCount++; - - if (doneCount == 3) - { - getConfigFile(function(configContent) - { - //Initialize the editor - var editor = document.querySelector('#configJSON'); - - try - { - var config = JSON.parse(configContent); - - if (config.version) - { - lastConfigVersion = parseFloat(config.version); - } - - configContent = JSON.stringify(config, null, 2); - } - catch(e) {} //Ignore - - editor.textContent = configContent; - editor = bililiteRange.fancyText(editor, Prism.highlightElement, 50); - - // add the undo's - bililiteRange(editor).undo(0).data().autoindent = true; // init - - editor.addEventListener ('keydown', function(evt) - { - if (evt.keyCode === 9) // tab key - { - // now insert four non-breaking spaces for the tab key - var editor = evt.target; - var doc = editor.ownerDocument.defaultView; - var sel = doc.getSelection(); - var range = sel.getRangeAt(0); - - var tabNode = document.createTextNode("\t"); - range.insertNode(tabNode); - - range.setStartAfter(tabNode); - range.setEndAfter(tabNode); - sel.removeAllRanges(); - sel.addRange(range); - - evt.preventDefault(); // this will prevent us from tabbing out of the editor - } - // control z - else if ((evt.ctrlKey || evt.metaKey) && evt.which == 90) - { - bililiteRange.undo(evt); - } - // control y - else if ((evt.ctrlKey && evt.which == 89) || (evt.metaKey && evt.shiftKey && evt.which == 90)) - { - bililiteRange.redo(evt); - } - - $('#jsonMsg').html(' '); - }); - - $('#busyIndicator').hide(); - $('#createSpace').hide(); - $('#manageConfig').show(); - $('#cLibTabHeader').show(); - $('#cTempTabHeader').show(); - - fetchCustomLibs(); - setupUploadLibrary(); - }, showError); - } - }; - - function createPage(title, desc, callback) - { - if (existingPages[title]) - { - if (callback) - { - callback(existingPages[title], true); - } - else - { - checkAllDone(); - } - return; - } - - AP.request({ - type: 'POST', - url: '/rest/api/content', - contentType: 'application/json;charset=UTF-8', - data: JSON.stringify({ - space: { - key: 'DRAWIOCONFIG' - }, - title: title, - status: 'current', - type: 'page', - body: { - storage: { - value: desc, - representation: 'storage' - } - } - }), - success: function (resp) - { - var pageId = JSON.parse(resp).id; - restrictContentToAdmins(pageId); - - if (callback) - { - callback(pageId); - } - else - { - checkAllDone(); - } - }, - error: showError - }); - }; - - //Note: name shouldn't be translated as we search by page name - createPage('Configuration', mxResources.get('confAConfPageDesc'), function(pageId, pageExist) - { - configPageId = pageId; - createAttFile(pageId, CONFIG_FILENAME, 'application/json', '{}', checkAllDone, showError, pageExist); - }); - - createPage('Libraries', mxResources.get('confALibPageDesc'), function(pageId) - { - libsPageId = pageId; - checkAllDone(); - }); - - createPage('Templates', mxResources.get('confATempPageDesc'), function(pageId) - { - $('#tempPageLnk').attr('href', baseUrl + '/spaces/DRAWIOCONFIG/pages/' + pageId); - checkAllDone(); - }); -}; - -var createConfigSpace = function() -{ - $('#createSpace').html(' ' + mxResources.get('working') + '...'); - - AP.request({ - type: 'POST', - url: '/rest/api/space', - contentType: 'application/json;charset=UTF-8', - data: JSON.stringify({ - key: 'DRAWIOCONFIG', - name: 'draw.io Configuration', - description: { - plain: { - value: mxResources.get('confAConfSpaceDesc'), - representation: 'plain' - } - } - }), - success: function () - { - fixMissingComponents({}); - }, - error: showError - }); -}; - -function addLibRow(item) -{ - var libTable = $('#curLibs'); - - var tr = $(''); - libTable.append(tr); - var title = $(''); - tr.append(title); - title.text(item.title); - var action = $('') - tr.append(action); - var delBtn = $(''); - delBtn.click(function(e) - { - if (confirm("Are you sure?")) - { - AP.request({ - type: 'DELETE', - url: '/rest/api/content/' + item.id, - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - tr.remove(); - - if (libTable.find('td').length == 0) - { - $('
' + mxResources.get('confANoCustLib') + '
').insertAfter(libTable); - } - }, - error: function() - { - alert(mxResources.get('delFailed')); - } - }); - } - }); - action.append(delBtn); - - var idTd = $(''); - //This code is from RemoteLibrary. It's better to call that code but it is not available in this page - var libConfigId = 'R' + encodeURIComponent(JSON.stringify([item.id, item.title, item._links.download])); - var showConfigIDBtn = $(''); - showConfigIDBtn.click(function() - { - $('.libConfigID').show(); - $('.showIDBtn').hide(); - }); - - idTd.append(showConfigIDBtn); - idTd.append($('')); - tr.append(idTd); -}; - -function fetchCustomLibs() -{ - AP.request({ - type: 'GET', - url: '/rest/api/content/' + libsPageId + '/child/attachment', - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - resp = JSON.parse(resp); - - if (resp.results.length == 0) - { - $('
' + mxResources.get('confANoCustLib') + '
').insertAfter('#curLibs'); - } - else - { - for (var i = 0; i < resp.results.length; i++) - { - addLibRow(resp.results[i]); - } - } - }, - error: function() - { - - } - }); -}; - -function setupUploadLibrary() -{ - var uploadLib = document.getElementById('uploadLib'); - - uploadLib.addEventListener("click", function () - { - this.value = null; - }); - - uploadLib.addEventListener('change', function (e) { - var libFile = uploadLib.files[0]; - - if (libFile.type != 'text/xml') - { - $('#cLibMsg').css('color', '#bb0000').html(mxResources.get('confAIncorrectLibFileType')); - return; - } - - $('#cLibMsg').css('color', '#000000').html(' ' + mxResources.get('uploading') + '...'); - - reader = new FileReader(); - - reader.onload = function(event) - { - createAttFile(libsPageId, libFile.name, libFile.type, event.target.result, function(resp) - { - if (resp == true) - { - $('#cLibMsg').css('color', '#bb0000').html(mxResources.get('confALibExist')); - } - else - { - $('#noLibMsg').remove(); - addLibRow(JSON.parse(resp).results[0]); - $('#cLibMsg').css('color', '#00bb00').html(mxResources.get('confAUploadSucc')); - } - }, function() - { - $('#cLibMsg').css('color', '#bb0000').html(mxResources.get('confAUploadFailErr')); - }, true); - } - - reader.readAsText(libFile); - }, false); -}; - -function collectDrawAtts(success, error) -{ - var allTextPlainAtts = []; - var drawioAtts = []; - var pngAttMap = {}; - var start = 0, limit = 200; - var searchUrl = '/rest/api/content/search?cql=' + encodeURIComponent('type=attachment') + '&expand=metadata,container,version' - //Collect all attachments in the system and filter them into text/plain (old draw.io mime type) and png. - // Then, if a text/plain attachment has an associated png image, then most probably this is a draw.io diagram - function getChunck() - { - AP.request({ - type: 'GET', - url: searchUrl + '&start=' + start + '&limit=' + limit, - contentType: 'application/json;charset=UTF-8', - success: function(resp) { - var resp = JSON.parse(resp); - - for (var i = 0; i < resp.results.length; i++) - { - var att = resp.results[i]; - var mimeType = att.metadata.mediaType; - - if (mimeType == 'text/plain') - { - allTextPlainAtts.push(att); - } - else if (mimeType == 'image/png') - { - pngAttMap[att.container.id + '%' + att.title] = true; - } - } - - //Support pageing - if (resp._links && resp._links.next) - { - start += resp.limit; //Sometimes the limit is changed by the server - getChunck(); - } - else - { - for (var i = 0; i < allTextPlainAtts.length; i++) - { - var att = allTextPlainAtts[i]; - - if (pngAttMap[att.container.id + '%' + att.title + '.png']) - { - drawioAtts.push(att); - } - } - - success(drawioAtts); - } - }, - error: error - }); - }; - - getChunck(); -}; - -function processCustomContents(pagesList, srcToDstMap, custCntMap, impBaseUrl, index, allDone, logDiv) -{ - if (index >= pagesList.length) - { - allDone(); - return; - } - - var pageInfo = pagesList[index]; - var curPageId = pageInfo.id; - logDiv.append($('
' + mxResources.get('confAPrcsDiagInPage', [AC.htmlEntities(pageInfo.name)]) + '...
')); - - //No need for paging? - AP.request({ - type: 'GET', - url: '/rest/api/content/' + curPageId + '/child/ac:com.mxgraph.confluence.plugins.diagramly:drawio-diagram?expand=body.storage,version&limit=200', - contentType: 'application/json;charset=UTF-8', - success: function(custCnts) - { - var custCnts = JSON.parse(custCnts); - var ccIndex = 0; - - function checkDone() - { - ccIndex++; - - if (custCnts.size <= ccIndex) - { - logDiv.append($('
' + mxResources.get('confAPrcsDiagInPageDone', [AC.htmlEntities(pageInfo.name)]) + '
')); - processCustomContents(pagesList, srcToDstMap, custCntMap, impBaseUrl, ++index, allDone, logDiv); - } - }; - - if (custCnts.size == 0) - { - checkDone(); - } - - //build map by spaceKey and title -> id, version - for (var i = 0; i < custCnts.size; i++) - { - (function(custCnt) - { - var spaceKey = AC.getSpaceKey(custCnt._expandable? custCnt._expandable.space : ''); - - if (custCntMap[spaceKey] == null) - { - custCntMap[spaceKey] = {}; - } - - //Check custom content internal pageId and fix if needed - var info = JSON.parse(decodeURIComponent(custCnt.body.storage.value)); - - custCntMap[spaceKey][custCnt.title] = {id: custCnt.id, version: custCnt.version.number, revision: info.version}; - - if (curPageId != info.pageId) - { - logDiv.append($('
' + mxResources.get('confAImpDiagram', [AC.htmlEntities(custCnt.title)]) + '...
')); - var custCntObj = custCntMap[spaceKey][custCnt.title]; - info.name = info.diagramName; - info.pageId = curPageId; - info.revision = info.version; - - processDiagramLinks(info, srcToDstMap, spaceKey, impBaseUrl, function(resp) - { - if (resp != null) - { - try - { - info.version = JSON.parse(resp).results[0].version.number; - custCntObj.revision = info.version; - } - catch(e){} //ignore - } - - AC.saveCustomContent(spaceKey, curPageId, pageInfo.type, info.diagramName, custCnt.title, info.version, - custCnt.id, custCnt.version.number, - function(responseText) - { - var content = JSON.parse(responseText); - //Update info - custCntObj.id = content.id; - custCntObj.version = content.version.number; - logDiv.append($('
' + mxResources.get('confImpDiagramSuccess', [AC.htmlEntities(custCnt.title)]) + '
')); - checkDone(); - }, function() - { - logDiv.append($('
' + mxResources.get('confAUpdateDgrmCCFailed', [AC.htmlEntities(custCnt.title)]) + '
')); - checkDone(); - }, info.comments); - }, function() - { - logDiv.append($('
' + mxResources.get('confAImpDiagramError', [AC.htmlEntities(custCnt.title)]) + '
')); - checkDone(); - }, logDiv); - } - else - { - logDiv.append($('
' + mxResources.get('confAImpDiagramFailed', [AC.htmlEntities(custCnt.title)]) + '
')); - checkDone(); - } - })(custCnts.results[i], i); - } - }, - error: function() - { - logDiv.append($('
' + mxResources.get('confAErrPrcsDiagInPage', [AC.htmlEntities(pageInfo.name)]) + '
')); - processCustomContents(pagesList, srcToDstMap, custCntMap, impBaseUrl, ++index, allDone, logDiv); - } - }); -}; - -function processPageIdsImport(pagesList, srcToDstMap, custCntMap, drawioRegExps, incDrawioRegExps, impBaseUrl, index, allDone, logDiv) -{ - if (index >= pagesList.length) - { - allDone(); - return; - } - - var pageInfo = pagesList[index]; - var curPageId = pageInfo.id; - logDiv.append($('
' + mxResources.get('confAPrcsMacrosInPage', [AC.htmlEntities(pageInfo.name)]) + '...
')); - - function fixDrawIoMacros(pageId, pageType, spaceKey, params, macroId, success, error, skip) - { - //['diagramName', 'contentId', 'contentVer', 'revision', 'width', 'height', 'tempPreview', 'zoom', 'lbox', 'diagramDisplayName', 'tbstyle', 'links', 'simple', 'hiResPreview', 'inComment', 'aspect', 'pageId', 'baseUrl'] - //inc-drawio macro specific params - //'diagramUrl', 'includedDiagram', 'aspectHash', 'imgPageId', 'attVer', 'custContentId' - //'pCenter' - var attName = params[0]; - var contentId = params[1] || params[23]; - var contentVer = params[2]; - var revision = params[3]; - var width = params[4]; - var height = params[5]; - var tempPreview = params[6]; - var zoom = params[7]; - var lbox = params[8]; - var diagramDisplayName = params[9]; - var tbstyle = params[10]; - var links = params[11]; - var simple = params[12]; - var hiResPreview = params[13]; - var inComment = params[14]; - var aspect = params[15]; - var macroPageId = params[16]; - var macroBaseUrl = params[17]; - - var diagramUrl = params[18]; - var isInc = params[19] == '1'; - var aspectHash = params[20]; - var imgPageId = params[21]; - var attVer = params[22]; - var pCenter = params[24]; - logDiv.append($('
' + mxResources.get('confAFixingMacro', [AC.htmlEntities(attName)]) + '...
')); - - var macroCurPageId = srcToDstMap[macroPageId]; - var attInfo = { - pageId: macroCurPageId || pageId, - macroId: macroId, - name: attName, - contentId: contentId, - contentVer: contentVer, - revision: revision, - width: width, - height: height, - previewPng: tempPreview, - zoom: zoom, - lbox: lbox, - diagramDisplayName: diagramDisplayName || attName, - tbstyle: tbstyle, - links: links, - simple: simple, - hiResPreview: hiResPreview, - inComment: inComment, - aspect: aspect, - diagramUrl: diagramUrl, - isInc: isInc, - aspectHash: aspectHash, - imgPageId: imgPageId, - attVer: attVer, - pCenter: pCenter - }; - - //If the diagram points to another page, change macro type to inc-drawio - if (attInfo.pageId != pageId) - { - attInfo.isInc = true; - } - - //(macroPageId == null) when a server macro without a pageId is imported - if (macroPageId == null || (macroCurPageId != null && macroCurPageId != macroPageId)) - { - var custCntInfo = custCntMap[spaceKey]? custCntMap[spaceKey][attInfo.diagramDisplayName] : null; - - if (custCntInfo != null) - { - attInfo.contentId = custCntInfo.id; - attInfo.contentVer = custCntInfo.version; - attInfo.revision = custCntInfo.revision; - logDiv.append($('
' + mxResources.get('confImpDiagramSuccess', [AC.htmlEntities(attInfo.diagramDisplayName)]) + '
')); - success(attInfo); - } - else if (!attInfo.isInc) //Check links and Create a custom content - { - processDiagramLinks(attInfo, srcToDstMap, spaceKey, impBaseUrl, function(resp) - { - if (resp != null) - { - try - { - attInfo.revision = JSON.parse(resp).results[0].version.number; - } - catch(e){} //ignore - } - - AC.saveCustomContent(spaceKey, attInfo.pageId, pageInfo.type, attInfo.name, attInfo.diagramDisplayName, attInfo.revision, - null, null, - function(responseText) - { - var content = JSON.parse(responseText); - //Update info - attInfo.contentId = content.id; - attInfo.contentVer = content.version.number; - logDiv.append($('
' + mxResources.get('confImpDiagramSuccess', [AC.htmlEntities(attInfo.diagramDisplayName)]) + '
')); - success(attInfo); - }, function() - { - logDiv.append($('
' + mxResources.get('confAUpdateDgrmCCFailed', [AC.htmlEntities(attInfo.diagramDisplayName)]) + '
')); - success(attInfo); - }); - }, function() - { - logDiv.append($('
' + mxResources.get('confAImpDiagramError', [AC.htmlEntities(attInfo.diagramDisplayName)]) + '
')); - success(attInfo); - }, logDiv); - } - else - { - logDiv.append($('
' + mxResources.get('confImpDiagramSuccess', [AC.htmlEntities(attInfo.diagramDisplayName)]) + '
')); - success(attInfo); - } - } - else - { - //skip - logDiv.append($('
' + mxResources.get('confAFixingMacroSkipped', [AC.htmlEntities(attName)]) + '
')); - skip(attInfo); - } - }; - - function pageProcessed() - { - processPageIdsImport(pagesList, srcToDstMap, custCntMap, drawioRegExps, incDrawioRegExps, impBaseUrl, ++index, allDone, logDiv); - }; - - AP.request({ - type: 'GET', - url: '/rest/api/content/' + curPageId + '?expand=body.storage,version', - contentType: 'application/json;charset=UTF-8', - success: function(page) - { - var page = JSON.parse(page); - - replacePageMacro(page, drawioRegExps, fixDrawIoMacros, function(successfullyConverted1, macrosParsed1) - { - replacePageMacro(page, incDrawioRegExps, fixDrawIoMacros, function(successfullyConverted, macrosParsed) - { - successfullyConverted += successfullyConverted1; - macrosParsed += macrosParsed1; - - if (macrosParsed == 0) - { - logDiv.append($('
' + mxResources.get('confANoDiagFoundInPage', ['draw.io', AC.htmlEntities(page.title)]) + '
')); - } - if (successfullyConverted == macrosParsed) - { - logDiv.append($('
' + mxResources.get('confAAllDiagInPageDone', ['draw.io', AC.htmlEntities(page.title)]) + '
')); - } - else - { - logDiv.append($('
' + mxResources.get('confAPartialDiagDone', [successfullyConverted, macrosParsed, 'draw.io', AC.htmlEntities(page.title)]) + '
')); - } - - pageProcessed(); - }, function(resp) - { - logDiv.append($('
' + mxResources.get('confAUpdatePageFailed', [AC.htmlEntities(page.title)]) + '
')); - pageProcessed(); - }, true); - }, function(resp) - { - logDiv.append($('
' + mxResources.get('confAUpdatePageFailed', [AC.htmlEntities(page.title)]) + '
')); - pageProcessed(); - }, true); - }, - error: function() - { - logDiv.append($('
' + mxResources.get('confAErrFetchPage', [AC.htmlEntities(pageInfo.name)]) + '
')); - pageProcessed(); - } - }); -}; - -RegExp.escape = function(string) -{ - return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') -}; - -function updateGraphModelLinks(xmlDoc, srcToDstMap, spaceKey, srcBaseUrl, attInfo, logDiv) -{ - //TinyURL - // In Java: Base64.encodeBase64(longToByteArray(id)); - // https://community.atlassian.com/t5/Confluence-questions/What-is-the-algorithm-used-to-create-the-quot-Tiny-links-quot/qaq-p/186555 - // The long to byte array conversion is taken from this source: - // https://stackoverflow.com/questions/8482309/converting-javascript-integer-to-byte-array-and-back - function byteArrayToLong(byteArray) - { - var value = 0; - - for ( var i = byteArray.length - 1; i >= 0; i--) - { - value = (value * 256) + byteArray[i]; - } - - return value; - }; - - function shortUrlToPageId(shortUrl) - { - try - { - return byteArrayToLong(atob(shortUrl) - .split('') - .map(function (b) { return b.charCodeAt()})); - } - catch(e) - { - console.log('Failed to decode this short url: ', shortUrl, e); - return null; - } - }; - - var pageIdFullUrl = /\/pages\/viewpage\.action\?pageId=(\d+)/; - - var attachmentFullUrl = /\/download\/attachments\/(\d+)/; - - var tinyPageUrl = /\/x\/(\S+)/; - - var cloudPageUrl = /\/spaces\/\S+\/pages\/([^\/]+)/; - - var ceoLightboxUrl = /ceoId=(.*?)(?=&)/; - - function extractPageIdFromFullUrl(link) - { - var m = link.match(pageIdFullUrl); - - if (m != null) - { - return m[1]; - } - - var m = link.match(attachmentFullUrl); - - if (m != null) - { - return m[1]; - } - - return null; - }; - - function extractPageIdFromTinyUrl(link) - { - var m = link.match(tinyPageUrl); - - if (m != null) - { - var encoded = m[1]; - var pageId = shortUrlToPageId(encoded); - return pageId != null? String(pageId) : null; - } - return null; - }; - - function extractPageIdFromCloudUrl(link) - { - var m = link.match(cloudPageUrl); - - if (m != null) - { - return m[1]; - } - return null; - }; - - function getPageIdFromAnyUrl(url) - { - var pageId = null; - - try - { - pageId = extractPageIdFromFullUrl(url); - - if (pageId == null) - { - pageId = extractPageIdFromTinyUrl(url); - } - - if (pageId == null) - { - pageId = extractPageIdFromCloudUrl(url); - } - } - catch(e) - { - console.log('Failed to process url: ', url, e); - } - - return pageId; - }; - - function extractPageIdFromLightboxUrl(link) - { - var m = link.match(ceoLightboxUrl); - - if (m != null) - { - return m[1]; - } - - return null; - }; - - function fixLink(link) - { - var linkUpdated = false; - - if (link != null && link.length != 0) - { - var pmm = getPageIdFromAnyUrl(link); - - if (pmm != null) - { - var curPageId = srcToDstMap[pmm]; - - if (curPageId != null) - { - link = baseUrl + '/spaces/' + encodeURIComponent(spaceKey) + '/pages/' + curPageId; - logDiv.append($('
' + mxResources.get('confAUpdateLnkToPg', [AC.htmlEntities(curPageId), AC.htmlEntities(attInfo.name)]) + '
')); - linkUpdated = true; - } - } - else - { - //TODO Add support to lightbox links via custom contents. This requires saving the custom content first without a version - //[baseUrl]/plugins/servlet/ac/com.mxgraph.confluence.plugins.diagramly/customContentViewer?content.plugin=ac%3Acom.mxgraph.confluence.plugins.diagramly%3Adrawio-diagram&space.key=[spaceKey]&content.id=[contentId]&content.version=[contentVer]&content.type=custom - var lightboxPageId = extractPageIdFromLightboxUrl(link); - - if (lightboxPageId != null) - { - var curPageId = srcToDstMap[lightboxPageId]; - - if (curPageId != null) - { - link = link.replace(lightboxPageId, curPageId); - logDiv.append($('
' + mxResources.get('confAUpdateLBLnkToPg', [AC.htmlEntities(curPageId), AC.htmlEntities(attInfo.name)]) + '
')); - linkUpdated = true; - } - } - } - - if (link.indexOf(srcBaseUrl) >= 0) - { - link = link.replace(new RegExp(RegExp.escape(srcBaseUrl), 'g'), baseUrl); - logDiv.append($('
' + mxResources.get('confAUpdateLnkBase', [AC.htmlEntities(srcBaseUrl), AC.htmlEntities(baseUrl), AC.htmlEntities(attInfo.name)]) + '
')); - linkUpdated = true; - } - } - - return linkUpdated? link : null; - }; - - function fixText(text) - { - if (text == null) return null; - - var linkUpdated = false; - var parser = new DOMParser(); - var labelDoc = parser.parseFromString(text, 'text/html'); - - var els = labelDoc.getElementsByTagName('a'); - - for (var i = 0; i < els.length; i++) - { - var el = els[i]; - var href = null; - - try - { - href = fixLink(el.getAttribute('href')); - } - catch(e) - { - console.log(e); - } - - if (href != null) - { - el.setAttribute('href', href); - linkUpdated = true; - } - } - - return linkUpdated? labelDoc.body.innerHTML : null; - }; - - var graph = new Graph(); - var codec = new mxCodec(xmlDoc); - var model = graph.getModel(); - codec.decode(xmlDoc.documentElement, model); - - var linkUpdated = false; - - for (var cellId in model.cells) - { - var cell = model.cells[cellId]; - var value = model.getValue(cell); - - if (value != null) - { - if (mxUtils.isNode(value)) - { - var el = value; - var text = fixText(el.getAttribute('label')); - - if (text != null) - { - el.setAttribute('label', text); - linkUpdated = true; - } - - var link = null; - - try - { - link = fixLink(el.getAttribute('link')); - } - catch(e) - { - console.log(e); - } - - if (link != null) - { - el.setAttribute('link', link); - linkUpdated = true; - } - } - else if (typeof(value.toString) == 'function') - { - var text = fixText(value.toString()); - - if (text != null) - { - cell.setValue(text); - linkUpdated = true; - } - } - } - } - - if (linkUpdated) - { - var enc = new mxCodec(mxUtils.createXmlDocument()); - return enc.encode(model); - } - else - { - return null; - } -}; - -function processDiagramLinks(attInfo, srcToDstMap, spaceKey, impBaseUrl, callback, error, logDiv) -{ - //Used to keep the same attributes for the mxGraphModel - function copyAttributes(src, dst) - { - var attrs = src.attributes; - - for(var i = 0; attrs!= null && i < attrs.length; i++) - { - dst.setAttribute(attrs[i].name, attrs[i].value); - } - }; - - AP.request( - { - url: '/download/attachments/' + attInfo.pageId + '/' + encodeURIComponent(attInfo.name) + - (attInfo.revision != null ? '?version=' + attInfo.revision : ''), - success: function(xml) - { - try - { - var xmlDoc = mxUtils.parseXml(xml); - var xmlNode = xmlDoc.documentElement; - var fileChanged = false, fileXml = null; - - if (xmlNode.nodeName == 'mxfile') - { - var diagrams = xmlNode.getElementsByTagName('diagram'); - - for (var i = 0; i < diagrams.length; i++) - { - var xmlDoc = Editor.parseDiagramNode(diagrams[i]); - - if (xmlDoc != null) - { - xmlDoc = xmlDoc.ownerDocument; - } - - var newDiagram = updateGraphModelLinks(xmlDoc, srcToDstMap, spaceKey, impBaseUrl, attInfo, logDiv); - - if (newDiagram != null) - { - fileChanged = true; - copyAttributes(xmlDoc.documentElement, newDiagram); - EditorUi.removeChildNodes(diagrams[i]); - diagrams[i].appendChild(newDiagram); - } - } - - if (fileChanged) - { - fileXml = mxUtils.getXml(xmlNode); - } - } - else - { - var newDiagram = updateGraphModelLinks(xmlDoc, srcToDstMap, spaceKey, impBaseUrl, attInfo, logDiv); - - if (newDiagram != null) - { - fileChanged = true; - copyAttributes(xmlNode, newDiagram); - fileXml = mxUtils.getXml(newDiagram); - } - } - - if (fileChanged) - { - AC.saveDiagram(attInfo.pageId, attInfo.name, fileXml, callback, error, false, 'application/vnd.jgraph.mxfile', mxResources.get('drawDiag'), false, false); //We don't support draft pages - } - else - { - logDiv.append($('
' + mxResources.get('confANoLnksInDrgm', [AC.htmlEntities(attInfo.name)]) + '
')); - callback(); - } - } - catch(e) - { - error(); - console.log('Processing of diagram ' + attInfo.name + ' failed', e); - } - }, - error: error - }); -}; - -//TODO Import comments from server -//Page IDs import -function importPageIds(csvData, logDiv) -{ - $('#PIBusyIcon').show(); - logDiv.html('
'); - //Code from https://gist.github.com/Jezternz/c8e9fafc2c114e079829974e3764db75 and https://stackoverflow.com/questions/1293147/javascript-code-to-parse-csv-data - function csvStringToArray(strData) - { - var objPattern = new RegExp(("(\\,|\\r?\\n|\\r|^)(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|([^\\,\\r\\n]*))"), "gi"); - var arrMatches = null, arrData = [[]]; - - while (arrMatches = objPattern.exec(strData)) - { - if (arrMatches[1].length && arrMatches[1] !== ",") arrData.push([]); - - arrData[arrData.length - 1].push(arrMatches[2] ? - arrMatches[2].replace(new RegExp( "\"\"", "g" ), "\"") : - arrMatches[3]); - } - - return arrData; - }; - - function removeLastChar(str) - { - return str.substr(0, str.length -1); - }; - - try - { - var srcPageNamesMap = {}, srcToDstMap = {}; - var lines = csvStringToArray(csvData); - var fileType = removeLastChar(lines[0][0]); - var impBaseUrl = removeLastChar(lines[1][0]); - - if (impBaseUrl.indexOf('baseUrl=') == 0) - { - impBaseUrl = impBaseUrl.substr(8); - } - else - { - $('#PIBusyIcon').hide(); - logDiv.append($('
' + mxResources.get('confAInvalidPageIdsFormat') + '
')); - return; - } - - if (fileType == 'cloud' || fileType == 'server') - { - for (var i = 2; i < lines.length - 1; i++) - { - if (lines[i].length == 3) - { - var pageId = lines[i][0], - pageName = lines[i][1], - spaceKey = removeLastChar(lines[i][2]); - - if (srcPageNamesMap[spaceKey] == null) - { - srcPageNamesMap[spaceKey] = {}; - } - - srcPageNamesMap[spaceKey][pageName] = pageId; - } - else - { - logDiv.append($('
' + mxResources.get('confAInvalidPageIdsFormat') + '
')); - $('#PIBusyIcon').hide(); - return; - } - } - - var drawioRegExps = getMacroRegExps('drawio', drawioMacroParams); - var incDrawioRegExps = getMacroRegExps('inc-drawio', drawioMacroParams); - - logDiv.append($('
' + mxResources.get('confACollectingCurPages') + '...
')); - - collectAllPages(function(curPages) - { - logDiv.append($('
' + mxResources.get('confABuildingPagesMap') + '...
')); - var pages = []; - - for (var i = 0; i < curPages.length; i++) - { - if (srcPageNamesMap[curPages[i].spaceKey] != null) - { - var srcPageId = srcPageNamesMap[curPages[i].spaceKey][curPages[i].title]; - - if (srcPageId != null) - { - srcToDstMap[srcPageId] = curPages[i].id; - pages.push({id: curPages[i].id, type: curPages[i].type, name: curPages[i].title}); - } - } - } - - var custCntMap = {}; - - logDiv.append($('
' + mxResources.get('confAProcessDrawDiag') + '...
')); - //Fix custom contents first to build its ids map - processCustomContents(pages, srcToDstMap, custCntMap, impBaseUrl, 0, function() - { - logDiv.append($('
' + mxResources.get('confAProcessDrawDiagDone') + '
')); - logDiv.append($('
' + mxResources.get('confAProcessImpPages') + '
')); - - processPageIdsImport(pages, srcToDstMap, custCntMap, drawioRegExps, incDrawioRegExps, impBaseUrl, 0, function() - { - logDiv.append($('
' + mxResources.get('confAPageIdsImpDone') + '
')); - $('#PIBusyIcon').hide(); - }, logDiv); - }, logDiv); - }, function() - { - $('#PIBusyIcon').hide(); - logDiv.append($('
' + mxResources.get('confAErrFetchPageList') + '
')); - }); - } - else - { - $('#PIBusyIcon').hide(); - logDiv.append($('
' + mxResources.get('confAInvalidPageIdsFormat') + '
')); - } - } - catch (e) - { - $('#PIBusyIcon').hide(); - logDiv.append($('
' + mxResources.get('confAInvalidPageIdsFormat') + '
')); - } -}; - -var baseUrl = AC.getBaseUrl(); - -var script = document.createElement('script'); - -script.onload = function() -{ - AP.sizeToParent(true); - - setTimeout(function() - { - AP.sizeToParent(true); - }, 5000); //Try resizing again after 5 sec since the first one fails sometimes - - AP.request({ - type: 'GET', - url: '/rest/api/space?spaceKey=DRAWIOCONFIG', - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - if (resp.results.length > 0) - { - //Check all pages exists, automatically fix if a page/attachment doesn't exist - AP.request({ - type: 'GET', - url: '/rest/api/content/search?cql=type%3Dpage%20and%20space%3DDRAWIOCONFIG', - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - var configSpaceFoundComponents = {}; - - for (var i = 0; i < resp.results.length; i++) - { - var item = resp.results[i]; - restrictContentToAdmins(item.id); - configSpaceFoundComponents[item.title] = item.id; - } - - fixMissingComponents(configSpaceFoundComponents); - }, - error: showError - }); - } - else - { - $('#busyIndicator').hide(); - $('#createSpace').show(); - } - }, - error: showError - }); - - getAndApplyTranslation(function() - { - //JQuery is loaded in this page, so we can use it - var indexBtn = $('#indexBtn'); - - indexBtn.attr("disabled", null); - - indexBtn.click(function() - { - $('#DRIbusyIcon').show(); - DrawIoDiagramsIndexer($('#operationLog'), function() - { - $('#DRIbusyIcon').hide(); - }); - }); - - var exportBtn = $('#exportBtn'); - - exportBtn.attr("disabled", null); - - exportBtn.click(function() - { - exportPageIds($('#exportResult')); - }); - - var createConfig = $('#createConfSpaceBtn'); - - createConfig.attr("disabled", null); - - createConfig.click(createConfigSpace); - - $('#saveConfigBtn').click(checkConfigAndSave); - - var importBtn = $('#importBtn'); - importBtn.attr("disabled", null); - var uploadExpFileElt = null; - - importBtn.click(function() - { - if (uploadExpFileElt == null) - { - var input = document.createElement('input'); - input.setAttribute('type', 'file'); - - $(input).change(function() - { - if (input.files != null) - { - var file = input.files[0]; - var reader = new FileReader(); - - reader.onload = function(e) - { - importPageIds(e.target.result, $('#pageIdsImportLog')); - }; - - reader.onerror = function(e) - { - $('#idImportErrors').html(mxResources.get('confAErrReadingExpFile')); - }; - - reader.readAsText(file); - - // Resets input to force change event for same file (type reset required for IE) - input.type = ''; - input.type = 'file'; - input.value = ''; - } - }); - - input.style.display = 'none'; - document.body.appendChild(input); - uploadExpFileElt = input; - } - - uploadExpFileElt.click(); - }); - }); - - AJS.tabs.setup(); -}; - -script.src = 'https://connect-cdn.atl-paas.net/all.js'; -script.setAttribute('data-options', 'resize:false;margin:false'); -document.getElementsByTagName('head')[0].appendChild(script); diff --git a/src/main/webapp/connect/confluence/connect-dev.json b/src/main/webapp/connect/confluence/connect-dev.json deleted file mode 100644 index 6efd48f7..00000000 --- a/src/main/webapp/connect/confluence/connect-dev.json +++ /dev/null @@ -1,482 +0,0 @@ -{ - "name": "draw.io", - "description": "draw.io add-on for Confluence", - "key": "com.mxgraph.confluence.plugins.diagramly", - "baseUrl": "https://test.draw.io", - "enableLicensing": true, - "apiMigrations": { - "gdpr": true - }, - "vendor": - { - "name": "//SEIBERT/MEDIA", - "url": "https://www.seibert-media.net/" - }, - "links": { - "documentation": "https://support.draw.io/display/DFCC/draw.io+for+Confluence+Cloud" - }, - "version": "1.4.42", - "authentication": - { - "type": "none" - }, - "modules": - { - "adminPages": [ - { - "key": "gliffyImport", - "url": "/connect/confluence/admin.html", - "name": { - "value": "draw.io Gliffy Import", - "i18n": "gliffyImport" - } - }, - { - "key": "lucidImport", - "url": "/connect/confluence/lucidMassImport.html", - "name": { - "value": "draw.io Lucidchart Import", - "i18n": "lucidImport" - } - }, - { - "key": "drawioConfig", - "url": "/connect/confluence/config.html", - "name": { - "value": "draw.io Configuration", - "i18n": "drawConfig" - } - } - ], - "postInstallPage": { - "key": "postInstall", - "url": "/connect/confluence/support.html", - "name": { - "value": "Welcome to draw.io", - "i18n": "postinstall" - } - }, - "generalPages": [ - { - "key": "lightbox", - "location": "hidden", - "url": "/connect/confluence/viewer-1-4-42.html?lightbox=1", - "name": { - "value": "Lightbox", - "i18n": "lightbox" - } - }, - { - "key": "customContentViewer", - "location": "hidden", - "url": "/connect/confluence/viewer-1-4-42.html?custom=1&contentId={content.id}", - "name": { - "value": "draw.io Viewer", - "i18n": "drawViewer" - } - }, - { - "key": "customContentEditor", - "location": "hidden", - "url": "/connect/confluence/macroEditor-1-4-8.html?custom=1", - "name": { - "value": "draw.io Editor", - "i18n": "drawEditor" - } - }, - { - "key": "macroEditor", - "location": "hidden", - "url": "/connect/confluence/macroEditor-1-4-8.html", - "name": { - "value": "draw.io Editor", - "i18n": "drawEditor" - } - }, - { - "key": "splashEditor", - "location": "hidden", - "url": "/connect/confluence/splashEditor.html", - "name": { - "value": "draw.io Splash Editor", - "i18n": "drawSplashEditor" - } - }, - { - "key": "support", - "location": "system.help/pages", - "url": "/connect/confluence/support.html", - "name": { - "value": "draw.io Support", - "i18n": "support" - } - } - ], - "customContent": [{ - "key": "drawio-diagram", - "name": { - "value": "draw.io Diagrams", - "i18n": "drawDiagrams" - }, - "uiSupport": { - "contentViewComponent": { - "moduleKey": "customContentViewer" - }, - "icons": { - "item": { - "url": "/images/drawlogo48.png" - } - } - }, - "apiSupport": { - "supportedContainerTypes": ["page", "comment", "space", "blogpost"], - "supportedChildTypes": ["attachment"], - "indexing": { - "enabled": true - } - } - } - ], - "dynamicContentMacros": - [ - { - "name": - { - "i18n": "drawioMacro", - "value": "draw.io Diagram" - }, - "url": "/connect/confluence/viewer-1-4-42.html?ceoId=${page.id}&diagramName=${diagramName}&revision=${revision}&width=${width}&height=${height}&tbstyle=${tbstyle}&simple=${simple}&lbox=${lbox}&zoom=${zoom}&links=${links}&owningPageId=${pageId}&displayName=${diagramDisplayName}&contentId={contentId}&custContentId={custContentId}&contentVer={contentVer}&inComment={inComment}&aspect={aspect}&pCenter={pCenter}", - "width": "100%", - "description": - { - "i18n": "drawDesc", - "value": "Inserts a new draw.io diagram" - }, "icon": - { - "width": 128, - "height": 128, - "url": "/images/drawlogo128.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": true, - "key": "drawio", - "parameters": - [ - { - "identifier": "diagramName", - "name": - { - "value": "Diagram name (do not change)", - "i18n": "diagramName" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "autoSize", - "name": - { - "value": "automatic size", - "i18n": "automaticSize" - }, - "type": "boolean", - "defaultValue": "true" - }, - { - "identifier": "PageId", - "name": - { - "value": "Parent page ID", - "i18n": "pPageID" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "baseUrl", - "name": - { - "value": "Confluence Base URL", - "i18n": "baseUrl" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "width", - "name": - { - "value": "Diagram width", - "i18n": "dWidth" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Diagram height", - "i18n": "dHeight" - }, - "type": "string" - } - ], - "editor": { - "url": "/connect/confluence/initEditor.html?ceoId=${page.id}&diagramName=${diagramName}", - "width": "100%", - "height": "100%", - "editTitle": - { - "value" : "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" - }, - "insertTitle": - { - "value" : "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" - } - }, - "imagePlaceholder": { - "width": 500, - "height": 300, - "url": "/connectImage", - "applyChrome": true - }, - "renderModes": { - "default": { - "url": "/connectRender?pageId=${page.id}&diagramName=${diagramName}&tempPreview=${tempPreview}&width=${width}&height=${height}&zoom=${zoom}" - } - } - }, - { - "name": - { - "i18n": "incDrawioMacro", - "value": "Embed draw.io Diagram" - }, - "url": "/connect/confluence/viewer-1-4-42.html?linked=1&ceoId=${page.id}&imgPageId=${imgPageId}&diagramName=${diagramName}&revision=${revision}&width=${width}&height=${height}&tbstyle=${tbstyle}&simple=${simple}&lbox=${lbox}&zoom=${zoom}&links=${links}&owningPageId=${pageId}&displayName=${diagramDisplayName}&contentId=${contentId}&custContentId={custContentId}&contentVer=${contentVer}&diagramUrl=${diagramUrl}&csvFileUrl=${csvFileUrl}&aspect=${aspect}&aspectHash=${aspectHash}&attVer=${attVer}&service=${service}&sFileId=${sFileId}&odriveId=${odriveId}", - "width": "100%", - "description": - { - "i18n": "embedDesc", - "value": "Embed an existing draw.io diagram" - }, "icon": - { - "width": 128, - "height": 128, - "url": "/images/drawlogo128.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": true, - "key": "inc-drawio", - "parameters": - [ - { - "identifier": "diagramName", - "name": - { - "value": "Diagram name (do not change)", - "i18n": "diagramName" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "autoSize", - "name": - { - "value": "automatic size", - "i18n": "automaticSize" - }, - "type": "boolean", - "defaultValue": "true" - }, - { - "identifier": "PageId", - "name": - { - "value": "Parent page ID", - "i18n": "pPageID" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "baseUrl", - "name": - { - "value": "Confluence Base URL", - "i18n": "baseUrl" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "width", - "name": - { - "value": "Diagram width", - "i18n": "dWidth" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Diagram height", - "i18n": "dHeight" - }, - "type": "string" - } - ], - "editor": { - "url": "/connect/confluence/includeDiagram.html", - "width": "80%", - "height": "60%" - }, - "imagePlaceholder": { - "width": 500, - "height": 300, - "url": "/connectImage", - "applyChrome": true - }, - "renderModes": { - "default": { - "url": "/connectRender?pageId=${pageId}&imgPageId=${imgPageId}&diagramName=${diagramName}&tempPreview=${tempPreview}&width=${width}&height=${height}&zoom=${zoom}&aspectHash={aspectHash}" - } - } - }, - { - "name": - { - "i18n": "legacyDrawioMacro", - "value": "Legacy macro - do not use" - }, - "url": "/connect/confluence/viewer.html?ceoId=${page.id}&diagramName=${diagramName}&revision=${revision}&width=${width}&height=${height}", - "width": "100%", - "description": - { - "i18n": "legacyDesc", - "value": "Do not use" - }, "icon": - { - "width": 80, - "height": 80, - "url": "/images/stop-flat-icon-80.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": false, - "key": "drawio-macro", - "parameters": - [ - { - "identifier": "diagramName", - "name": - { - "value": "Diagram name (do not change)", - "i18n": "diagramName" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "autoSize", - "name": - { - "value": "automatic size", - "i18n": "automaticSize" - }, - "type": "boolean" - }, - { - "identifier": "PageId", - "name": - { - "value": "Parent page ID", - "i18n": "pPageID" - }, - "type": "string" - }, - { - "identifier": "baseUrl", - "name": - { - "value": "Confluence Base URL", - "i18n": "baseUrl" - }, - "type": "string" - }, - { - "identifier": "width", - "name": - { - "value": "Diagram width", - "i18n": "dWidth" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Diagram Height", - "i18n": "dHeight" - }, - "type": "string" - } - ], - "editor": { - "url": "/connect/confluence/macroEditor.html?ceoId=${page.id}&diagramName=${diagramName}", - "editTitle": { - "value": "Edit Markdown", - "i18n": "macro.md.edit" - }, - "insertTitle": { - "value": "Insert Markdown", - "i18n": "macro.md.insert" - }, - "width": "100%", - "height": "100%" - }, - "imagePlaceholder": { - "width": 500, - "height": 300, - "url": "/connectImage", - "applyChrome": true - }, - "renderModes": { - "default": { - "url": "/connectRender?pageId=${page.id}&diagramName=${diagramName}&revision=${revision}&tempPreview=${tempPreview}" - } - } - } - ] - }, - "scopes": [ - "read", - "write", - "delete" - ] -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/connect.json b/src/main/webapp/connect/confluence/connect.json deleted file mode 100644 index be839d59..00000000 --- a/src/main/webapp/connect/confluence/connect.json +++ /dev/null @@ -1,493 +0,0 @@ -{ - "name": "draw.io", - "description": "draw.io add-on for Confluence", - "key": "com.mxgraph.confluence.plugins.diagramly", - "baseUrl": "https://confluence.draw.io", - "enableLicensing": true, - "apiMigrations": { - "gdpr": true - }, - "vendor": - { - "name": "//SEIBERT/MEDIA", - "url": "https://www.seibert-media.net/" - }, - "links": { - "documentation": "https://support.draw.io/display/DFCC/draw.io+for+Confluence+Cloud" - }, - "version": "1.4.42", - "authentication": - { - "type": "none" - }, - "modules": - { - "adminPages": [ - { - "key": "gliffyImport", - "url": "/connect/confluence/admin.html", - "name": { - "value": "draw.io Gliffy Import", - "i18n": "gliffyImport" - } - }, - { - "key": "lucidImport", - "url": "/connect/confluence/lucidMassImport.html", - "name": { - "value": "draw.io Lucidchart Import", - "i18n": "lucidImport" - } - }, - { - "key": "drawioConfig", - "url": "/connect/confluence/config.html", - "name": { - "value": "draw.io Configuration", - "i18n": "drawConfig" - } - } - ], - "postInstallPage": { - "key": "postInstall", - "url": "/connect/confluence/support.html", - "name": { - "value": "Welcome to draw.io", - "i18n": "postinstall" - } - }, - "generalPages": [ - { - "key": "lightbox", - "location": "hidden", - "url": "/connect/confluence/viewer-1-4-42.html?lightbox=1", - "name": { - "value": "Lightbox", - "i18n": "lightbox" - } - }, - { - "key": "customContentViewer", - "location": "hidden", - "url": "/connect/confluence/viewer-1-4-42.html?custom=1&contentId={content.id}", - "name": { - "value": "draw.io Viewer", - "i18n": "drawViewer" - } - }, - { - "key": "customContentEditor", - "location": "hidden", - "url": "/connect/confluence/macroEditor-1-4-8.html?custom=1", - "name": { - "value": "draw.io Editor", - "i18n": "drawEditor" - } - }, - { - "key": "macroEditor", - "location": "hidden", - "url": "/connect/confluence/macroEditor-1-4-8.html", - "name": { - "value": "draw.io Editor", - "i18n": "drawEditor" - } - }, - { - "key": "splashEditor", - "location": "hidden", - "url": "/connect/confluence/splashEditor.html", - "name": { - "value": "draw.io Splash Editor", - "i18n": "drawSplashEditor" - } - }, - { - "key": "support", - "location": "system.help/pages", - "url": "/connect/confluence/support.html", - "name": { - "value": "draw.io Support", - "i18n": "support" - } - } - ], - "customContent": [{ - "key": "drawio-diagram", - "name": { - "value": "draw.io Diagrams", - "i18n": "drawDiagrams" - }, - "uiSupport": { - "contentViewComponent": { - "moduleKey": "customContentViewer" - }, - "icons": { - "item": { - "url": "/images/drawlogo48.png" - } - } - }, - "apiSupport": { - "supportedContainerTypes": ["page", "comment", "space", "blogpost"], - "supportedChildTypes": ["attachment"], - "indexing": { - "enabled": true - } - } - } - ], - "dynamicContentMacros": - [ - { - "name": - { - "i18n": "drawioMacro", - "value": "draw.io Diagram" - }, - "url": "/connect/confluence/viewer-1-4-42.html?ceoId=${page.id}&diagramName=${diagramName}&revision=${revision}&width=${width}&height=${height}&tbstyle=${tbstyle}&simple=${simple}&lbox=${lbox}&zoom=${zoom}&links=${links}&owningPageId=${pageId}&displayName=${diagramDisplayName}&contentId={contentId}&custContentId={custContentId}&contentVer={contentVer}&inComment={inComment}&aspect={aspect}&pCenter={pCenter}", - "width": "100%", - "description": - { - "i18n": "drawDesc", - "value": "Inserts a new draw.io diagram" - }, "icon": - { - "width": 128, - "height": 128, - "url": "/images/drawlogo128.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": true, - "key": "drawio", - "parameters": - [ - { - "identifier": "diagramName", - "name": - { - "value": "Diagram name (do not change)", - "i18n": "diagramName" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "autoSize", - "name": - { - "value": "automatic size", - "i18n": "automaticSize" - }, - "type": "boolean", - "defaultValue": "true" - }, - { - "identifier": "PageId", - "name": - { - "value": "Parent page ID", - "i18n": "pPageID" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "baseUrl", - "name": - { - "value": "Confluence Base URL", - "i18n": "baseUrl" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "width", - "name": - { - "value": "Diagram width", - "i18n": "dWidth" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Diagram height", - "i18n": "dHeight" - }, - "type": "string" - } - ], - "editor": { - "url": "/connect/confluence/initEditor.html?ceoId=${page.id}&diagramName=${diagramName}", - "width": "100%", - "height": "100%", - "editTitle": - { - "value" : "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" - }, - "insertTitle": - { - "value" : "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" - } - }, - "imagePlaceholder": { - "width": 500, - "height": 300, - "url": "/connectImage", - "applyChrome": true - }, - "renderModes": { - "default": { - "url": "/connectRender?pageId=${page.id}&diagramName=${diagramName}&tempPreview=${tempPreview}&width=${width}&height=${height}&zoom=${zoom}" - } - } - }, - { - "name": - { - "i18n": "incDrawioMacro", - "value": "Embed draw.io Diagram" - }, - "url": "/connect/confluence/viewer-1-4-42.html?linked=1&ceoId=${page.id}&imgPageId=${imgPageId}&diagramName=${diagramName}&revision=${revision}&width=${width}&height=${height}&tbstyle=${tbstyle}&simple=${simple}&lbox=${lbox}&zoom=${zoom}&links=${links}&owningPageId=${pageId}&displayName=${diagramDisplayName}&contentId=${contentId}&custContentId={custContentId}&contentVer=${contentVer}&diagramUrl=${diagramUrl}&csvFileUrl=${csvFileUrl}&aspect=${aspect}&aspectHash=${aspectHash}&attVer=${attVer}&service=${service}&sFileId=${sFileId}&odriveId=${odriveId}", - "width": "100%", - "description": - { - "i18n": "embedDesc", - "value": "Embed an existing draw.io diagram" - }, "icon": - { - "width": 128, - "height": 128, - "url": "/images/drawlogo128.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": true, - "key": "inc-drawio", - "parameters": - [ - { - "identifier": "diagramName", - "name": - { - "value": "Diagram name (do not change)", - "i18n": "diagramName" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "autoSize", - "name": - { - "value": "automatic size", - "i18n": "automaticSize" - }, - "type": "boolean", - "defaultValue": "true" - }, - { - "identifier": "PageId", - "name": - { - "value": "Parent page ID", - "i18n": "pPageID" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "baseUrl", - "name": - { - "value": "Confluence Base URL", - "i18n": "baseUrl" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "width", - "name": - { - "value": "Diagram width", - "i18n": "dWidth" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Diagram height", - "i18n": "dHeight" - }, - "type": "string" - } - ], - "editor": { - "url": "/connect/confluence/includeDiagram.html", - "width": "80%", - "height": "60%" - }, - "imagePlaceholder": { - "width": 500, - "height": 300, - "url": "/connectImage", - "applyChrome": true - }, - "renderModes": { - "default": { - "url": "/connectRender?pageId=${pageId}&imgPageId=${imgPageId}&diagramName=${diagramName}&tempPreview=${tempPreview}&width=${width}&height=${height}&zoom=${zoom}&aspectHash={aspectHash}" - } - } - }, - { - "name": - { - "i18n": "legacyDrawioMacro", - "value": "Legacy macro - do not use" - }, - "url": "/connect/confluence/viewer.html?ceoId=${page.id}&diagramName=${diagramName}&revision=${revision}&width=${width}&height=${height}", - "width": "100%", - "description": - { - "i18n": "legacyDesc", - "value": "Do not use" - }, "icon": - { - "width": 80, - "height": 80, - "url": "/images/stop-flat-icon-80.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": false, - "key": "drawio-macro", - "parameters": - [ - { - "identifier": "diagramName", - "name": - { - "value": "Diagram name (do not change)", - "i18n": "diagramName" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "autoSize", - "name": - { - "value": "automatic size", - "i18n": "automaticSize" - }, - "type": "boolean" - }, - { - "identifier": "PageId", - "name": - { - "value": "Parent page ID", - "i18n": "pPageID" - }, - "type": "string" - }, - { - "identifier": "baseUrl", - "name": - { - "value": "Confluence Base URL", - "i18n": "baseUrl" - }, - "type": "string" - }, - { - "identifier": "width", - "name": - { - "value": "Diagram width", - "i18n": "dWidth" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Diagram Height", - "i18n": "dHeight" - }, - "type": "string" - } - ], - "editor": { - "url": "/connect/confluence/macroEditor.html?ceoId=${page.id}&diagramName=${diagramName}", - "editTitle": { - "value": "Edit Markdown", - "i18n": "macro.md.edit" - }, - "insertTitle": { - "value": "Insert Markdown", - "i18n": "macro.md.insert" - }, - "width": "100%", - "height": "100%" - }, - "imagePlaceholder": { - "width": 500, - "height": 300, - "url": "/connectImage", - "applyChrome": true - }, - "renderModes": { - "default": { - "url": "/connectRender?pageId=${page.id}&diagramName=${diagramName}&revision=${revision}&tempPreview=${tempPreview}" - } - } - } - ] - }, - "scopes": [ - "read", - "write", - "delete" - ], - "translations": { - "paths": { - "en-US": "/connect/confluence/i18n/en.json", - "fr-FR": "/connect/confluence/i18n/fr_FR.json", - "de-DE": "/connect/confluence/i18n/de_DE.json", - "ja-JP": "/connect/confluence/i18n/ja_JP.json", - "ko-KR": "/connect/confluence/i18n/ko_KR.json", - "es-ES": "/connect/confluence/i18n/es_ES.json", - "ru-RU": "/connect/confluence/i18n/ru_RU.json" - } - } -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/connectUtils-1-4-8.js b/src/main/webapp/connect/confluence/connectUtils-1-4-8.js deleted file mode 100644 index c2a4742f..00000000 --- a/src/main/webapp/connect/confluence/connectUtils-1-4-8.js +++ /dev/null @@ -1,3477 +0,0 @@ -// Sets base path for mxgraph library -if (typeof window.mxBasePath === 'undefined') -{ - window.mxBasePath = '/mxgraph'; -} - -// Sets absolute path for proxy -window.PROXY_URL = window.PROXY_URL || '/proxy'; - -// Renamed from ac.js. This is the version used for release 1.4.8-AC onwards -var AC = {}; - -AC.autosaveTimeout = 10000; -AC.draftExtension = '.tmp'; -AC.draftPrefix = '~'; -AC.timeout = 25000; - -//Allow saving multiple times -AC.autoExit = true; - -// Last Checked on 08-AUG-2017: No delete scope needed to delete drafts -// LATER: If delete scope is needed users must upgrade to the latest json -// Disabled. Flag to mute notifications for drafts is needed. 16-AUG-2017 -AC.draftEnabled = true; //Enabled with the new save that mute notifications for saving TODO is there notification for deleting a draft? - -AC.customContentEditMode = false; - -AC.findMacrosRegEx = new RegExp('\\]+?(?=ac\\:name\\=)ac\\:name\\=\\"drawio\\".*?(?=\\<\\/ac\\:structured\\-macro\\>)', 'g'); - -AC.VERSION = '1.4.8'; //TODO Get the version - -AC.logError = function(message, url, linenumber, colno, err, severity) -{ - try - { - if (message == AC.lastErrorMessage || (message != null && url != null && - ((message.indexOf('Script error') != -1) || (message.indexOf('extension') != -1)))) - { - // TODO log external domain script failure "Script error." is - // reported when the error occurs in a script that is hosted - // on a domain other than the domain of the current page - } - // DocumentClosedError seems to be an FF bug an can be ignored for now - else if (message != null && message.indexOf('DocumentClosedError') < 0) - { - AC.lastErrorMessage = message; - severity = ((severity != null) ? severity : (message.indexOf('NetworkError') >= 0 || - message.indexOf('SecurityError') >= 0 || message.indexOf('NS_ERROR_FAILURE') >= 0 || - message.indexOf('out of memory') >= 0) ? 'CONFIG' : 'SEVERE'); - err = (err != null) ? err : new Error(message); - - var img = new Image(); - img.src = 'https://log.draw.io/log?severity=' + severity + '&v=' + encodeURIComponent(AC.VERSION) + - '&msg=clientError:' + encodeURIComponent(message) + ':url:' + encodeURIComponent(window.location.href) + - ':lnum:' + encodeURIComponent(linenumber) + ((colno != null) ? ':colno:' + encodeURIComponent(colno) : '') + - ((err != null && err.stack != null) ? '&stack=' + encodeURIComponent(err.stack) : ''); - } - } - catch (err) - { - // do nothing - } -}; - -(function() { - AC.macroParams = ["diagramName", "diagramDisplayName", "revision", "pageId", "contentId", "contentVer", "baseUrl", "width", "height", "tbstyle", "links", "simple", "lbox", "zoom", "hiResPreview", "inComment", "aspect", "custContentId", "pCenter"]; - AC.findMacroParamRegEx = {}; - - for (var i = 0; i < AC.macroParams.length; i++) - { - AC.findMacroParamRegEx[AC.macroParams[i]] = new RegExp('\\([^\\<]+)'); - } -})(); - -AC.getUrlParam = function(param, escape, url){ - try{ - var url = url || window.location.search; - var regex = new RegExp(param + '=([^&]+)'), - data = regex.exec(url)[1]; - // decode URI with plus sign fix. - return (escape) ? window.decodeURIComponent(data.replace(/\+/g, '%20')) : data; - } catch (e){ - return undefined; - } -}; - -AC.getSpaceKey = function(url) -{ - try{ - var url = url || window.location.href; - var regex = new RegExp(/\/(spaces|space)\/([^\/]+)/); - return decodeURIComponent(regex.exec(url)[2]); - } catch (e){ - return undefined; - } -}; - -AC.getMetaTag = function(name) { - return document.getElementsByTagName('meta')[name].getAttribute('content'); -} - -AC.getBaseUrl = function() -{ - var baseUrl = AC.getUrlParam('xdm_e', true) + AC.getUrlParam('cp', true); - //Ensure baseUrl belongs to attlasian (*.jira.com and *.atlassian.net) - //Since we add cp to xdm_e, we had to ensure that there is a slash after the domain. Since if xdm_e is ok, cp can corrupt is such as cp = '.fakedomain.com' such that baseUrl is atlassian.net.fakedomain.com - if (/^https:\/\/([^\.])+\.jira\.com\//.test(baseUrl + '/') || /^https:\/\/([^\.])+\.atlassian\.net\//.test(baseUrl + '/')) - { - return baseUrl; - } - throw 'Invalid baseUrl!'; -}; - -AC.getSiteUrl = function() -{ - var siteUrl = AC.getUrlParam('xdm_e', true); - //Ensure siteUrl belongs to attlasian (*.jira.com and *.atlassian.net) - if (/^https:\/\/([^\.])+\.jira\.com$/.test(siteUrl) || /^https:\/\/([^\.])+\.atlassian\.net$/.test(siteUrl)) - { - return siteUrl; - } - throw 'Invalid siteUrl!'; -}; - -//Code from: https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript -AC.b64toBlob = function(b64Data, contentType, sliceSize, isByteCharacters) -{ - contentType = contentType || ''; - sliceSize = sliceSize || 512; - - var byteCharacters = isByteCharacters? b64Data : atob(b64Data); - var byteArrays = []; - - for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { - var slice = byteCharacters.slice(offset, offset + sliceSize); - - var byteNumbers = new Array(slice.length); - for (var i = 0; i < slice.length; i++) { - byteNumbers[i] = slice.charCodeAt(i); - } - - var byteArray = new Uint8Array(byteNumbers); - - byteArrays.push(byteArray); - } - - var blob = new Blob(byteArrays, {type: contentType}); - return blob; -}; - -//We need language translation for error messages mainly which are not needed immediately -AC.initI18nAsync = function(lang, callback) -{ - RESOURCE_BASE = '/resources/dia'; - - //define mxResources such that it is available until code is loaded - mxResources = { - get: function(key, params, def) - { - return (def || '').replace('{1}', params? (params[0] || '') : ''); //Simple replacement which covers most cases - } - }; - - var script = document.createElement('script'); - - script.onload = function() - { - mxResources.loadDefaultBundle = false; - var bundle = mxResources.getDefaultBundle(RESOURCE_BASE, lang) || - mxResources.getSpecialBundle(RESOURCE_BASE, lang); - - mxUtils.getAll([bundle], function(xhr) - { - // Adds bundle text to resources - mxResources.parse(xhr[0].getText()); - - if (callback) - { - callback(); - } - }); - }; - - script.src = '/js/viewer-static.min.js'; - document.getElementsByTagName('head')[0].appendChild(script); -}; - -//AP.flag has a bug and stopped working, we'll use alert until it is fixed -// https://ecosystem.atlassian.net/browse/ACJS-1052 -AC.showNotification = function(notifConfig) -{ - AP.flag.create(notifConfig); - alert(notifConfig.title + ': ' + notifConfig.body); -}; - -AC.initAsync = function(baseUrl, contentId, initMacroData, config, lang) -{ - AC.customContentEditMode = contentId != null; - var contentVer = initMacroData != null? initMacroData.contentVer : null; - - var link = document.createElement('a'); - link.href = location.href; - link.href = link.href; //to have 'host' populated under IE - var hostUrl = link.protocol + '//' + link.hostname; - var site = AC.getSiteUrl(); - var user = null; - - AP.user.getCurrentUser(function(atlUser) - { - user = atlUser.atlassianAccountId; - }); - - if (lang != null) - { - var dash = lang.indexOf('_'); - - if (dash >= 0) - { - lang = lang.substring(0, dash); - } - - AC.initI18nAsync(lang); - } - - var ui = 'atlas'; - var plugins = 'ac148;ac148cmnt'; - - try - { - var configObj = (config != null) ? JSON.parse(config) : null; - - if (configObj != null) - { - // Adds support for ui theme - if (configObj.ui != null) - { - ui = configObj.ui; - } - - // Redirects plugins to p URL parameter - if (configObj.plugins != null) - { - plugins = plugins + ';' + configObj.plugins; - } - - AC.hiResPreview = configObj.hiResPreview || false; - } - } - catch (e) - { - console.log('Configuration error', e); - } - - var editor = document.createElement('iframe'); - editor.setAttribute('width', '100%'); - editor.setAttribute('height', '100%'); - editor.style.width = '100%'; - editor.style.height = '100%'; - editor.setAttribute('id', 'editorFrame'); - editor.setAttribute('frameborder', '0'); - //editor.setAttribute('src', hostUrl + '/?dev=1&' + - editor.setAttribute('src', hostUrl + '/?' + - 'ui=' + ui + '&p=' + plugins + '&embed=1&modified=unsavedChanges' + - ((AC.autoExit) ? '&noSaveBtn=1' : '&saveAndExit=1') + - '&keepmodified=1&spin=1&libraries=1&confLib=1&proto=json' + - ((lang != null) ? '&lang=' + lang : '') + ((site != null) ? '&site=' + encodeURIComponent(site) : '') + - ((user != null) ? '&user=' + encodeURIComponent(user) : '')); - - var initReceived = false; - var draftHandled = false; - var waitingForAttachments = false; - var xmlReceived = null; - var draftXml = null; - var draftName = null; - var filename = null; - var theMacroData = null; - var pageId = null; - var draftPage = false; - var theLocation = null; - var attachments = null; - - var serverName = AC.getSiteUrl(); - var index1 = serverName.indexOf('//'); - - if (index1 > 0) - { - var index2 = serverName.indexOf('/', index1 + 2); - - if (index2 > index1) - { - serverName = serverName.substring(index1 + 2, index2); - } - else - { - serverName = serverName.substring(index1 + 2); - } - } - - function startEditor() - { - if (initReceived && xmlReceived != null && draftHandled && !waitingForAttachments) - { - AC.init(baseUrl, theLocation, pageId, editor, filename, xmlReceived, draftName, draftXml, theMacroData, draftPage); - } - }; - - function loadDraft() - { - if (waitingForAttachments) - { - return; - } - - if (AC.draftEnabled && pageId != null && attachments != null && - (draftName != null || xmlReceived == '') && !draftHandled) - { - // Searches for pending new drafts from this user - var prefix = '~drawio~' + user + '~'; - - // Check if attachments contains draftName - for (var i = 0; i < attachments.length; i++) - { - var fn = attachments[i].title; - - if (draftName == null && attachments[i].fileSize > 0 && - fn.substring(0, prefix.length) === prefix && - fn.substring(fn.length - AC.draftExtension.length) === AC.draftExtension) - { - filename = fn.substring(prefix.length, fn.length - AC.draftExtension.length); - draftName = fn; - } - - if (fn == draftName) - { - //keeping the block of AP.require to minimize the number of changes! - { - var acceptResponse = true; - var timeoutHandler = function() - { - acceptResponse = false; - document.body.style.backgroundSize = 'auto auto'; - document.body.style.backgroundImage = 'url(/images/stop-flat-icon-80.png)'; - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', show: false}), '*'); - - AC.showNotification({ - title: mxResources.get('confTimeout'), - body: mxResources.get('confSrvTakeTooLong', [serverName]), - type: 'error', - close: 'manual' - }); - - //TODO find how to listen to flag close event, currently just close the editor immediately -// messages.onClose(message, function() -// { - AP.dialog.close(); -// }); - }; - - var timeoutThread = window.setTimeout(timeoutHandler, AC.timeout); - - AC.loadDiagram(pageId, draftName, null, function(loadResp) - { - //console.trace('DRAFT: Found', draftName, loadResp); - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - if (loadResp != null && loadResp.length > 0) - { - draftXml = loadResp; - } - - draftHandled = true; - startEditor(); - } - }, function() - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - draftHandled = true; - startEditor(); - } - }); - }; - - // Terminates function - return; - } - } - } - - draftHandled = true; - startEditor(); - }; - - var initHandler = function(evt) - { - if (evt.origin == hostUrl) - { - var msg = JSON.parse(evt.data); - - if (msg.event == 'configure') - { - // Configure must be sent even if JSON invalid - var configObj = {compressXml: false}; - - try - { - configObj = JSON.parse(config); - - // Overrides default - if (configObj != null && configObj.compressXml == null) - { - configObj.compressXml = false; - } - } - catch (e) - { - // ignore - } - - editor.contentWindow.postMessage(JSON.stringify({action: 'configure', - config: configObj}), '*'); - } - else if (msg.event == 'init') - { - window.removeEventListener('message', initHandler); - document.body.style.backgroundImage = 'none'; - initReceived = true; - startEditor(); - } - } - }; - - window.addEventListener('message', initHandler); - - AP.getLocation(function(location) - { - theLocation = location; - - var infoReady = function(data, macroData_p) - { - if (pageId == null || isNaN(pageId)) - { - document.body.style.backgroundImage = 'url(/images/stop-flat-icon-80.png)'; - document.body.style.backgroundSize = 'auto auto'; - - if (data != null && data.target == 'contentcreate') - { - AC.showNotification({ - title: mxResources.get('confCannotInsertNew'), - body: mxResources.get('confSaveTry'), - type: 'error', - close: 'manual' - }); - } - else - { - AC.showNotification({ - title: mxResources.get('confCannotGetID'), - body: mxResources.get('confContactAdmin'), - type: 'error', - close: 'manual' - }); - } - - //TODO find how to listen to flag close event, currently just close the editor immediately -// messages.onClose(message, function() -// { - AP.dialog.close(); -// }); - } - else - { - // Workaround for blocked referrer policy in iframe - editor.setAttribute('src', editor.getAttribute('src') + '&base=' + - encodeURIComponent(baseUrl + '/pages/viewpage.action?pageId=' + pageId) + - //adding config here to be the last in the url - (config != null? '&configure=1' : '')); - document.body.appendChild(editor); - - // Not needed if drafts not enabled - if (AC.draftEnabled) - { - waitingForAttachments = true; - var acceptResponse2 = true; - var timeoutHandler2 = function() - { - acceptResponse2 = false; - document.body.style.backgroundSize = 'auto auto'; - document.body.style.backgroundImage = 'url(/images/stop-flat-icon-80.png)'; - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', show: false}), '*'); - - AC.showNotification({ - title: mxResources.get('confTimeout'), - body: mxResources.get('confSrvTakeTooLong', [serverName]), - type: 'error', - close: 'manual' - }); - - //TODO find how to listen to flag close event, currently just close the editor immediately -// messages.onClose(message, function() -// { - AP.dialog.close(); -// }); - }; - - var timeoutThread2 = window.setTimeout(timeoutHandler2, AC.timeout); - - //TODO do a search instead if possible - AC.getPageAttachments(pageId, function(atts) - { - window.clearTimeout(timeoutThread2); - - if (acceptResponse2) - { - waitingForAttachments = false; - attachments = atts; - loadDraft(); - } - }, function(res) - { - window.clearTimeout(timeoutThread2); - - if (acceptResponse2) - { - waitingForAttachments = false; - draftHandled = true; - } - }); - } - - var acceptResponse = true; - var timeoutHandler = function() - { - acceptResponse = false; - document.body.style.backgroundSize = 'auto auto'; - document.body.style.backgroundImage = 'url(/images/stop-flat-icon-80.png)'; - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', show: false}), '*'); - - AC.showNotification({ - title: mxResources.get('confTimeout'), - body: mxResources.get('confSrvTakeTooLong', [serverName]), - type: 'error', - close: 'manual' - }); - - //TODO find how to listen to flag close event, currently just close the editor immediately -// messages.onClose(message, function() -// { - AP.dialog.close(); -// }); - }; - - var timeoutThread = window.setTimeout(timeoutHandler, AC.timeout); - - AP.confluence.getMacroData(function (macroData) - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - var name = null, revision, owningPageId; - - if (AC.customContentEditMode) - { - name = macroData_p.diagramName; - revision = macroData_p.revision; - owningPageId = pageId; - - //fill the macro data - theMacroData = macroData_p; - } - else if (macroData != null) - { - theMacroData = macroData; - name = macroData.diagramName || ''; - revision = parseInt(macroData.revision); - owningPageId = macroData.pageId; - } - - if (name != null && name.length > 0) - { - draftName = (name != null) ? AC.draftPrefix + name + AC.draftExtension : null; - loadDraft(); - - if (isNaN(revision)) - { - revision = null; - } - - timeoutThread = window.setTimeout(timeoutHandler, AC.timeout); - - AC.loadDiagram(pageId, name, revision, function(loadResp, curPageId, curDiagName) - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - //Get current diagram information which is needed for comments - AC.getAttachmentInfo(curPageId, curDiagName, function(info) - { - AC.curDiagVer = info.version.number; - AC.curDiagId = info.id; - }, function() - { - AC.curDiagId = false; - }); - - xmlReceived = loadResp; - filename = name; - //console.trace('DRAFT: Created', AC.draftPrefix + filename + AC.draftExtension); - startEditor(); - } - }, - function(resp) - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - editor.parentNode.removeChild(editor); - - AC.showNotification({ - title: mxResources.get('readErr'), - body: (resp.status == 404) ? - mxResources.get('fileNotFound') : mxResources.get('errorLoadingFile'), - type: 'error', - close: 'manual' - }); - - //TODO find how to listen to flag close event, currently just close the editor immediately -// messages.onClose(message, function() -// { - AP.dialog.close(); -// }); - } - }, owningPageId, true); - } - else - { - filename = null; - xmlReceived = ''; - loadDraft(); - } - } - }); - } - }; - - var extEditingError = function() - { - AC.showNotification({ - title: mxResources.get('editingErr'), - body: mxResources.get('confExtEditNotPossible'), - type: 'error', - close: 'manual' - }); - - AP.dialog.close({noBack: true}); - }; - - //keeping the block of AP.require to minimize the number of changes! - { - AP.navigator.getLocation(function (data) - { - AC.inComment = (data != null && data.context != null && data.context.contentType == 'comment'); - - if (AC.customContentEditMode) //we can also find the contentId in data.target == 'addonmodule' and data.context.context["content.id"][0] - { - //load the custom content to get the page info - AP.request({ - type: 'GET', - url: '/rest/api/content/' + contentId + '/?expand=body.storage,version' + (contentVer != null? ('&version=' + contentVer) : ''), - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - var info = JSON.parse(decodeURIComponent(resp.body.storage.value)); - - pageId = info.pageId; - info.displayName = resp.title; - info.contentVer = resp.version.number; - - //Out of sync custom content. This happen when a page is moved/copied - if (initMacroData != null && - ((initMacroData.pageId != null && initMacroData.pageId != pageId) - || (initMacroData.diagramName != null && initMacroData.diagramName != info.diagramName) - || (initMacroData.diagramDisplayName != null && initMacroData.diagramDisplayName != info.displayName) - || (initMacroData.revision != null && initMacroData.revision != info.version))) - { - pageId = initMacroData.pageId; - - info.createCustomContent = true; - } - - AC.findMacroInPage(pageId, info.diagramName, info.version, function(macroFound, originalBody, matchingMacros, page) - { - if (macroFound) - { - if (info.createCustomContent) - { - info.diagramName = initMacroData.diagramName; - info.displayName = initMacroData.diagramDisplayName; - info.version = initMacroData.revision || 1; //using version one when null is received which is usually the case - - //Create a new custom content and update the macro - var spaceKey = AC.getSpaceKey(page._expandable.space); - var pageType = page.type; - - AC.saveCustomContent(spaceKey, pageId, pageType, info.diagramName, info.displayName, info.version, - null, null, - function(responseText) - { - var content = JSON.parse(responseText); - - contentId = content.id; - info.contentVer = content.version? content.version.number : 1; - contentVer = info.contentVer; - - AC.adjustMacroParametersDirect(pageId, - {pageId: pageId, revision: info.version, contentId: content.id, custContentId: content.id, contentVer: contentVer}, - originalBody, matchingMacros, page, function() - { - infoReady(null, matchingMacros[0].macroParams); - }, extEditingError); - }, extEditingError); - } - else - { - infoReady(null, matchingMacros[0].macroParams); - } - } - else //A published page that has a draft content containing the diagram OR the diagram is deleted from the page OR diagram is edited and page is old! - { - var directPageEdit = contentVer != null; - - if (directPageEdit) - { - //We added translation since sometimes resources doesn't load quickly for this error - AC.showNotification({ - title: mxResources.get('confEditedExt', null, 'Diagram/Page edited externally'), - body: mxResources.get('confEditedExtRefresh', null, 'Diagram/Page is edited externally. Please refresh the page.'), - type: 'error', - close: 'manual' - }); - AP.dialog.close({noBack: true, noBackOnClose: directPageEdit}); - } - else //If this is edit of a custom content, we allow editing since it can be a stranded diagram (only exists as an attachment and custom contents BUT not as a macro) - { - //We added translation since sometimes resources doesn't load quickly for this error - AC.showNotification({ - title: mxResources.get('macroNotFound', null, 'Macro Not Found'), - body: mxResources.get('confEditDraftDelOrExt', null, 'This diagram is in a draft page, is deleted from the page, or is edited externally. ' + - 'It will be saved as a new attachment version and may not be reflected in the page.'), - type: 'warning', - close: 'manual' - }); - AC.strandedMode = true; - //Add required info that is usually found in the macro - info.contentId = contentId; - info.custContentId = contentId; - info.revision = info.version; - info.diagramDisplayName = info.displayName; - infoReady(null, info); - } - } - }, function() //On error, it means the page is a newly created draft that is not published - { - AC.showNotification({ - title: mxResources.get('diagNotFound'), - body: mxResources.get('confDiagNotPublished'), - type: 'error', - close: 'manual', - actions: { - 'actionkey': mxResources.get('retBack') - } - }); - - AP.dialog.close({noBack: true}); - }); - }, - error: extEditingError //We can create the custom content and fix this case but it adds more complexity to rare situation (e.g., a page is copied then the source page is deleted) - }); - } - else if (data != null && data.context != null - && (data.target == 'contentedit' || data.target == 'contentcreate' || AC.inComment)) - { - draftPage = (data.target == 'contentcreate'); - pageId = data.context.contentId; - infoReady(data); - } - else - { - infoReady(); - } - }); - }; - }); -}; - - -AC.getPageAttachments = function(pageId, success, error) -{ - var attachments = []; - - function getAttsChunk(start) - { - AP.request({ - url: '/rest/api/content/' + pageId + '/child/attachment?limit=100&start=' + start, - type: 'GET', - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - resp = JSON.parse(resp); - Array.prototype.push.apply(attachments, resp.results); - - //Support paging - if (resp._links && resp._links.next) - { - start += resp.limit; //Sometimes the limit is changed by the server - getAttsChunk(start); - } - else - { - success(attachments); - } - }, - error : error - }); - }; - - getAttsChunk(0); -}; - -AC.searchDiagrams = function(searchStr, success, error) -{ - //Note: we manually filter trashed diagrams as we couldn't make cqlcontext={"contentStatuses":["current"]} work - AP.request({ - url: '/rest/api/content/search?cql=' + encodeURIComponent('type="ac:com.mxgraph.confluence.plugins.diagramly:drawio-diagram" and title ~ "*' + searchStr + '*"') + '&limit=50&expand=body.storage,version', - success: function(resp) - { - resp = JSON.parse(resp); - var retList = []; - var gliffyList = []; - var list = resp.results; - var customContentMap = {}; - if (list) - { - //Add items in the list and convert the list to map so we can search by name efficiently - for (var i = 0; i < list.length; i++) - { - if (list[i].status == 'trashed') continue; - - try - { - var attInfo = JSON.parse(decodeURIComponent(list[i]["body"]["storage"]["value"])); - - customContentMap[attInfo.pageId + '|' + attInfo.diagramName] = true; - - retList.push({ - title: list[i].title, - url: "/download/attachments/" + attInfo.pageId + "/" - + encodeURIComponent(attInfo.diagramName) - + '?version=' + attInfo.version, - info: { - id: list[i].id, - contentId: list[i].id, - custContentId: list[i].id, - contentVer: list[i].version.number, - pageId: attInfo.pageId, - version: attInfo.version, - name: attInfo.diagramName, - displayName: list[i].title - }, - imgUrl: baseUrl + "/download/attachments/" + attInfo.pageId + "/" - + encodeURIComponent(attInfo.diagramName) - + ".png?api=v2&version=" + attInfo.version - }); - } - catch(e) - { - //ignore, this should not happen! - console.log(e); - } - } - } - - //This request search for Gliffy files as well as to support old draw.io diagrams that have no associated draw.io custom contents - AP.request({ - url: '/rest/api/content/search?cql=' + encodeURIComponent('type=attachment and (title ~ "*' + searchStr + '*" or title ~ "*' + searchStr + '*.png")') + '&limit=200&expand=metadata', //limit is 200 to get as much results as possible - success: function(resp) - { - resp = JSON.parse(resp); - var list = resp.results; - if (list) - { - var attMap = {}; - //convert the list to map so we can search by name efficiently - for (var i = 0; i < list.length; i++) - { - if (list[i].status == 'trashed') continue; - - //key is pageId + | + att name - var pageId = list[i]["_links"]["webui"].match(/pages\/(\d+)/); - - if (pageId != null) - { - var key = pageId[1] + '|' + list[i].title; - - //exclude contents already found in the custom contents - if (!customContentMap[key]) - { - attMap[key] = {att: list[i], pageId: pageId[1]}; - } - } - } - - function getAttObj(att, isImport, noImg) - { - var obj = { - title: att.att.title, - url: "/download/attachments/" + att.pageId + "/" - + encodeURIComponent(att.att.title), - info: { - id: att.att.id, - pageId: att.pageId, - name: att.att.title, - isImport: isImport - } - }; - - if (noImg) - { - obj.noImg = true; - } - else - { - obj.imgUrl = baseUrl + '/download/attachments/' + att.pageId + '/' - + encodeURIComponent(att.att.title) - + '.png?api=v2'; - } - - return obj; - }; - - for (var key in attMap) - { - var att = attMap[key]; - var mimeType = att.att.metadata.mediaType; - - if (mimeType == 'application/gliffy+json') - { - gliffyList.push(getAttObj(att, true)); - } - else if (mimeType == 'text/plain' && attMap[key+'.png']) //each draw.io attachment should have an associated png preview and mimeType is text/plain - { - //We cannot get the latest version info, it can be searched when a diagram is selected - retList.push(getAttObj(att)); - } - } - } - - success(retList, null, {"Gliffy": gliffyList}); - }, - error : error - }); - }, - error : error - }); -}; - -AC.getRecentDiagrams = function(success, error) -{ - //I think it is safe now to base the recent documents on draw.io custom contents only since it is in production for long time now - AP.request({ - url: '/rest/api/content/search?cql=type%3D%22ac%3Acom.mxgraph.confluence.plugins.diagramly%3Adrawio-diagram%22%20and%20lastmodified%20%3E%20startOfDay(%22-7d%22)&limit=50&expand=body.storage,version', // type="ac:com.mxgraph.confluence.plugins.diagramly:drawio-diagram" and lastmodified > startOfDay("-7d") //modified in the last 7 days - success: function(resp) - { - resp = JSON.parse(resp); - var retList = []; - var list = resp.results; - if (list) - { - //Add items in the list - for (var i = 0; i < list.length; i++) - { - try - { - var attInfo = JSON.parse(decodeURIComponent(list[i]["body"]["storage"]["value"])); - - retList.push({ - title: list[i].title, - url: "/download/attachments/" + attInfo.pageId + "/" - + encodeURIComponent(attInfo.diagramName) - + '?version=' + attInfo.version, - info: { - id: list[i].id, - contentId: list[i].id, - custContentId: list[i].id, - contentVer: list[i].version.number, - pageId: attInfo.pageId, - version: attInfo.version, - name: attInfo.diagramName, - displayName: list[i].title - }, - imgUrl: baseUrl + "/download/attachments/" + attInfo.pageId + "/" - + encodeURIComponent(attInfo.diagramName) - + ".png?api=v2&version=" + attInfo.version - }); - } - catch(e) - { - //ignore, this should not happen! - console.log(e); - } - } - } - - success(retList); - }, - error : error - }); -}; - -AC.getPageDrawioDiagrams = function(pageId, success, error) -{ - AP.request({ - type: 'GET', - url: '/rest/api/content/' + pageId + '/child/ac:com.mxgraph.confluence.plugins.diagramly:drawio-diagram?limit=100&expand=body.storage,version', - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - var retList = []; - var list = resp.results; - - if (list) - { - //Add items in the list - for (var i = 0; i < list.length; i++) - { - try - { - var attInfo = JSON.parse(decodeURIComponent(list[i]["body"]["storage"]["value"])); - var diagramName = list[i].title.replace('.drawio', ''); - - retList.push({ - title: diagramName, - url: "/download/attachments/" + attInfo.pageId + "/" - + encodeURIComponent(attInfo.diagramName) - + '?version=' + attInfo.version, - info: { - id: list[i].id, - contentId: list[i].id, - custContentId: list[i].id, - contentVer: list[i].version.number, - pageId: attInfo.pageId, - version: attInfo.version, - name: attInfo.diagramName, - displayName: diagramName - }, - imgUrl: baseUrl + "/download/attachments/" + attInfo.pageId + "/" - + encodeURIComponent(attInfo.diagramName) - + ".png?api=v2&version=" + attInfo.version - }); - } - catch(e) - { - //ignore, this should not happen! - console.log(e); - } - } - } - - success(retList); - }, - error: error - }); -}; - -AC.getCustomTemplates = function(success, error) -{ - var customCats = {}; - var customCatsCount = 0; - var customCatsDone = 0; - - function checkDone() - { - customCatsDone++; - - if (customCatsCount == customCatsDone) - { - success(customCats, customCatsDone); - } - } - - AP.request({ - type: 'GET', - url: '/rest/api/content/search?cql=type%3Dpage%20and%20space%3DDRAWIOCONFIG%20and%20title%3DTemplates', //type=page and space=DRAWIOCONFIG and title=Templates. - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - if (resp.size == 1) - { - var tempPageId = resp.results[0].id; - //load the configuration file - AP.request({ - type: 'GET', - url: '/rest/api/content/search?limit=50&cql=type%3Dpage%20and%20space%3DDRAWIOCONFIG%20and%20ancestor%3D' + tempPageId, //type=page and space=DRAWIOCONFIG and ancestor={tempPageId}. Limit 50 which is most probably more than enough - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - if (resp.size > 0) - { - for (var i = 0; i < resp.results.length; i++) - { - var cat = resp.results[i]; - customCats[cat.title] = []; - customCatsCount++; - - (function(cat2){ - AC.getPageDrawioDiagrams(cat2.id, function(catList) - { - customCats[cat2.title] = catList; - checkDone(); - }, checkDone); //On error, just ignore this page - })(cat); - } - } - else - { - success({}, 0); - } - }, - error: error - }); - } - else - { - success({}, 0); - } - }, - error: error - }); -}; - -AC.init = function(baseUrl, location, pageId, editor, diagramName, initialXml, draftName, draftXml, macroData, draftPage) -{ - // Hides the logo - document.body.style.backgroundImage = 'none'; - var user = null; - - AP.user.getCurrentUser(function(atlUser) - { - user = atlUser.atlassianAccountId; - }); - - var draftExists = false; - - var diagramDisplayName = diagramName, contentId = null, contentVer = null, lastMacroVer = null, revision = null; - - if (macroData != null) - { - diagramDisplayName = macroData.diagramDisplayName || diagramName; - contentId = macroData.contentId || macroData.custContentId; - contentVer = macroData.contentVer; - lastMacroVer = macroData.revision; - AC.aspect = macroData.aspect; - AC.hiResPreview = macroData.hiResPreview != null? macroData.hiResPreview == '1' : AC.hiResPreview; - } - - //keeping the block of AP.require to minimize the number of changes! - { - var newPage = location.indexOf('createpage.action') > -1 ? true : false; - var diagramXml = null; - var link = document.createElement('a'); - link.href = location.href; - link.href = link.href; //to have 'host' populated under IE - var hostUrl = link.protocol + '//' + link.hostname; - - function removeDraft(fn, err) - { - if (draftExists) - { - AC.removeAttachment(pageId, draftName, fn, err); - } - else - { - fn(); - } - }; - - function saveDraft(xml, fn, err) - { - //console.trace('DRAFT: Save', draftName, xml); - - AC.saveDiagram(pageId, draftName, - xml, - function(res) - { - var obj = null; - - try - { - obj = JSON.parse(res); - } - catch (e) - { - // ignore - } - - //console.trace('DRAFT: Saved', obj); - - if (obj != null && obj.error != null) - { - if (err != null) - { - err(obj); - } - } - else - { - draftExists = true; - - if (fn != null) - { - fn(obj); - } - } - }, - function(res) - { - //console.trace('DRAFT: Save error'); - var obj = null; - - try - { - obj = JSON.parse(res); - } - catch (e) - { - // ignore - } - - if (obj != null && obj.error != null) - { - if (err != null) - { - err(obj); - } - } - }, false, 'application/vnd.jgraph.mxfile', mxResources.get('createdByDraw'), false, draftPage); - }; - - function showTemplateDialog() - { - if (AC.draftEnabled) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'template', callback: true, enableRecent: true, enableSearch: true, enableCustomTemp: true}), '*'); - } - else - { - editor.contentWindow.postMessage(JSON.stringify({action: 'template', enableRecent: true, enableSearch: true, enableCustomTemp: true}), '*'); - } - }; - - function promptName(name, err, errKey) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'prompt', - titleKey: 'filename', okKey: 'save', defaultValue: name || '' }), '*'); - - if (err != null || errKey != null) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'dialog', - titleKey: 'error', message: err, messageKey: errKey, - buttonKey: 'ok'}), '*'); - } - }; - - function checkName(name, fn, err) - { - if (name == null || name.length == 0) - { - err(name, mxResources.get('filenameShort')); - } - else if (/[&\*+=\\;/{}|\":<>\?~]/g.test(name)) - { - err(name, mxResources.get('invalidChars') + ' \\ / | : { } < > & + ? = ; * " ~'); - } - else - { - name = name.trim(); - //TODO do a search instead if possible - AC.getPageAttachments(pageId, function(attachments) - { - var draftPattern = new RegExp('^~drawio~.*~' + name. - replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") + '.tmp$', 'i'); - var lc = name.toLowerCase(); - var dn = AC.draftPrefix + lc + AC.draftExtension - var fileExists = false; - - // Checks if any files will be overwritten - for (var i = 0; i < attachments.length && !fileExists; i++) - { - // To avoid name clash with new diagrams of other users, - // we need to check for ~drawio~.*~filename.tmp - var an = attachments[i].title.toLowerCase(); - - if (an == lc || an == lc + '.png' || (AC.draftEnabled && - (an == dn || draftPattern.test(an)))) - { - fileExists = true; - } - } - - if (fileExists) - { - err(name, mxResources.get('alreadyExst', [name])); - } - else - { - fn(name); - } - - }, function(res) - { - // TODO: What error message to return here? - err(name, res); - }); - } - }; - - var autosaveThread = null; - var autosaveCounter = 0; - var currentXml = null; - - // Shows template dialog for new diagrams with no draft state - if (initialXml != '') - { - editor.contentWindow.postMessage(JSON.stringify({action: 'load', - autosave: 1, xml: initialXml, title: diagramDisplayName, - macroData: macroData}), '*'); - } - - if (draftXml != null) - { - // Keeps ignore option even for existing files - editor.contentWindow.postMessage(JSON.stringify({action: 'draft', xml: draftXml, - name: diagramDisplayName, discardKey: 'discardChanges', ignore: true}), '*'); - } - else if (initialXml == '') - { - showTemplateDialog(); - } - - var messageListener = function(evt) - { - if (typeof window.AC !== 'undefined' && evt.origin == hostUrl) - { - var drawMsg = JSON.parse(evt.data); - - if (drawMsg.event == 'draft') - { - if (drawMsg.error != null) - { - //console.log('DRAFT: error', drawMsg); - - editor.parentNode.removeChild(editor); - - AC.showNotification({ - title: mxResources.get('draftReadErr'), - body: drawMsg.error, - type: 'error', - close: 'manual' - }); - - //TODO find how to listen to flag close event, currently just close the editor immediately -// messages.onClose(message, function() -// { - AP.dialog.close(); -// }); - } - else if (drawMsg.result == 'edit') - { - // Use draft - //console.trace('DRAFT: Using', draftName); - - editor.contentWindow.postMessage(JSON.stringify({action: 'load', - autosave: 1, xml: drawMsg.message.xml, title: diagramDisplayName}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'status', - messageKey: 'unsavedChanges', modified: true}), '*'); - draftExists = true; - } - else - { - if (drawMsg.result == 'discard') - { - //console.trace('DRAFT: Discarding', draftName); - - AC.removeAttachment(pageId, draftName); - } - - if (initialXml == '' || drawMsg.result == 'ignore') - { - if (initialXml != '') - { - editor.contentWindow.postMessage(JSON.stringify({action: 'load', - autosave: 1, xml: initialXml, title: diagramDisplayName, - macroData: macroData}), '*'); - } - else - { - diagramName = null; - showTemplateDialog(); - } - } - } - } - else if (drawMsg.event == 'template') - { - AC.curDiagId = false; //New diagram, so no diagram id - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: true, messageKey: 'inserting'}), '*'); - - if (drawMsg.docUrl) - { - checkName(drawMsg.name, function(name) - { - diagramName = name; - diagramDisplayName = name; - - //keeping the block of AP.require to minimize the number of changes! - { - var loadTemplate = function(version) - { - AP.request({ - url: drawMsg.docUrl + (version != null? "?version=" + version : ""), - success: function(xml) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'load', - autosave: 1, xml: xml, title: diagramDisplayName}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - }, - error : function(resp) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'dialog', - titleKey: 'error', message: mxResources.get('diagCantLoad'), messageKey: null, - buttonKey: 'ok'}), '*'); - } - }); - } - - AP.request({ - url: '/rest/api/content/' + drawMsg.info.id, - success: function(resp) - { - resp = JSON.parse(resp); - - try - { - loadTemplate(resp.version.number); - } - catch(e) - { - loadTemplate(); - } - }, - error : function(resp) - { - loadTemplate(); - } - }); - }; - }, - function(name, err, errKey) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'dialog', - titleKey: 'error', message: err, messageKey: errKey, - buttonKey: 'ok'}), '*'); - }); - } - else - { - checkName(drawMsg.name, function(name) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - diagramName = name; - diagramDisplayName = name; - - if (AC.draftEnabled) - { - draftName = '~drawio~' + user + '~' + diagramName + AC.draftExtension; - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: true, messageKey: 'inserting'}), '*'); - - saveDraft(drawMsg.xml, function() - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', show: false}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'load', - autosave: 1, xml: drawMsg.xml, title: diagramDisplayName}), '*'); - }, - function() - { - editor.parentNode.removeChild(editor); - - AC.showNotification({ - title: mxResources.get('draftWriteErr'), - body: mxResources.get('draftCantCreate'), - type: 'error', - close: 'manual' - }); - - //TODO find how to listen to flag close event, currently just close the editor immediately -// messages.onClose(message, function() -// { - AP.dialog.close(); -// }); - }); - } - else - { - editor.contentWindow.postMessage(JSON.stringify({action: 'load', - autosave: 1, xml: drawMsg.xml, title: diagramDisplayName}), '*'); - } - }, - function(name, err, errKey) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'dialog', - titleKey: 'error', message: err, messageKey: errKey, - buttonKey: 'ok'}), '*'); - }); - } - } - else if (drawMsg.event == 'autosave') - { - // Saves all changes to draft attachment - currentXml = drawMsg.xml; - - if (autosaveThread == null && AC.draftEnabled) - { - //console.trace('DRAFT: Starting timer'); - - autosaveThread = window.setTimeout(function() - { - //console.log('DRAFT: Saving', currentXml); - - autosaveThread = null - saveDraft(currentXml); - autosaveCounter++; - }, (autosaveCounter == 0) ? 0 : AC.autosaveTimeout); - } - } - else if (drawMsg.event == 'exit') - { - removeDraft(function() - { - //revision is non-null if the diagram is saved - AP.dialog.close(revision? {newRev: revision, newContentVer: contentVer, newContentId: contentId, newAspect: AC.aspect} : null); - }); - } - else if (drawMsg.event == 'save') - { - diagramXml = drawMsg.xml; - - if (diagramName == null) - { - promptName(''); - } - else - { - var aspectObj = AC.getAspectObj(); - - //Copy & Paste causes multiple diagrams in a page to have the same attachment name. Rename doesn't help as it only changes the display name (not the attachment name) - //So, prompt the use for a new attachment name - AP.request({ - url: '/rest/api/content/' + pageId + '/?expand=body.storage,version&status=draft', //always request draft content which will match published content if no draft is found - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - var page = JSON.parse(resp); - - //find all macros and check if diagram name (attachment) is used more than once - var foundMacros = page.body.storage.value.match(AC.findMacrosRegEx); - matchingCount = 0; - - for (var i = 0; foundMacros != null && i < foundMacros.length; i++) - { - var macroDiagName = foundMacros[i].match(AC.findMacroParamRegEx["diagramName"]); - - if (macroDiagName != null && macroDiagName[1] == diagramName) - { - matchingCount++; - } - } - - if (matchingCount > 1) - { - promptName(diagramName, mxResources.get('confDuplName')); - } - else - { - editor.contentWindow.postMessage(JSON.stringify({action: 'export', - format: 'png', spinKey: 'saving', scale: AC.hiResPreview? 2 : 1, - pageId: aspectObj.pageId, layerIds: aspectObj.layerIds, message: drawMsg}), '*'); - - } - }, - error : function(resp) - { - //We can safely ignore errors to avoid complicating loading diagram process - editor.contentWindow.postMessage(JSON.stringify({action: 'export', - format: 'png', spinKey: 'saving', scale: AC.hiResPreview? 2 : 1, - pageId: aspectPageId, layerIds: aspectLayerIds, message: drawMsg}), '*'); - } - }); - } - } - else if (drawMsg.event == 'prompt') - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: true, messageKey: 'inserting'}), '*'); - - checkName(drawMsg.value, function(name) - { - var aspectObj = AC.getAspectObj(); - - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - diagramName = name; - diagramDisplayName = name; - contentId = null; - contentVer = null; - editor.contentWindow.postMessage(JSON.stringify({action: 'export', - format: 'png', spinKey: 'saving', scale: AC.hiResPreview? 2 : 1, - pageId: aspectObj.pageId, layerIds: aspectObj.layerIds}), '*'); - }, - function(name, err, errKey) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - promptName(name, err, errKey); - }); - } - else if (drawMsg.event == 'rename') - { - //If diagram name is not set yet, use the new name for both file and diagram - //TODO should we disable renaming if diagramName is null? - if (diagramName == null) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: true}), '*'); - - checkName(drawMsg.name, function(name) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - diagramName = name; - diagramDisplayName = name; - }, - function(name, err, errKey) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: false}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'dialog', - titleKey: 'error', message: err, messageKey: errKey, - buttonKey: 'ok'}), '*'); - }); - } - else - { - diagramDisplayName = drawMsg.name; - } - - editor.contentWindow.postMessage(JSON.stringify({action: 'status', - messageKey: 'unsavedChanges', modified: true}), '*'); - } - else if (drawMsg.event == 'export') - { - // Proceeds from sending the export message by saving the exported files - var imageData = drawMsg.data.substring(drawMsg.data.indexOf(',') + 1); - var diaWidth = drawMsg.bounds.width / drawMsg.scale; - var diaHeight = drawMsg.bounds.height / drawMsg.scale; - - function showError(key, message) - { - var msg = {action: 'dialog', titleKey: 'error', modified: true, buttonKey: 'close'}; - - if (message != null) - { - msg.message = message; - } - else - { - msg.messageKey = key || 'errorSavingFile'; - } - - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', show: false}), '*'); - editor.contentWindow.postMessage(JSON.stringify(msg), '*'); - }; - - function saveError(err) - { - var key = null; - var message = null; - - if (err.status == 409) - { - diagramName = null; - key = 'fileExists'; - } - else if (err.status == 401) - { - // Session expired - message = mxResources.get('confSessionExpired') + - ' ' + mxResources.get('login') + ''; - } - else if (err.status == 400) - { - try - { - var errObj = JSON.parse(err.responseText); - - if (errObj.message.indexOf('Content body cannot be converted to new editor') > 0) - { - message = 'A Confluence Bug (CONFCLOUD-69902) prevented saving the page. Please edit the diagram from "Confluence Page Editor" where you can restore you changes from "File -> Revision history".'; - } - } - catch(e){} //Ignore - } - - showError(key, message); - }; - - function successXml(responseText) - { - var resp = null; - revision = '1'; - - //TODO Why this code (Is it expected to have incorrect responseText?) - try - { - resp = JSON.parse(responseText); - } - catch (e) - { - // Ignores and use default value for revision - } - - // LATER: Get revision from metadata of attachment and check - // what condition makes the response not contain an URL - //TODO Is prev comment still needed with REST API? - if (resp != null && resp.results != null && resp.results[0]) - { - var attObj = resp.results[0]; - revision = attObj.version.number; - //Save/update the custom content - var spaceKey = AC.getSpaceKey(attObj._expandable.space); - var pageType = attObj.container.type; - - AC.saveCustomContent(spaceKey, pageId, pageType, diagramName, diagramDisplayName, revision, - contentId, contentVer, - function(responseText) - { - var content = JSON.parse(responseText); - - contentId = content.id; - contentVer = content.version? content.version.number : 1; - - AC.saveDiagram(pageId, diagramName + '.png', AC.b64toBlob(imageData, 'image/png'), - successPng, saveError, false, 'image/png', mxResources.get('drawPrev'), false, draftPage); - }, saveError, drawMsg.comments); - } - else - { - // Logs special case where save response has no URL - try - { - var img = new Image(); - var message = 'Invalid Confluence Cloud response'; - img.src = '/images/2x2.png?msg=' + encodeURIComponent(message) + - ((responseText != null) ? '&resp=' + encodeURIComponent(responseText) : '&resp=[null]'); - '&url=' + encodeURIComponent(window.location.href); - } - catch (err) - { - // do nothing - } - - //TODO Save png here in case responseText is incorrect (But why it can be incorrect?) - AC.saveDiagram(pageId, diagramName + '.png', AC.b64toBlob(imageData, 'image/png'), - successPng, saveError, false, 'image/png', mxResources.get('drawPrev'), false, draftPage); - } - - function successPng(pngResponseText) - { - try - { - // IMPORTANT: New macro parameters must be added to AC.macroParams to for adjustMacroParametersDirect to parse existing parameters correctly. - var newMacroData = { - diagramName: diagramName, - diagramDisplayName: diagramDisplayName, - revision: revision, - pageId: newPage ? null : pageId, - custContentId: contentId, - contentVer: contentVer, - baseUrl: baseUrl, - width: diaWidth, - height: diaHeight, - tbstyle: (drawMsg.macroData != null && drawMsg.macroData.tbstyle) ? drawMsg.macroData.tbstyle : '', - links: (drawMsg.macroData != null && drawMsg.macroData.links) ? drawMsg.macroData.links : '', - simple: (drawMsg.macroData != null && drawMsg.macroData.simple != null) ? drawMsg.macroData.simple : '0', - lbox: (drawMsg.macroData != null && drawMsg.macroData.lbox != null) ? drawMsg.macroData.lbox : '1', - zoom: (drawMsg.macroData != null && drawMsg.macroData.zoom != null) ? drawMsg.macroData.zoom : '1', - pCenter: (drawMsg.macroData != null && drawMsg.macroData.pCenter != null) ? drawMsg.macroData.pCenter : '0', - aspect: AC.aspect, - inComment: AC.inComment? '1' : '0' - }; - - //Set the hiResPreview only if the user set it in the UI which overrides the global settings - if (drawMsg.macroData != null && drawMsg.macroData.hiResPreview != null) - { - newMacroData.hiResPreview = drawMsg.macroData.hiResPreview; - } - - var finalizeSaving = function() - { - if (AC.autoExit || drawMsg.message == null || drawMsg.message.message == null || drawMsg.message.message.exit) - { - var savingCallback = function() - { - removeDraft(function() - { - AP.dialog.close({newRev: revision, newContentVer: contentVer, newContentId: contentId, newAspect: AC.aspect}); - }); - }; - - //Save indexing text - //Exit is done when the response is received! - //This is needed for advanced search by draw.io diagrams type - AC.remoteInvoke('getDiagramTextContent', null, null, function(textContent) - { - AC.saveContentSearchBody(contentId, diagramDisplayName + ' ' + textContent, - savingCallback, savingCallback); //ignore error and just exit - }, savingCallback); - } - else - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', show: false}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'status', message: '', modified: false}), '*'); - } - }; - - if (AC.customContentEditMode) - { - //load the page to edit the macro - AC.findMacroInPage(pageId, diagramName, lastMacroVer, function(macroFound, originalBody, matchingMacros, page) - { - if (macroFound) - { - AC.adjustMacroParametersDirect(pageId, newMacroData, originalBody, matchingMacros, page, finalizeSaving, saveError); - lastMacroVer = revision; //for next save - } - else //macro is not found in the page content, so just continue with saving instead of showing an error and losing users modifications - { - //Using alert here to pause execution as some execution flows go back and Confluence error messages will be lost - //In strandedMode, we already warned the user at the beginning - if (!AC.strandedMode) - { - alert(mxResources.get('confDiagEditedExt')); - } - - finalizeSaving(); - } - }, saveError); - } - else - { - AP.confluence.saveMacro(newMacroData); - finalizeSaving(); - } - } - catch (e) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', show: false}), '*'); - editor.contentWindow.postMessage(JSON.stringify({action: 'dialog', - titleKey: 'errorSavingFile', message: e.message, buttonKey: 'ok'}), '*'); - } - }; - }; - - if (diagramName != null) - { - editor.contentWindow.postMessage(JSON.stringify({action: 'spinner', - show: true, messageKey: 'saving'}), '*'); - - AC.saveDiagram(pageId, diagramName, diagramXml, - successXml, saveError, false, 'application/vnd.jgraph.mxfile', mxResources.get('drawDiag'), false, draftPage); - } - } - else if (drawMsg.event == 'remoteInvoke') - { - AC.handleRemoteInvoke(drawMsg); - } - else if (drawMsg.event == 'remoteInvokeResponse') - { - AC.handleRemoteInvokeResponse(drawMsg); - } - } - }; - - window.addEventListener('message', messageListener); - editor.contentWindow.postMessage(JSON.stringify({action: 'remoteInvokeReady'}), '*'); - AC.remoteWin = editor.contentWindow; - }; -}; - -AC.loadDiagram = function (pageId, diagramName, revision, success, error, owningPageId, tryRev1, dontCheckVer) -{ - var curDiagName = diagramName; - var curPageId = pageId; - // TODO: Get binary - - //keeping the block of AP.require to minimize the number of changes! - { - var localSuccess = function(resp) - { - success(resp, curPageId, curDiagName); - } - - AP.request({ - //TODO find out the ID of the page that actually holds the attachments because historical revisions do not have attachments - url: '/download/attachments/' + pageId + '/' + encodeURIComponent(diagramName) + - ((revision != null) ? '?version=' + revision : ''), - success: localSuccess, - error : function(resp) - { - //When a page is copied, attachments are reset to version 1 while the revision parameter remains the same - if (tryRev1 && revision > 1 && resp.status == 404) - { - AP.request({ - url: '/download/attachments/' + pageId + '/' + encodeURIComponent(diagramName), - success: localSuccess, - error : function(resp) { //If revesion 1 failed, then try the owningPageId - if (owningPageId && resp.status == 404) - { - curPageId = owningPageId; - AP.request({ - url: '/download/attachments/' + owningPageId + '/' + encodeURIComponent(diagramName) - +'?version=' + revision, //this version should exists in the original owning page - success: localSuccess, - error : function(resp) - { - if (/(^\s|\s$)/.test(diagramName)) - { - AC.loadDiagram(pageId, diagramName.trim(), revision, success, error, owningPageId, tryRev1, dontCheckVer); - } - else - { - error(resp); - } - } - }); - } - } - }); - } - else if (owningPageId && resp.status == 404) //We are at revesion 1, so try the owningPageId directly - { - curPageId = owningPageId; - AP.request({ - url: '/download/attachments/' + owningPageId + '/' + encodeURIComponent(diagramName), - success: localSuccess, - error : function(resp) - { - if (/(^\s|\s$)/.test(diagramName)) - { - AC.loadDiagram(pageId, diagramName.trim(), revision, success, error, owningPageId, tryRev1, dontCheckVer); - } - else - { - error(resp); - } - } - }); - } - else - { - error(resp); - } - } - }); - }; -}; - -AC.findMacroInPage = function(pageId, diagramName, lastMacroVer, success, error, draftPage) -{ - //load the page to edit the macro - AP.request({ - type: 'GET', - url: '/rest/api/content/' + pageId + '/?expand=body.storage,version' + (draftPage ? "&status=draft" : ""), - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - var page = JSON.parse(resp); - - var originalBody = page.body.storage.value; - - var foundMacros = originalBody.match(AC.findMacrosRegEx); - - var macroFound = false; - var matchingMacros = []; - - for (var i = 0; foundMacros != null && i < foundMacros.length; i++) - { - var macroDiagName = foundMacros[i].match(AC.findMacroParamRegEx["diagramName"]); - var macroRevision = foundMacros[i].match(AC.findMacroParamRegEx["revision"]); - - if (macroDiagName != null && macroRevision != null && macroDiagName[1] == diagramName && (macroRevision[1] == lastMacroVer || lastMacroVer == false)) - { - var macroParams = {}; - - for (var j = 0; j < AC.macroParams.length; j++) - { - var param = AC.macroParams[j]; - var val = foundMacros[i].match(AC.findMacroParamRegEx[param]); - - if (val != null) - macroParams[param] = val[1]; - } - - matchingMacros.push({macro: foundMacros[i], macroParams: macroParams}); - macroFound = true; - } - } - - success(macroFound, originalBody, matchingMacros, page); - }, - error: error - }); -}; - -//FIXME Confluence adjust macros in draft such that there is no way to adjust the content of drafts currently! So, drafts code is removed -AC.adjustMacroParametersDirect = function(pageId, macroData, originalBody, matchingMacros, page, success, error) -{ - for (var i = 0; i < matchingMacros.length; i++) - { - var modMacro = matchingMacros[i].macro; - - for (var param in macroData) - { - var pRegEx = AC.findMacroParamRegEx[param]; - - //This to avoid errors if a new parameter/key is added to the macro and is not in the macro regexps - if (pRegEx == null) continue; - - var newParamVal = '' + macroData[param]; - - //If parameter exists, change it. Otherwise, add it - if (modMacro.match(pRegEx)) - { - modMacro = modMacro.replace(pRegEx, newParamVal); - } - else - { - modMacro += newParamVal + ""; - } - } - - originalBody = originalBody.replace(matchingMacros[i].macro, modMacro); - } - - page.body.storage.value = originalBody; - page.version.number++; - - AP.request({ - type: 'PUT', - data: JSON.stringify(page), - url: "/rest/api/content/" + pageId, - contentType: "application/json", - success: success, - error: error - }); -}; - -AC.saveCustomContent = function(spaceKey, pageId, pageType, diagramName, diagramDisplayName, revision, contentId, contentVer, success, error, comments, reportAllErr) -{ - //Make sure comments are not lost - if (comments == null) - { - AC.getOldComments(contentId, function(comments) - { - AC.saveCustomContent(spaceKey, pageId, pageType, diagramName, diagramDisplayName, revision, contentId, contentVer, success, error, comments, reportAllErr); - }, - //On error, whether the custom content is deleted or corrupted. It is better to proceed with saving and losing the comments than losing the diagram - function() - { - AC.saveCustomContent(spaceKey, pageId, pageType, diagramName, diagramDisplayName, revision, contentId, contentVer, success, error, [], reportAllErr); - }); - - return; - } - - var info = { - "pageId": pageId, - "diagramName": diagramName, - "version": revision, - "inComment": AC.inComment, - "comments": comments || [] - }; - - var customObj = { - "type": "ac:com.mxgraph.confluence.plugins.diagramly:drawio-diagram", - "space": { - "key": spaceKey - }, - "container": { - "type": pageType, - "id": pageId - }, - "title": diagramDisplayName, - "body": { - "storage": { - "value": encodeURIComponent(JSON.stringify(info)), - "representation": "storage" - } - }, - "status": "current" - }; - - if (contentId) - { - customObj.version = { - "number": ++contentVer - }; - } - - //keeping the block of AP.require to minimize the number of changes! - { - AP.request({ - type: contentId? 'PUT' : 'POST', - data: JSON.stringify(customObj), - url: "/rest/api/content/" + (contentId? contentId : ""), - contentType: "application/json", - success: success, - error: function(resp) - { - if (reportAllErr) - { - error(resp); - return; - } - - //User can delete a custom content externally and we will get error 403 and message will contain the given id - //Then save a new one - var err = JSON.parse(resp.responseText); - - //Sometimes the macro is not updated such that the version is not correct. The same happens when a page version is restored - if (err.statusCode == 409 && err.message.indexOf("Current version is:") > 0) - { - //We will use the error message to detect the correct version instead of doing another request. - //It should be safe as long as error messages are not translated or changed - var curContentVer = err.message.match(/\d+/); - - if (curContentVer != null) - { - AC.saveCustomContent(spaceKey, pageId, pageType, diagramName, diagramDisplayName, revision, contentId, curContentVer[0], success, error, comments); - } - } - //Sometimes, when a page is copied or site is cloned, custom contents are lost, so create a new one - //For example, error 400: When a page is moved to another space, an error occur since the original custom content belong to another space/page - else if (contentId != null) - { - AC.saveCustomContent(spaceKey, pageId, pageType, diagramName, diagramDisplayName, revision, null, null, success, error, comments); - } - else - { - error(resp); - } - } - }); - }; -}; - -AC.saveContentSearchBody = function(contentId, searchBody, success, error) -{ - var doSaveSearchBody = function(version) - { - AC.setContentProperty(contentId, 'ac:custom-content:search-body', searchBody, version, success, error); - }; - - - AC.getContentProperty(contentId, 'ac:custom-content:search-body', function(resp) - { - resp = JSON.parse(resp); - - doSaveSearchBody(resp.version.number); - }, - function(resp) - { - var err = JSON.parse(resp.responseText); - - //if not found, create one - if (err.statusCode == 404) - { - doSaveSearchBody(); - } - else - error(); - }); -}; - -//TODO We can upload both the diagram and its png in one call if needed? -AC.saveDiagram = function(pageId, diagramName, xml, success, error, newSave, mime, comment, sendNotif, draftPage) -{ - loadSucess = function(resp) - { - error({status: 409, message: mxResources.get('fileExists')}); - }; - - loadError = function(resp) - { - if (resp.status == 404) // file under given name does not exist means we can proceed with saving - { - doSave(); - } - else - { - error({status: resp.status, message : resp.statusText }); - } - }; - - var sessionCheck = function(responseText) - { - if (responseText != null) - { - var obj = JSON.parse(responseText); - - if (obj != null && obj.code == -32600) //TODO is the codes the same with new REST APIs - { - error({status: 401}); - - return; - } - } - - success(responseText); - } - - doSave = function() - { - //keeping the block of AP.require to minimize the number of changes! - { - var attFile = (xml instanceof Blob)? xml : new Blob([xml], {type: mime}); - attFile.name = diagramName; - - var reqData = {file: attFile, minorEdit: !sendNotif}; - var draft = draftPage ? "?status=draft" : ""; - - if (comment != null) - { - reqData.comment = comment; - } - - AP.request({ - type: 'PUT', - data: reqData, - url: "/rest/api/content/"+ pageId +"/child/attachment" + draft, - contentType: "multipart/form-data", - success: sessionCheck, - error: error - }); - }; - }; - - if(newSave && mime == 'application/vnd.jgraph.mxfile') - { - this.loadDiagram(pageId, diagramName, 0, loadSucess, loadError); - } - else - { - doSave(); - } -}; - -AC.removeAttachment = function(pageId, filename, fn, err) -{ - if (pageId != null && filename != null) - { - var errFn = function() - { - if (err != null) - { - err(); - } - - if (fn != null) - { - fn(); - } - }; - - //Empty the draft file without deleting it to prevent email notifications - var attFile = new Blob(['']); - attFile.name = filename; - - var reqData = { - file: attFile, - minorEdit: true, - comment: 'draw.io draft (D)' - }; - - AP.request({ - type: 'PUT', - data: reqData, - url: "/rest/api/content/"+ pageId +"/child/attachment", - contentType: "multipart/form-data", - success: function () - { - if (fn != null) - { - fn(); - } - }, - error: errFn - }); - } - else - { - fn(); - } -}; - -AC.getMacroData = function(fn) -{ - AP.confluence.getMacroData(fn); -} - -//From mxUtils -AC.htmlEntities = function(s, newline) -{ - s = String(s || ''); - - s = s.replace(/&/g,'&'); // 38 26 - s = s.replace(/"/g,'"'); // 34 22 - s = s.replace(/\'/g,'''); // 39 27 - s = s.replace(//g,'>'); // 62 3E - - if (newline == null || newline) - { - s = s.replace(/\n/g, ' '); - } - - return s; -}; - -AC.fromHtmlEntities = function(str) -{ - var doc = new DOMParser().parseFromString(str || '', "text/html"); - return doc.documentElement.textContent; -}; - -AC.getCustomLibraries = function(callback, error) -{ - var ret = []; - - function getChunk(url) - { - AP.request({ - type: 'GET', - url: url, - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - for (var i = 0; i < resp.results.length; i++) - { - var obj = resp.results[i]; - ret.push({ - id: obj.id, - title: obj.title, - downloadUrl: obj._links? obj._links.download : null - }); - } - - //Support pageing - if (resp._links && resp._links.next) - { - getChunk(resp._links.next); - } - else - { - callback(ret); - } - }, - error: error - }); - }; - - AP.request({ - type: 'GET', - url: '/rest/api/content/search?cql=type%3Dpage%20and%20space%3DDRAWIOCONFIG%20and%20title%3DLibraries', //type=page and space=DRAWIOCONFIG and title=Libraries. Search doesn't return 404 if not found - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - if (resp.size == 1) - { - var libsPageId = resp.results[0].id; - - getChunk('/rest/api/content/' + libsPageId + '/child/attachment?limit=100'); - } - else - { - callback(ret); - } - }, - error: error - }); -}; - -AC.getFileContent = function(url, callback, error) -{ - AP.request({ - type: 'GET', - url: url, - contentType: 'text/xml;charset=UTF-8', - success: function (fileContent) - { - callback(fileContent); - }, - error: error - }); -}; - -AC.getCurrentUser = function(callback, error) -{ - var baseUrl = AC.getBaseUrl(); - - AP.request({ - type: 'GET', - url: '/rest/api/user/current', - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - callback({ - id: resp.accountId, - username: resp.username, - email: resp.email, - displayName: resp.displayName, - pictureUrl: resp.profilePicture? baseUrl.substr(0, baseUrl.lastIndexOf('/')) + resp.profilePicture.path : null - }); - }, - error: error - }); -}; - -AC.RESOLVED_MARKER = '$$RES$$ '; -AC.REPLY_MARKER = '$$REP$$'; -AC.REPLY_MARKER_END = '$$ '; -AC.DELETED_MARKER = '$$DELETED$$'; -AC.PREV_VERSIONS_KEY = '$$PREV_VER$$'; -AC.PREV_VERSIONS_START = '{"' + AC.PREV_VERSIONS_KEY + '": ['; -AC.PREV_VERSIONS_END = ']}'; -AC.COMMENTS_INDEX_PROP = 'commentsAttVerIndex'; - -AC.getPrevVersionsComment = function(attId, attVer, callback, error) -{ - AP.request({ - url : '/rest/api/content/' + attId + - '/child/comment?limit=200&expand=body.storage&parentVersion=' + attVer, - type : 'GET', - success : function(comments) - { - comments = JSON.parse(comments).results; - var count = comments.length; - var prevVer = []; - - for (var i = 0; i < comments.length; i++) - { - var decCntn = decodeURIComponent(comments[i].body.storage.value); - - if (decCntn.indexOf(AC.PREV_VERSIONS_START) == 0) - { - count--; - - try - { - prevVer = JSON.parse(decCntn)[AC.PREV_VERSIONS_KEY]; - } - catch(e){} //Ignore - } - } - - if (count > 0) - { - prevVer.push(attVer); - } - - callback(prevVer.length == 0? null : AC.PREV_VERSIONS_START + prevVer.join(',') + AC.PREV_VERSIONS_END); - }, - error : error - }); -}; - -//TODO Use of globals is risky and error-prone. Find another way to get attachment id and version? -AC.commentsFnWrapper = function(fn, noErrCheck) -{ - //Wait for attId and ver to be ready - function wrappedFn() - { - if (AC.curDiagId == false && !noErrCheck) - { - //Call error (last argument) - arguments[arguments.length - 1](); - } - else if (AC.curDiagId != null) - { - fn.apply(this, arguments); - } - else - { - var fnArgs = arguments; - //Wait - setTimeout(function() - { - wrappedFn.apply(this, fnArgs); - }, 300); - } - } - - return wrappedFn; -}; - -AC.getComments = AC.commentsFnWrapper(function(attVer, checkUnresolvedOnly, success, error) -{ - function isResolvedComment(atlasComment) - { - if (atlasComment.children != null) - { - var lastReply = atlasComment.children.comment.results.pop(); - - if (lastReply != null && decodeURIComponent(lastReply.body.storage.value).indexOf(AC.RESOLVED_MARKER) == 0) - { - return true; - } - else - { - return false; - } - } - else - { - return false; - } - }; - - var attId = AC.curDiagId; - attVer = attVer || AC.curDiagVer; - - var confComments = [], remaining; - - if (attId) - { - AC.getCommentsAttVersIndex(attId, function() - { - remaining = AC.curCommentIndex.length; - doNextChunk(); - indexIntegrityCheck(); - }, function() - { - indexIntegrityCheck(function() - { - remaining = AC.curCommentIndex.length; - doNextChunk(); - }, error); - }); - - function indexIntegrityCheck(callback, error) - { - if (checkUnresolvedOnly && callback == null) return; - - AC.getAttVersWithComments(attId, attVer, function(vers, versMap) - { - var matches = 0; - - for (var i = 0; i < AC.curCommentIndex.length; i++) - { - if (versMap[AC.curCommentIndex[i]]) - { - matches++; - } - } - - if (matches != vers.length || AC.curCommentIndex.length != vers.length) - { - AC.curCommentIndex = vers; - AC.setCommentsAttVersIndex(attId, vers); - } - - if (callback) - { - callback(); - } - }, - function() - { - console.log('Error while checking integrity of comments index for ' + attVer); //TODO What to do when integrity call fails? - - if (error) - { - error(); - } - }); - }; - - function doGetComments(ver, callback, error) - { - AP.request({ - url : '/rest/api/content/' + attId + - '/child/comment?limit=200&expand=body.storage,version,history,children.comment.body.storage,children.comment.version,children.comment.history' + - '&parentVersion=' + ver, - type : 'GET', - success : function(comments) - { - //TODO handle paging or 200 comments + 25 replies are enough? - comments = JSON.parse(comments).results; - - for (var i = 0; i < comments.length; i++) - { - if (checkUnresolvedOnly) - { - if (!isResolvedComment(comments[i])) - { - success(true); - return; - } - } - else - { - comments[i].attVer = ver; - confComments.push(comments[i]); - } - } - - callback(); - }, - error : error - }); - }; - - function doNextChunk() - { - remaining--; - - if (remaining < 0) - { - success(checkUnresolvedOnly? false : confComments, AC.getSiteUrl()); - return; - } - - doGetComments(AC.curCommentIndex[remaining], doNextChunk, error); - } - } - else - { - error({message: mxResources.get('saveDiagramFirst', null, 'Save diagram first!')}); - } -}, true); - -AC.hasUnresolvedComments = function(pageId, contentId, diagramName, callback, error) -{ - AC.getOldComments(contentId, function(comments) - { - var hasOldComments = false; - - for (var i = 0; i < comments.length; i++) - { - if (comments[i].isDeleted) continue; - - hasOldComments = true; - - if (!comments[i].isResolved) - { - callback(true); - break; - } - } - - if (!hasOldComments) - { - //Get current diagram information which is needed for comments - //This call is needed since we allow calling this from viewer without using AC.loadDiagram - //TODO viewer needs to use AC for interaction with Confluence - AC.getAttachmentInfo(pageId, diagramName, function(info) - { - AC.curDiagVer = info.version.number; - AC.curDiagId = info.id; - - AC.getComments(null, true, callback, error); - }, - error); - } - }, - error); -}; - -AC.setCommentsAttVersIndex = function(attId, vers) -{ - AC.setContentProperty(attId, AC.COMMENTS_INDEX_PROP, JSON.stringify(vers), AC.curCommentIndexVer, - function(resp) - { - resp = JSON.parse(resp); - AC.curCommentIndexVer = resp.version.number; - }, - function(){}); //Ignore errors -}; - -AC.getCommentsAttVersIndex = function(attId, success, error) -{ - AC.getContentProperty(attId, AC.COMMENTS_INDEX_PROP, function(resp) - { - resp = JSON.parse(resp); - AC.curCommentIndexVer = resp.version.number; - - try - { - AC.curCommentIndex = JSON.parse(resp.value); - - if (AC.curCommentIndex.length > AC.curDiagVer) - { - AC.curCommentIndex = []; //The length of the index cannot exceed the number of the versions, so, index is corrupt - } - } - catch(e) - { - AC.curCommentIndex = []; - } - - success(AC.curCommentIndex); - }, function() - { - AC.curCommentIndex = []; - error(); - }); -}; - -AC.getAttVersWithComments = function(attId, attVer, callback, error) -{ - var start = 1; - var vers = [], versMap = {}; - - function checkChunk(start, end, callback, error) - { - var doneCount = 0, total = end - start + 1; - - function checkDone() - { - doneCount++; - - if (doneCount == total) - { - callback(); - } - } - - function checkVer(ver) - { - AP.request({ - url : '/rest/api/content/' + attId + - '/child/comment?limit=200&parentVersion=' + ver, - type : 'GET', - success : function(comments) - { - //TODO handle paging or 200 comments + 25 replies are enough? - if (JSON.parse(comments).results.length > 0) - { - vers.push(ver); - versMap[ver] = true; - } - - checkDone(); - }, - error : error - }); - }; - - for (var i = start; i <= end; i++) - { - checkVer(i); - } - }; - - function doNextChunk() - { - if (start > attVer) - { - callback(vers, versMap); - return; - } - - //Check all versions 5 at a time - checkChunk(start, Math.min(start + 4, attVer), doNextChunk, error); - start += 5; - } - - doNextChunk(); -}; - -AC.addComment = AC.commentsFnWrapper(function(commentContent, success, error) -{ - var attId = AC.curDiagId; - - if (attId) - { - AP.request({ - url : '/rest/api/content', - type : 'POST', - data: JSON.stringify({ - type: 'comment', - container: { - "type": 'attachment', - "id": attId - }, - "body": { - "storage": { - "value": encodeURIComponent(commentContent), - "representation": "storage" - } - } - }), - success : function(addedComment) - { - addedComment = JSON.parse(addedComment); - success(addedComment.id, addedComment.version.number, AC.curDiagVer); - - //Add cur ver to list of versions - if (AC.curCommentIndex.indexOf(AC.curDiagVer) == -1) - { - AC.curCommentIndex.push(AC.curDiagVer); - AC.setCommentsAttVersIndex(attId, AC.curCommentIndex); - } - }, - error : error, - contentType: 'application/json' - }); - } - else - { - error({message: mxResources.get('saveDiagramFirst', null, 'Save diagram first!')}); - } -}, true); - -AC.addCommentReply = AC.commentsFnWrapper(function(parentId, parentAttVer, replyContent, doResolve, callback, error) -{ - var attId = AC.curDiagId; - - //We cannot add replies to comments that belong to old versions of the attachment, so, as a workaround we add a special regular comment - if (parentAttVer != AC.curDiagVer) - { - AC.addComment(AC.REPLY_MARKER + parentId + AC.REPLY_MARKER_END + (doResolve? AC.RESOLVED_MARKER : '') + replyContent, callback, error); - } - else - { - AP.request({ - url : '/rest/api/content', - type : 'POST', - data: JSON.stringify({ - "type": 'comment', - "ancestors": [ - { - "id": parentId - } - ], - "container": { - "type": 'attachment', - "id": attId - }, - "body": { - "storage": { - "value": encodeURIComponent((doResolve? AC.RESOLVED_MARKER : '') + replyContent), - "representation": "storage" - } - } - }), - success : function(addedReply) - { - addedReply = JSON.parse(addedReply); - callback(addedReply.id, addedReply.version.number); - }, - error : function(xhr) - { - if (xhr.responseText.indexOf('messageKey=parent.comment.does.not.exist') > 0) - { - error({message: mxResources.get('parentCommentDel', null, 'Parent comment has been deleted. A reply cannot be added.')}); - } - else - { - error(xhr) - } - }, - contentType: 'application/json' - }); - } -}); - -AC.editComment = AC.commentsFnWrapper(function(id, version, newContent, success, error) -{ - var attId = AC.curDiagId; - - AP.request({ - url : '/rest/api/content/' + id, - type : 'PUT', - data: JSON.stringify({ - "type": 'comment', - "body": { - "storage": { - "value": encodeURIComponent(newContent), - "representation": "storage" - } - }, - "container": { - "type": 'attachment', - "id": attId - }, - "version": { - "number": version + 1 - } - }), - success : function(editedComment) - { - editedComment = JSON.parse(editedComment); - success(editedComment.version.number); - }, - error : error, - contentType: 'application/json' - }); -}); - -AC.deleteComment = function(id, version, hasReplies, success, error) -{ - function doDel() - { - AP.request({ - url : '/rest/api/content/' + id, - type : 'DELETE', - success : success, - error : error - }); - }; - - if (hasReplies) - { - //Mark as deleted if there is replies - AC.editComment(id, version, AC.DELETED_MARKER, function() - { - success(true); - }, error); - } - else - { - doDel(); - } -}; - -AC.getOldComments = function(contentId, callback, error) -{ - if (contentId) - { - AP.request({ - type: 'GET', - url: '/rest/api/content/' + contentId + '/?expand=body.storage,version,container', - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - try - { - resp = JSON.parse(resp); - var infoObj = JSON.parse(decodeURIComponent(resp.body.storage.value)); - var spaceKey = AC.getSpaceKey(resp._expandable.space); - var pageId = resp.container.id; - var pageType = resp.container.type; - var contentVer = resp.version.number; - - callback(infoObj.comments || [], spaceKey, pageId, pageType, contentVer); - } - catch(e) - { - error(e); - } - }, - error: error - }); - } - else - { - callback([]); - } -}; - -//Check if user can edit content (page or another content) -//Confluence doesn't provide an easy way to check for permissions. -// E.g., https://draw-test.atlassian.net/wiki/rest/api/content/{contentId}/restriction/byOperation/update/user?accountId={userAccountId} -// It returns 404 even if the user has permission. It only returns 200 (OK) if the user is explicitly in restrictions list (doesn't check groups also) -AC.userCanEdit = function(contentId, callback, error) -{ - var userFound = false; - var accountId, groupsCount, parsedGroups = 0; - - function checkGroupMembers(resp) - { - //If the user belong to multiple groups, callback will be called more than once - if (userFound) return; - - resp = JSON.parse(resp); - - var list = resp.results; - - for (var i = 0; i < list.length; i++) - { - if (list[i].accountId == accountId) - { - callback(true); - userFound = true; - return; - } - } - - parsedGroups++; - - //All groups parsed - if (groupsCount == parsedGroups) - { - callback(false); - } - }; - - AP.user.getCurrentUser(function(user) { - accountId = user.atlassianAccountId; - - AP.request({ - type: 'GET', - url: '/rest/api/content/' + contentId + '/restriction/byOperation/update', //This API doesn't work well with paging, BUT 100 as a default limit looks enough - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - resp = JSON.parse(resp); - - if (resp.restrictions.user.size == 0) //When restrictions are empty, it means all are allowed - { - callback(true); - } - else - { - //Search users - var list = resp.restrictions.user.results; - - for (var i = 0; i < list.length; i++) - { - if (list[i].accountId == accountId) - { - callback(true); - userFound = true; - break; - } - } - - //Check groups - if (!userFound) - { - if (resp.restrictions.group.size == 0) //The owner must be in the list of editors, so, a group cannot exist without a user in the list - { - callback(false); //User cannot edit - } - else //For each group check its members! - { - var groups = resp.restrictions.group.results; - groupsCount = groups.length; - - for (var i = 0; i < groups.length; i++) - { - AP.request({ - type: 'GET', - url: '/rest/api/group/' + encodeURIComponent(groups[i].name) + '/member', - contentType: 'application/json;charset=UTF-8', - success: checkGroupMembers, - error: error - }); - } - } - } - } - }, - error: error - }); - }); -}; - -AC.getPageInfo = function(urlOnly, success, error) -{ - AP.getLocation(function(url) - { - if (urlOnly) - { - success({url: url}); - } - else - { - AP.navigator.getLocation(function (location) - { - AP.request({ - type: 'GET', - url: '/rest/api/content/' + location.context.contentId, - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - resp = JSON.parse(resp); - resp.url = url; - success(resp); - }, - error: error - }); - }); - - } - }); -}; - -AC.getContentProperty = function(contentId, propName, success, error) -{ - AP.request({ - type: 'GET', - url: '/rest/api/content/' + contentId + '/property/' + encodeURIComponent(propName) + '?expand=version', - contentType: 'application/json;charset=UTF-8', - success: success, - error: error - }); -}; - -AC.setContentProperty = function(contentId, propName, propVal, propVersion, success, error) -{ - var obj = { - 'value': propVal - }; - - if (propVersion) - { - obj['version'] = { - 'number': propVersion + 1, - 'minorEdit': true - }; - } - else - { - obj['key'] = propName; - } - - AP.request({ - url: '/rest/api/content/' + contentId + '/property' + (propVersion? '/' + encodeURIComponent(propName) + '?expand=version' : ''), - type: propVersion? 'PUT' : 'POST', - contentType: 'application/json', - data: JSON.stringify(obj), - success: success, - error: error - }); -}; - -AC.getConfPageEditorVer = function(pageId, callback) -{ - AC.getContentProperty(pageId, 'editor', function(resp) - { - resp = JSON.parse(resp); - callback(resp.value == 'v2'? 2 : 1); - }, function() - { - callback(1);// On error, assume the old editor - }) -}; - -AC.gotoAnchor = function(anchor) -{ - AC.getPageInfo(false, function(info) - { - var url = info.url; - - if (url != null) - { - //remove any hash - var hash = url.indexOf('#'); - - if (hash > -1) - { - url = url.substring(0, hash); - } - - AC.getConfPageEditorVer(info.id, function(ver) - { - if (ver == 1) - { - //When page title has a [ at the beginning, conf adds id- to anchor name - url = url + '#' + (info.title.indexOf('[') == 0? 'id-' : '') + - encodeURI(info.title.replace(/\s/g, '') + '-' + anchor.replace(/\s/g, '')); - } - else - { - url = url + '#' + encodeURIComponent(anchor.replace(/\s/g, '-')); - } - - top.window.location = url; - }); - - } - }, function() - { - //ignore as we cannot get the page info - }); -}; - -AC.getDiagramRevisions = function(diagramName, pageId, success, error) -{ - AP.request({ - type: 'GET', - url: '/rest/api/content/' + pageId + '/child/attachment', - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - resp = JSON.parse(resp); - var attObj = null; - - for (var i = 0; i < resp.results.length; i++) - { - if (resp.results[i].title == diagramName) - { - attObj = resp.results[i]; - } - } - - if (attObj != null) - { - AP.request({ - type: 'GET', - url: '/rest/api/content/' + attObj.id + '/version', - contentType: 'application/json;charset=UTF-8', - success: function(resp) - { - resp = JSON.parse(resp); - var revs = []; - - for (var i = 0; i < resp.results.length; i++) - { - var rev = resp.results[i]; - - revs.unshift({ - modifiedDate: rev.when, - lastModifyingUserName: rev.by? rev.by.displayName : '', - downloadUrl: '/download/attachments/' + pageId + '/' + encodeURIComponent(diagramName) + '?version=' + rev.number, - obj: rev - }); - } - - success(revs); - }, - error: error - }); - } - else - { - error(); - } - }, - error: error - }); -}; - -AC.setHiResPreview = function(hiResPreview, success, error) -{ - AC.hiResPreview = hiResPreview; -}; - -AC.setAspect = function(aspect, success, error) -{ - AC.aspect = aspect; -}; - -AC.getAspectObj = function() -{ - if (AC.aspect != null) - { - var aspectArray = AC.aspect.split(' '); - - if (aspectArray.length > 1) - { - return {pageId: aspectArray[0], layerIds: aspectArray.slice(1)}; - } - } - - return {}; -}; - -AC.getAttachmentInfo = function(pageId, attName, sucess, error) -{ - AP.request({ - type: 'GET', - url: '/rest/api/content/' + pageId + '/child/attachment?expand=version&filename=' + - encodeURIComponent(attName), - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - var tmp = JSON.parse(resp); - - if (tmp.results && tmp.results.length == 1) - { - sucess(tmp.results[0]); - } - else - { - error({status: 404}); - } - }, - error: error - }); -}; - -//White-listed functions and some info about it -AC.remoteInvokableFns = { - getRecentDiagrams: {isAsync: true}, - searchDiagrams: {isAsync: true}, - getCustomLibraries: {isAsync: true}, - getFileContent: {isAsync: true}, - getCurrentUser: {isAsync: true}, - getOldComments: {isAsync: true}, - getComments: {isAsync: true}, - addComment: {isAsync: true}, - addCommentReply: {isAsync: true}, - editComment: {isAsync: true}, - deleteComment: {isAsync: true}, - userCanEdit: {isAsync: true}, - getCustomTemplates: {isAsync: true}, - getPageInfo: {isAsync: true}, - getDiagramRevisions: {isAsync: true}, - setHiResPreview: {isAsync: false}, - setAspect: {isAsync: false} -}; - -AC.remoteInvokeCallbacks = []; - -AC.handleRemoteInvokeResponse = function(msg) -{ - var msgMarkers = msg.msgMarkers; - var callback = AC.remoteInvokeCallbacks[msgMarkers.callbackId]; - - if (msg.error) - { - if (callback.error) callback.error(msg.error.errResp); - } - else if (callback.callback) - { - callback.callback.apply(this, msg.resp); - } - - AC.remoteInvokeCallbacks[msgMarkers.callbackId] = null; //set it to null only to keep the index -}; - -//Here, the editor is ready before sending init even which starts everything, so no need for waiting for ready message. Init is enough -AC.remoteInvoke = function(remoteFn, remoteFnArgs, msgMarkers, callback, error) -{ - msgMarkers = msgMarkers || {}; - msgMarkers.callbackId = AC.remoteInvokeCallbacks.length; - AC.remoteInvokeCallbacks.push({callback: callback, error: error}); - AC.remoteWin.postMessage(JSON.stringify({action: 'remoteInvoke', funtionName: remoteFn, functionArgs: remoteFnArgs, msgMarkers: msgMarkers}), '*'); -}; - -AC.handleRemoteInvoke = function(msg) -{ - function sendResponse(resp, error) - { - var respMsg = {action: 'remoteInvokeResponse', msgMarkers: msg.msgMarkers}; - - if (error != null) - { - respMsg.error = {errResp: error}; - } - else if (resp != null) - { - respMsg.resp = resp; - } - - AC.remoteWin.postMessage(JSON.stringify(respMsg), '*'); - } - - try - { - //Remote invoke are allowed to call functions in AC - var funtionName = msg.funtionName; - var functionInfo = AC.remoteInvokableFns[funtionName]; - - if (functionInfo != null && typeof AC[funtionName] === 'function') - { - var functionArgs = msg.functionArgs; - - //Confirm functionArgs are not null and is array, otherwise, discard it - if (!Array.isArray(functionArgs)) - { - functionArgs = []; - } - - //for functions with callbacks (async) we assume last two arguments are success, error - if (functionInfo.isAsync) - { - //success - functionArgs.push(function() - { - sendResponse(Array.prototype.slice.apply(arguments)); - }); - - //error - functionArgs.push(function(err) - { - sendResponse(null, err || mxResources.get('unknownError')); - }); - - AC[funtionName].apply(this, functionArgs); - } - else - { - var resp = AC[funtionName].apply(this, functionArgs); - - sendResponse([resp]); - } - } - else - { - sendResponse(null, mxResources.get('invalidCallFnNotFound', [funtionName])); - } - } - catch(e) - { - sendResponse(null, mxResources.get('invalidCallErrOccured', [e.message])); - } -}; - -//Allow loading of plugins (we need it for comments) -AC.plugins = []; - -window.Draw = new Object(); -window.Draw.loadPlugin = function(callback) -{ - AC.plugins.push(callback); -}; - -AC.loadPlugins = function(ui) -{ - for (var i = 0; i < AC.plugins.length; i++) - { - AC.plugins[i](ui); - } -}; \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/cs_CZ.json b/src/main/webapp/connect/confluence/i18n/cs_CZ.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/cs_CZ.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/da_DK.json b/src/main/webapp/connect/confluence/i18n/da_DK.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/da_DK.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/de_DE.json b/src/main/webapp/connect/confluence/i18n/de_DE.json deleted file mode 100644 index 9238b2ed..00000000 --- a/src/main/webapp/connect/confluence/i18n/de_DE.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Konfiguration", - "drawDiagrams": "draw.io Diagramme", - "drawioMacro": "draw.io Diagramm", - "drawDesc": "Fügt eine neues draw.io Diagramm ein", - "incDrawioMacro": "draw.io Diagramm einbetten", - "embedDesc": "Bestehendes draw.io Diagramm einbetten", - "legacyDrawioMacro": "Legacy Makro - bitte nicht verwenden", - "legacyDesc": "Bitte nicht verwenden", - "lightbox": "Vollbild", - "drawViewer": "draw.io Ansicht", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Startbildschirm Editor", - "diagramName": "Diagrammname (bitte nicht ändern)", - "automaticSize": "automatische Grösse", - "pPageID": "ID der übergeordneten Seite", - "baseUrl": "Confluence Basis URL", - "dWidth": "Diagrammbreite", - "dHeight": "Diagrammhöhe", - "macro.md.edit": "Markdown bearbeiten", - "macro.md.insert": "Markdown einfügen" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/en.json b/src/main/webapp/connect/confluence/i18n/en.json deleted file mode 100644 index b367d5b9..00000000 --- a/src/main/webapp/connect/confluence/i18n/en.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit Markdown", - "macro.md.insert": "Insert Markdown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/es_ES.json b/src/main/webapp/connect/confluence/i18n/es_ES.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/es_ES.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/et_EE.json b/src/main/webapp/connect/confluence/i18n/et_EE.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/et_EE.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/fi_FI.json b/src/main/webapp/connect/confluence/i18n/fi_FI.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/fi_FI.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/fr_FR.json b/src/main/webapp/connect/confluence/i18n/fr_FR.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/fr_FR.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/hu_HU.json b/src/main/webapp/connect/confluence/i18n/hu_HU.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/hu_HU.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/is_IS.json b/src/main/webapp/connect/confluence/i18n/is_IS.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/is_IS.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/it_IT.json b/src/main/webapp/connect/confluence/i18n/it_IT.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/it_IT.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/ja_JP.json b/src/main/webapp/connect/confluence/i18n/ja_JP.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/ja_JP.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/ko_KR.json b/src/main/webapp/connect/confluence/i18n/ko_KR.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/ko_KR.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/nl_NL.json b/src/main/webapp/connect/confluence/i18n/nl_NL.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/nl_NL.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/no_NO.json b/src/main/webapp/connect/confluence/i18n/no_NO.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/no_NO.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/pl_PL.json b/src/main/webapp/connect/confluence/i18n/pl_PL.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/pl_PL.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/pt_BR.json b/src/main/webapp/connect/confluence/i18n/pt_BR.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/pt_BR.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/ro_RO.json b/src/main/webapp/connect/confluence/i18n/ro_RO.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/ro_RO.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/ru_RU.json b/src/main/webapp/connect/confluence/i18n/ru_RU.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/ru_RU.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/sk_SK.json b/src/main/webapp/connect/confluence/i18n/sk_SK.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/sk_SK.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/sv_SE.json b/src/main/webapp/connect/confluence/i18n/sv_SE.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/sv_SE.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/i18n/zh_CN.json b/src/main/webapp/connect/confluence/i18n/zh_CN.json deleted file mode 100644 index df9b90b5..00000000 --- a/src/main/webapp/connect/confluence/i18n/zh_CN.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "gliffyImport": "draw.io Gliffy Import", - "drawConfig": "draw.io Configuration", - "drawDiagrams": "draw.io Diagrams", - "drawioMacro": "draw.io Diagram", - "drawDesc": "Inserts a new draw.io diagram", - "incDrawioMacro": "Embed draw.io diagram", - "embedDesc": "Embed an existing draw.io diagram", - "legacyDrawioMacro": "Legacy macro - do not use", - "legacyDesc": "Do not use", - "lightbox": "Lightbox", - "drawViewer": "draw.io Viewer", - "drawEditor": "draw.io Editor", - "drawSplashEditor": "draw.io Splash Editor", - "diagramName": "Diagram name (do not change)", - "automaticSize": "automatic size", - "pPageID": "Parent page ID", - "baseUrl": "Confluence Base URL", - "dWidth": "Diagram width", - "dHeight": "Diagram height", - "macro.md.edit": "Edit MarkDown", - "macro.md.insert": "Insert New MarkDown" -} \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/includeDiagram-1-4-8.js b/src/main/webapp/connect/confluence/includeDiagram-1-4-8.js deleted file mode 100644 index d3a378fb..00000000 --- a/src/main/webapp/connect/confluence/includeDiagram-1-4-8.js +++ /dev/null @@ -1,1283 +0,0 @@ -function includeDiagramMain(confPageId, draftPage) -{ - var EXPORT_URL = 'https://exp.draw.io/ImageExport4/export'; - var selectedDiagramInfo = null; - var theMacroData = null; - var selectedElt = null; - var activeTab = 'recent'; - var recentLoaded = false; - var searchLoaded = false; - var curViewer = null; - var attEditor, odEditor = null, gdEditor = null; - var gSelFileContent = null; - var gSelFileModifiedTS = null; - var gAttVer = null; - var async = false; - var editMode = false; - var gCsvFileContent = null; - - var opts = - { - lines: 12, // The number of lines to draw - length: 8, // The length of each line - width: 3, // The line thickness - radius: 5, // The radius of the inner circle - rotate: 0, // The rotation offset - color: '#000', // #rgb or #rrggbb - speed: 1, // Rounds per second - trail: 60, // Afterglow percentage - shadow: false, // Whether to render a shadow - hwaccel: false, // Whether to use hardware acceleration - className: 'spinner', // The CSS class to assign to the spinner - zIndex: 2e9 // The z-index (defaults to 2000000000) - }; - - var spinner = new Spinner(opts); - - function sha1 (str) - { - // discuss at: http://locutus.io/php/sha1/ - // original by: Webtoolkit.info (http://www.webtoolkit.info/) - // improved by: Michael White (http://getsprink.com) - // improved by: Kevin van Zonneveld (http://kvz.io) - // input by: Brett Zamir (http://brett-zamir.me) - // note 1: Keep in mind that in accordance with PHP, the whole string is buffered and then - // note 1: hashed. If available, we'd recommend using Node's native crypto modules directly - // note 1: in a steaming fashion for faster and more efficient hashing - // example 1: sha1('Kevin van Zonneveld') - // returns 1: '54916d2e62f65b3afa6e192e6a601cdbe5cb5897' - - var hash - try { - var crypto = require('crypto') - var sha1sum = crypto.createHash('sha1') - sha1sum.update(str) - hash = sha1sum.digest('hex') - } catch (e) { - hash = undefined - } - - if (hash !== undefined) { - return hash - } - - var _rotLeft = function (n, s) { - var t4 = (n << s) | (n >>> (32 - s)) - return t4 - } - - var _cvtHex = function (val) { - var str = '' - var i - var v - - for (i = 7; i >= 0; i--) { - v = (val >>> (i * 4)) & 0x0f - str += v.toString(16) - } - return str - } - - var blockstart - var i, j - var W = new Array(80) - var H0 = 0x67452301 - var H1 = 0xEFCDAB89 - var H2 = 0x98BADCFE - var H3 = 0x10325476 - var H4 = 0xC3D2E1F0 - var A, B, C, D, E - var temp - - // utf8_encode - str = unescape(encodeURIComponent(str)) - var strLen = str.length - - var wordArray = [] - for (i = 0; i < strLen - 3; i += 4) { - j = str.charCodeAt(i) << 24 | - str.charCodeAt(i + 1) << 16 | - str.charCodeAt(i + 2) << 8 | - str.charCodeAt(i + 3) - wordArray.push(j) - } - - switch (strLen % 4) { - case 0: - i = 0x080000000 - break - case 1: - i = str.charCodeAt(strLen - 1) << 24 | 0x0800000 - break - case 2: - i = str.charCodeAt(strLen - 2) << 24 | str.charCodeAt(strLen - 1) << 16 | 0x08000 - break - case 3: - i = str.charCodeAt(strLen - 3) << 24 | - str.charCodeAt(strLen - 2) << 16 | - str.charCodeAt(strLen - 1) << - 8 | 0x80 - break - } - - wordArray.push(i) - - while ((wordArray.length % 16) !== 14) { - wordArray.push(0) - } - - wordArray.push(strLen >>> 29) - wordArray.push((strLen << 3) & 0x0ffffffff) - - for (blockstart = 0; blockstart < wordArray.length; blockstart += 16) { - for (i = 0; i < 16; i++) { - W[i] = wordArray[blockstart + i] - } - for (i = 16; i <= 79; i++) { - W[i] = _rotLeft(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1) - } - - A = H0 - B = H1 - C = H2 - D = H3 - E = H4 - - for (i = 0; i <= 19; i++) { - temp = (_rotLeft(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff - E = D - D = C - C = _rotLeft(B, 30) - B = A - A = temp - } - - for (i = 20; i <= 39; i++) { - temp = (_rotLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff - E = D - D = C - C = _rotLeft(B, 30) - B = A - A = temp - } - - for (i = 40; i <= 59; i++) { - temp = (_rotLeft(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff - E = D - D = C - C = _rotLeft(B, 30) - B = A - A = temp - } - - for (i = 60; i <= 79; i++) { - temp = (_rotLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff - E = D - D = C - C = _rotLeft(B, 30) - B = A - A = temp - } - - H0 = (H0 + A) & 0x0ffffffff - H1 = (H1 + B) & 0x0ffffffff - H2 = (H2 + C) & 0x0ffffffff - H3 = (H3 + D) & 0x0ffffffff - H4 = (H4 + E) & 0x0ffffffff - } - - temp = _cvtHex(H0) + _cvtHex(H1) + _cvtHex(H2) + _cvtHex(H3) + _cvtHex(H4) - return temp.toLowerCase() - }; - - function showError(errMsg, nohide) - { - var errorMsg = document.getElementById('errorMsg'); - errorMsg.innerHTML = AC.htmlEntities(errMsg); - errorMsg.className = 'fade'; - - if (!nohide) - { - setTimeout(function() - { - errorMsg.className = ''; - }, 2000); - } - }; - - function onSelect() - { - if (activeTab == 'extUrl') - { - var hasErr = false; - - if (!diagramUrl.value) - { - diagramUrl.style.border = '1px solid red'; - hasErr = true; - } - - if (!diagramName.value) - { - diagramName.style.border = '1px solid red'; - hasErr = true; - } - - if (hasErr) - { - return; - } - - theMacroData = { - baseUrl: baseUrl, - diagramName: diagramName.value, - diagramDisplayName: diagramName.value, - diagramUrl: diagramUrl.value, - includedDiagram: 1 - }; - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - } - else if (activeTab == 'csvImp') - { - var hasErr = false; - - if (!csvFileUrl.value) - { - csvFileUrl.style.border = '1px solid red'; - hasErr = true; - } - - if (!csvDiagName.value) - { - csvDiagName.style.border = '1px solid red'; - hasErr = true; - } - - if (hasErr) - { - return; - } - - theMacroData = { - baseUrl: baseUrl, - diagramName: csvDiagName.value, - diagramDisplayName: csvDiagName.value, - csvFileUrl: csvFileUrl.value, - includedDiagram: 1 - }; - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - } - else if (activeTab == 'gDrive') - { - gdEditor.doSubmit(); - } - else if (activeTab == 'oneDrive') - { - odEditor.doSubmit(); - } - else if (activeTab == 'upload') - { - attEditor.doSubmit(); - } - else if (selectedDiagramInfo != null) - { - var info = selectedDiagramInfo.info; - theMacroData = { - diagramName: info.name, - diagramDisplayName: info.displayName, - pageId: info.pageId, - custContentId: info.contentId || info.custContentId, - baseUrl: baseUrl, - includedDiagram: 1 - }; - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - } - else - { - showError('Please select a diagram to insert it.'); - } - }; - - function onSubmit() - { - if (activeTab == 'current') - { - if (theMacroData != null && curViewer != null) - { - spinner.spin(document.getElementById('current')); - AP.dialog.getButton('submit').disable(); - var aspectHash = null; - - if (!theMacroData.csvFileUrl) - { - var layerIds = [], pageId = curViewer.diagrams[curViewer.currentPage].getAttribute('id'); - - var model = curViewer.graph.getModel(); - var childCount = model.getChildCount(model.root); - - // Get visible layers - for (var i = 0; i < childCount; i++) - { - var layer = model.getChildAt(model.root, i); - - if (model.isVisible(layer)) - { - layerIds.push(layer.id); - } - } - - var aspect = pageId + ' ' + layerIds.join(' '); - aspectHash = sha1(aspect); - theMacroData.aspect = aspect; - theMacroData.aspectHash = aspectHash; - } - - theMacroData.imgPageId = confPageId; - - var bounds = curViewer.graph.view.graphBounds; - theMacroData.width = Math.round(bounds.width) || null; - theMacroData.height = Math.round(bounds.height) || null; - - function saveMacro() - { - AP.confluence.saveMacro(theMacroData); - AP.confluence.closeMacroEditor(); - }; - - function saveError() - { - spinner.stop(); - AP.dialog.getButton('submit').enable(); - showError('Saving failed, please try again later.') - }; - - function doSaveImage(imageData) - { - if (imageData == null) - { - saveError(); - return; - } - - AC.saveDiagram(confPageId, theMacroData.diagramName + (aspectHash? '-' + aspectHash : '') + '.png', AC.b64toBlob(imageData, 'image/png'), - saveMacro, saveError, false, 'image/png', 'draw.io aspect image' + (gAttVer != null? ' - ' + gAttVer : ''), false, draftPage); - }; - - function serverFallback() - { - - var acceptResponse = true; - - var timeoutThread = window.setTimeout(function() - { - acceptResponse = false; - doSaveImage(null); - }, 25000); - - var req = new mxXmlRequest(EXPORT_URL, 'format=png&base64=1' + - (layerIds != null? '&extras=' + encodeURIComponent(JSON.stringify({layerIds: layerIds})) : '') + - (pageId != null? '&pageId=' + pageId : '') + '&xml=' + encodeURIComponent(curViewer.xml)); - - req.send(function(req) - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - doSaveImage(req.getStatus() >= 200 && req.getStatus() <= 299? req.getText() : null); - } - }, - function() - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - doSaveImage(null); - } - }); - - }; - - function startSaving() - { - if (curViewer.editor.isExportToCanvas()) - { - curViewer.editor.exportToCanvas(function(canvas) - { - var data = canvas.toDataURL('image/png'); - doSaveImage(data.substring(data.lastIndexOf(',') + 1)); - } - , null, null, null, serverFallback); - } - else - { - serverFallback(); - } - }; - - //No caching is needed when referring to another conf diagram - if (theMacroData.service != null || theMacroData.csvFileUrl != null || theMacroData.diagramUrl != null) - { - function saveDiagram() - { - AC.saveDiagram(confPageId, theMacroData.diagramName, gSelFileContent, - startSaving, function(resp) - { - showError('Unexpected error. Cannot cannot save cached file'); - }, false, 'application/vnd.jgraph.mxfile.cached', 'Embedded draw.io diagram' + (gSelFileModifiedTS != null ? ' - ' + gSelFileModifiedTS : ''), false, draftPage); - }; - - function doSave() - { - if (theMacroData.csvFileUrl) - { - AC.saveDiagram(confPageId, theMacroData.diagramName + '.csv', gCsvFileContent, - saveDiagram, function(resp) - { - showError('Unexpected error. Cannot cannot save cached file'); - }, false, 'text/csv', 'Embedded draw.io diagram (CSV)', false, draftPage); - } - else - { - saveDiagram(); - } - }; - - if (editMode) - { - doSave() - } - else - { - //Confirm filename is unique for new files - AC.getPageAttachments(confPageId, function(attachments) - { - var fileExists = false; - var lc = theMacroData.diagramName.toLowerCase(); - - // Checks if any files will be overwritten - for (var i = 0; i < attachments.length && !fileExists; i++) - { - var an = attachments[i].title.toLowerCase(); - - if (an == lc) - { - fileExists = true; - } - } - - if (fileExists) - { - //Make filename unique - theMacroData.diagramName = Date.now() + '-' + theMacroData.diagramName; - } - - doSave(); - }, function(res) - { - showError('Unexpected error. Cannot cannot save cached file'); - }); - } - } - else - { - startSaving(); - } - } - else - { - showError('Unexpected error. Cannot show diagram'); - } - } - else - { - showError('Please select a diagram to insert it.'); - } - }; - - function deselectDiagram() - { - selectedDiagramInfo = null; - - if (selectedElt != null) - { - selectedElt.style.backgroundColor = 'transparent'; - selectedElt.style.border = '1px solid #ddd'; - } - }; - - function fillDiagramsList(list, listDiv, top, emptyMsg) - { - listDiv.innerHTML = ''; - var div = document.createElement('div'); - div.style.border = '1px solid #d3d3d3'; - div.style.margin = '6px 0 0 -1px'; - div.style.padding = '6px'; - div.style.overflow = 'auto'; - div.style.position = 'absolute'; - div.style.bottom = '10px'; - div.style.right = '10px'; - div.style.left = '10px'; - div.style.top = top + 'px'; - - var w = 140; - var h = 140; - - function selectElement(elt, infoObj) - { - deselectDiagram(); - - selectedElt = elt; - selectedDiagramInfo = infoObj; - - selectedElt.style.backgroundColor = '#e6eff8'; - selectedElt.style.border = '2px solid #ccd9ea'; - }; - - function addButton(url, imgUrl, tooltip, infoObj) - { - var elt = document.createElement('div'); - elt.className = 'diagram'; - elt.style.height = w + 'px'; - elt.style.width = h + 'px'; - - elt.setAttribute('title', tooltip); - - elt.style.backgroundImage = 'url(' + imgUrl + ')'; - elt.style.backgroundSize = 'contain'; - elt.style.backgroundPosition = 'center center'; - elt.style.backgroundRepeat = 'no-repeat'; - - elt.addEventListener('click', function(evt) - { - selectElement(elt, infoObj); - }); - - elt.addEventListener('dblclick', function(evt) - { - selectedDiagramInfo = infoObj; - onSelect(); - }); - - div.appendChild(elt); - } - - for (var i = 0; i < list.length; i++) - { - addButton(list[i].url, list[i].imgUrl, list[i].title, list[i]); - } - - if (list.length == 0 && emptyMsg) - { - var msg = document.createElement('div'); - msg.style.width = '100%'; - msg.style.height = '100%'; - msg.style.textAlign = 'center'; - msg.innerHTML = AC.htmlEntities(emptyMsg); - - div.appendChild(msg); - } - - listDiv.appendChild(div); - return div; - } - - function activateTab() - { - deselectDiagram(); - showError('', true); - AP.dialog.getButton('selectBtn').show(); - AP.dialog.getButton('submit').hide(); - AP.dialog.getButton('submit').disable(); - - switch (activeTab) - { - case 'recent': - if (!recentLoaded) - { - recentLoaded = true; - AC.getRecentDiagrams(function(retList) - { - fillDiagramsList(retList, document.getElementById('recentList'), 50, 'No recent diagrams found!'); - }, function() - { - showError('Failed to fetch recent diagrams.', true); - }); - } - break; - case 'search': - if (!searchLoaded) - { - searchLoaded = true; - //fill the div with empty box - fillDiagramsList([], document.getElementById('searchList'), 80, 'Use the search box to find draw.io diagrams'); - } - break; - case 'gDrive': - if (gdEditor == null) - { - gdEditor = new GDriveEditor(function(selectedFile, width, height, autoSize, selFileContent) - { - gSelFileContent = selFileContent; - gSelFileModifiedTS = new Date(selectedFile.modifiedDate).getTime(); - gAttVer = null; - editMode = false; - //Upload is the same as embedding an existing draw.io macro but without content id - theMacroData = { - diagramName: selectedFile.title, - diagramDisplayName: selectedFile.title, - pageId: confPageId, - baseUrl: baseUrl, - service: 'GDrive', - sFileId: selectedFile.id, - aspect: selectedFile.aspect, - includedDiagram: 1 - }; - - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - }, null, 'GD', true, true); - } - else - { - gdEditor.spinner.stop(); - } - break; - case 'oneDrive': - if (odEditor == null) - { - odEditor = new OneDriveEditor(function(selectedFile, width, height, autoSize, selFileContent) - { - gSelFileContent = selFileContent; - gSelFileModifiedTS = new Date(selectedFile.lastModifiedDateTime).getTime(); - gAttVer = null; - editMode = false; - //Upload is the same as embedding an existing draw.io macro but without content id - theMacroData = { - diagramName: selectedFile.name, - diagramDisplayName: selectedFile.name, - pageId: confPageId, - baseUrl: baseUrl, - service: 'OneDrive', - sFileId: selectedFile.id, - odriveId: selectedFile.parentReference.driveId, - aspect: selectedFile.aspect, - includedDiagram: 1 - }; - - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - }, null, 'OD', true, true); - } - else - { - odEditor.spinner.stop(); - } - break; - case 'upload': - attEditor.spinner.stop(); - break; - case 'current': - AP.dialog.getButton('selectBtn').hide(); - AP.dialog.getButton('submit').show(); - - var div = document.getElementById('current'); - div.innerHTML = ''; - var container = document.createElement('div'); - // NOTE: Height must be specified with default value "auto" to force automatic fit in viewer - container.style.cssText = 'position:absolute;width:100%;height:auto;bottom:0px;top:45px;border:1px solid transparent;'; - div.appendChild(container); - spinner.spin(div); - - var pageId, layerIds; - - if (theMacroData.aspect != null) - { - var aspectArray = theMacroData.aspect.split(' '); - - if (aspectArray.length > 1) - { - pageId = aspectArray[0]; - layerIds = aspectArray.slice(1); - } - } - - function showFile(fileContent) - { - if (!async) - { - var doc = mxUtils.parseXml(fileContent); - - curViewer = new GraphViewer(container, doc.documentElement, - {highlight: '#3572b0', border: 8, 'auto-fit': true, - resize: false, nav: true, lightbox: false, title: (theMacroData.diagramDisplayName || theMacroData.diagramName), - 'toolbar-nohide': true, 'toolbar-position': 'top', toolbar: 'pages layers', - pageId: pageId, layerIds: layerIds - }); - - spinner.stop(); - AP.dialog.getButton('submit').enable(); - } - }; - - if (theMacroData.diagramUrl) - { - if (gSelFileContent == null) - { - processDiagramUrl(div, function(fileContent) - { - showFile(fileContent); - }); - } - else - { - showFile(gSelFileContent); - } - } - else if (theMacroData.csvFileUrl) - { - if (gSelFileContent == null) - { - processCsvUrl(div, function(fileContent) - { - showFile(fileContent); - }); - } - else - { - showFile(gSelFileContent); - } - } - else if (theMacroData.service != null && gSelFileContent != null) - { - showFile(gSelFileContent); - } - else - { - //Get version - AC.getAttachmentInfo(theMacroData.pageId, theMacroData.diagramName, function(info) - { - gAttVer = info.version.number; - - AP.request({ - url: '/download/attachments/' + theMacroData.pageId + '/' + encodeURIComponent(theMacroData.diagramName), - success: showFile, - error : function() - { - showError('Cannot read the specified diagram. Please check you have read permission on that file.', true); - } - }); - }, function() - { - showError('Cannot fetch diagram info. Please check you have read permission on that file.', true); - }); - } - break; - default: - gSelFileContent = null; - } - } - - function openTab(evt) - { - var tabName = this.getAttribute('data-tabContetn'); - // Declare all variables - var i, tabcontent, tablinks; - - // Get all elements with class='tabcontent' and hide them - tabcontent = document.getElementsByClassName('tabcontent'); - for (i = 0; i < tabcontent.length; i++) { - tabcontent[i].style.display = 'none'; - } - - // Get all elements with class='tablinks' and remove the class 'active' - tablinks = document.getElementsByClassName('tablinks'); - for (i = 0; i < tablinks.length; i++) { - tablinks[i].className = tablinks[i].className.replace(' active', ''); - } - - // Show the current tab, and add an 'active' class to the button that opened the tab - document.getElementById(tabName).style.display = 'block'; - evt.currentTarget.className += ' active'; - - activeTab = tabName; - activateTab(); - } - - function doSearch() - { - var searchList = document.getElementById('searchList'); - var searchStr = document.getElementById('searchStr').value; - - if (searchStr != null && searchStr.length > 0) - { - spinner.spin(searchList); - - AC.searchDiagrams(searchStr, function(retList) - { - spinner.stop(); - fillDiagramsList(retList, searchList, 80, 'No diagrams found!'); - }, function() - { - showError('Searching failed. Please try again later.', true); - }); - } - else - { - showError('Please type a search string.'); - } - }; - - //=======Upload========== - attEditor = new AttViewerEditor(function(selectedFile, selFileContent, editedFile, width, height, autoSize, isDrawio, aspect, onError) - { - //We only have add in Jira - if (selectedFile != null) - { - gSelFileContent = selFileContent; - gSelFileModifiedTS = null; - gAttVer = null; - editMode = false; - //Upload is the same as embedding an existing draw.io macro but without content id - theMacroData = { - diagramName: selectedFile.name, - diagramDisplayName: selectedFile.name, - pageId: confPageId, - baseUrl: baseUrl, - service: 'AttFile', - aspect: aspect, - includedDiagram: 1 - }; - - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - } - }, null, 'UD', true, true); - - //Staring the editor - //Setting events listeners - document.getElementById('searchBtn').addEventListener('click', doSearch); - document.getElementById('searchStr').addEventListener('keypress', function(e) - { - if (e.keyCode == 13) doSearch(); - }); - - function renderDiagram(div, doc, title) - { - div.innerHTML = ''; - var container = document.createElement('div'); - // NOTE: Height must be specified with default value "auto" to force automatic fit in viewer - container.style.cssText = 'position:absolute;width:auto;left:0px;right:0px;height:auto;bottom:0px;top:0px;border:1px solid transparent;'; - div.appendChild(container); - - new GraphViewer(container, doc, - {highlight: '#3572b0', border: 8, 'auto-fit': true, - resize: false, nav: true, lightbox: false, title: title, - 'toolbar-nohide': true, 'toolbar-position': 'top', toolbar: 'pages layers', - }); - }; - - - document.getElementById('showDiagBtn').addEventListener('click', showDiagFromUrl); - - function resetBorder() - { - if (this.value) - this.style.border = ''; - - //Reset file content on urrl change - if (this.id.indexOf('Url') > 0) - { - gSelFileContent = null; - csvModel = null; - } - }; - - //TODO Optimize extUrl and Csv code as they are very similar. Also, showFile is similar (conf server code is better) - var diagramUrl = document.getElementById('diagramUrl'); - var diagramName = document.getElementById('diagramName'); - - diagramUrl.addEventListener('keypress', resetBorder); - diagramName.addEventListener('keypress', resetBorder); - diagramUrl.addEventListener('change', resetBorder); - diagramName.addEventListener('change', resetBorder); - - var csvFileUrl = document.getElementById('csvFileUrl'); - var csvDiagName = document.getElementById('csvDiagName'); - - csvFileUrl.addEventListener('keypress', resetBorder); - csvDiagName.addEventListener('keypress', resetBorder); - csvFileUrl.addEventListener('change', resetBorder); - csvDiagName.addEventListener('change', resetBorder); - - function processDiagramUrl(div, callback) - { - spinner.spin(div); - - mxUtils.get(diagramUrl.value, function(req) - { - if (req.getStatus() >= 200 && req.getStatus() <= 299) - { - try - { - gSelFileContent = req.getText(); - - if (callback) - { - callback(gSelFileContent); - } - else - { - renderDiagram(div, mxUtils.parseXml(gSelFileContent).documentElement, diagramName.value); - } - } - catch(e) - { - showError('Unsupported file. Please check the specified URL', true); - spinner.stop(); - } - } - else - { - showError('Diagram not found or cannot be accessed. Please check the specified URL', true); - spinner.stop(); - } - }); - }; - - function showDiagFromUrl(e) - { - e.preventDefault(); - - if (!diagramUrl.value) - { - diagramUrl.style.border = '1px solid red'; - return; - } - - processDiagramUrl(document.getElementById('extUrlDiagram')); - }; - - function processCsvUrl(div, callback) - { - spinner.spin(div); - - mxUtils.get(csvFileUrl.value, function(req) - { - if (req.getStatus() >= 200 && req.getStatus() <= 299) - { - try - { - gCsvFileContent = req.getText(); - - AC.importCsv(gCsvFileContent, function(csvModel, xml) - { - gSelFileContent = xml; - - if (callback) - { - callback(gSelFileContent, gCsvFileContent); - } - else - { - renderDiagram(div, csvModel, csvDiagName.value); - } - }, - function() - { - showError('Unsupported format. Please check the specified URL', true); - spinner.stop(); - }); - } - catch(e) - { - showError('Unsupported format. Please check the specified URL', true); - spinner.stop(); - } - } - else - { - showError('CSV file not found or cannot be accessed. Please check the specified URL', true); - spinner.stop(); - } - }); - }; - - document.getElementById('convertBtn').addEventListener('click', function(e) - { - e.preventDefault(); - - if (!csvFileUrl.value) - { - csvFileUrl.style.border = '1px solid red'; - return; - } - - processCsvUrl(document.getElementById('csvDiagram')); - }); - - var tabs = document.getElementsByClassName('tablinks'); - - for (var i = 0; i < tabs.length; i++) - { - tabs[i].addEventListener('click', openTab); - } - - AP.sizeToParent(true); - - AP.confluence.getMacroData(function (macroData) - { - if (macroData != null && macroData.includedDiagram != null) - { - theMacroData = macroData; - editMode = true; - - if (macroData.diagramUrl) - { - diagramUrl.value = macroData.diagramUrl; - diagramName.value = macroData.diagramName; - } - else if (macroData.csvFileUrl) - { - csvFileUrl.value = macroData.csvFileUrl; - csvDiagName.value = macroData.diagramName; - } - - function extractFileContents(resp, isPng) - { - if (isPng) - { - resp = 'data:image/png;base64,' + Editor.base64Encode (resp); - resp = AC.extractGraphModelFromPng(resp); - } - - gSelFileContent = resp; - async = false; - document.getElementById('currentTab').click(); - }; - - async = true; - gSelFileContent = ''; //To prevent fetching the cached file - - //Update file - if (macroData.service == 'GDrive') - { - GAC.getFileInfo(macroData.sFileId, function(fileInfo) - { - var isPng = fileInfo.mimeType == 'image/png'; - gSelFileModifiedTS = new Date(fileInfo.modifiedDate).getTime(); - - GAC.doAuthRequestPlain(fileInfo['downloadUrl'], 'GET', null, function(req) - { - extractFileContents(req.responseText, isPng); - }, function() - { - showError('Cannot read "' + fileInfo.title + '" file from Google Drive.', true); - }, null, isPng); - }, function() - { - showError('Fetching file info from Google Drive failed.', true); - }); - } - else if (macroData.service == 'OneDrive') - { - AC.getFileInfo(macroData.sFileId, macroData.odriveId, function(fileInfo) - { - var isPng = fileInfo.file.mimeType == 'image/png'; - gSelFileModifiedTS = new Date(fileInfo.lastModifiedDateTime).getTime(); - - var req = new XMLHttpRequest(); - req.open('GET', fileInfo['@microsoft.graph.downloadUrl']); - - req.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - extractFileContents(req.responseText, isPng); - } - else - { - showError('Cannot read "' + fileInfo.name + '" file from OneDrive.', true); - } - } - }; - - if (isPng && req.overrideMimeType) - { - req.overrideMimeType('text/plain; charset=x-user-defined'); - } - - req.send(); - }, function() - { - showError('Fetching file info from OneDrive failed.', true); - }); - } - else if (macroData.service == 'AttFile') - { - AP.request({ - url: '/download/attachments/' + theMacroData.pageId + '/' + encodeURIComponent(theMacroData.diagramName), - success: function(resp) - { - extractFileContents(resp); - }, - error : function() - { - showError('Cannot read the uploaded diagram.', true); - } - }); - } - else - { - async = false; - gSelFileContent = null; - } - - document.getElementById('currentTab').click(); - } - else - { - document.getElementById('currentTab').style.display = 'none'; - document.getElementById('recentTab').click(); - } - }); - - var selectBtn = AP.dialog.createButton({ - text: 'Select...', - identifier: 'selectBtn' - }); - selectBtn.bind(onSelect); - - AP.dialog.disableCloseOnSubmit(); - AP.events.on('dialog.submit', onSubmit); - AP.dialog.getButton('submit').hide(); - AP.dialog.getButton('submit').disable(); -}; - -//Logs uncaught errors -window.onerror = function(message, url, linenumber, colno, err) -{ - message = 'Confluence Cloud Embed Editor: ' + ((message != null) ? message : ''); - - AC.logError(message, url, linenumber, colno, err); -}; - -var xdm_e = AC.getSiteUrl(); -var license = AC.getUrlParam('lic', false); -var baseUrl = AC.getBaseUrl(); //TODO FIXME search and recent depends on having baseUrl global -var connectUrl = baseUrl + '/atlassian-connect'; -var head = document.getElementsByTagName('head')[0]; -var licenseValid = true; - -var script = document.createElement('script'); -script.setAttribute('data-options', 'resize:false;margin:false'); - -if (license != null && xdm_e != null) -{ - if (license == 'none') - { - var hostParse = document.createElement('a'); - hostParse.href = xdm_e; - var hostname = hostParse.hostname; - - if (hostname != null) - { - if (hostname.indexOf('.ngrok.io') > -1) - { - console.log("License status = ", license); - } - else - { - var xhr = new XMLHttpRequest(); - - xhr.onreadystatechange = function() - { - if (xhr.readyState == XMLHttpRequest.DONE && xhr.status >= 200 && xhr.status <= 299) - { - var resp = xhr.responseText; - - if (resp != null && resp.length > 0) - { - var lic = JSON.parse(resp); - - if (lic != null && lic.atlasCloudLic != null) - { - licenseValid = true; - } - } - } - }; - - xhr.open('POST', '/license?domain=' + hostname, true); - xhr.send(null); - } - } - } - else - { - licenseValid = true; - } -} - -// Adds event listeners -document.getElementById('gdAnchor').onclick = function() -{ - document.getElementById('filePickerGD').click(); -}; - -document.getElementById('odAnchor').onclick = function() -{ - document.getElementById('filePickerOD').click(); -}; - -document.getElementById('fileUploadAnchor').onclick = function() -{ - document.getElementById('fileuploadUD').click(); -}; - -// Main -script.onload = function() -{ - if (!licenseValid) - { - setTimeout(function() - { - if (!licenseValid) - { - alert("Please install a license for the draw.io app"); - AP.confluence.closeMacroEditor(); - } - }, 3000); - } - - //start the macro editro - AP.navigator.getLocation(function (data) - { - if (data != null && data.context != null) - { - var draftPage = (data.target == 'contentcreate'); - var pageId = data.context.contentId; - - includeDiagramMain(pageId, draftPage); - } - else - { - alert('Unexpected Error: Cannot get content id or type.'); - } - }); -}; - -script.src = 'https://connect-cdn.atl-paas.net/all.js'; -head.appendChild(script); - -var link = document.createElement('link'); -link.type = 'text/css'; -link.rel = 'stylesheet'; -link.href = connectUrl + '/all.css'; -head.appendChild(link); diff --git a/src/main/webapp/connect/confluence/includeDiagram.html b/src/main/webapp/connect/confluence/includeDiagram.html deleted file mode 100644 index a35ba3b3..00000000 --- a/src/main/webapp/connect/confluence/includeDiagram.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - -Include draw.io Diagram - - - - - - - - - - - - - -
- - - - - - - - -
- - -
-
- -
-
- -
-
- - - -
-
-
-
- - - -
-
Google Drive file name
-
-
-
-
- -
Width of the viewer (px)
-
-
-
- -
Height of the viewer (px)
-
-
-
- - -
-
- -
- -
-
-
- - -
-
- Sign Out -
-
- -
- -
-
-
-
- - - -
-
OneDrive file name
-
-
-
-
- -
Width of the viewer (px)
-
-
-
- -
Height of the viewer (px)
-
-
-
- - -
-
- -
- -
-
-
- - -
-
- Sign Out -
-
- -
- -
-
-
-
- - - - -
-
Diagram file name
-
-
-
-
- -
Width of the viewer (px)
-
-
-
- -
Height of the viewer (px)
-
-
-
- - -
-
-
-
-
-
- -
- -
-
-
-
- -
- -
- -
-
-
-
-
-
- Diagram Preview -
-
-
-
-
-
- -
- -
- -
-
-
-
-
-
- Diagram Preview -
-
-
- -
- - - diff --git a/src/main/webapp/connect/confluence/includeDiagram.js b/src/main/webapp/connect/confluence/includeDiagram.js deleted file mode 100644 index 4f3c07db..00000000 --- a/src/main/webapp/connect/confluence/includeDiagram.js +++ /dev/null @@ -1,985 +0,0 @@ -function includeDiagramMain(confPageId, draftPage) -{ - var EXPORT_URL = 'https://exp.draw.io/ImageExport4/export'; - var selectedDiagramInfo = null; - var theMacroData = null; - var selectedElt = null; - var activeTab = 'recent'; - var recentLoaded = false; - var searchLoaded = false; - var curViewer = null; - var attEditor, odEditor = null, gdEditor = null; - var gSelFileContent = null; - var gSelFileModifiedTS = null; - var gAttVer = null; - var async = false; - var editMode = false; - - var opts = - { - lines: 12, // The number of lines to draw - length: 8, // The length of each line - width: 3, // The line thickness - radius: 5, // The radius of the inner circle - rotate: 0, // The rotation offset - color: '#000', // #rgb or #rrggbb - speed: 1, // Rounds per second - trail: 60, // Afterglow percentage - shadow: false, // Whether to render a shadow - hwaccel: false, // Whether to use hardware acceleration - className: 'spinner', // The CSS class to assign to the spinner - zIndex: 2e9 // The z-index (defaults to 2000000000) - }; - - var spinner = new Spinner(opts); - - function sha1 (str) - { - // discuss at: http://locutus.io/php/sha1/ - // original by: Webtoolkit.info (http://www.webtoolkit.info/) - // improved by: Michael White (http://getsprink.com) - // improved by: Kevin van Zonneveld (http://kvz.io) - // input by: Brett Zamir (http://brett-zamir.me) - // note 1: Keep in mind that in accordance with PHP, the whole string is buffered and then - // note 1: hashed. If available, we'd recommend using Node's native crypto modules directly - // note 1: in a steaming fashion for faster and more efficient hashing - // example 1: sha1('Kevin van Zonneveld') - // returns 1: '54916d2e62f65b3afa6e192e6a601cdbe5cb5897' - - var hash - try { - var crypto = require('crypto') - var sha1sum = crypto.createHash('sha1') - sha1sum.update(str) - hash = sha1sum.digest('hex') - } catch (e) { - hash = undefined - } - - if (hash !== undefined) { - return hash - } - - var _rotLeft = function (n, s) { - var t4 = (n << s) | (n >>> (32 - s)) - return t4 - } - - var _cvtHex = function (val) { - var str = '' - var i - var v - - for (i = 7; i >= 0; i--) { - v = (val >>> (i * 4)) & 0x0f - str += v.toString(16) - } - return str - } - - var blockstart - var i, j - var W = new Array(80) - var H0 = 0x67452301 - var H1 = 0xEFCDAB89 - var H2 = 0x98BADCFE - var H3 = 0x10325476 - var H4 = 0xC3D2E1F0 - var A, B, C, D, E - var temp - - // utf8_encode - str = unescape(encodeURIComponent(str)) - var strLen = str.length - - var wordArray = [] - for (i = 0; i < strLen - 3; i += 4) { - j = str.charCodeAt(i) << 24 | - str.charCodeAt(i + 1) << 16 | - str.charCodeAt(i + 2) << 8 | - str.charCodeAt(i + 3) - wordArray.push(j) - } - - switch (strLen % 4) { - case 0: - i = 0x080000000 - break - case 1: - i = str.charCodeAt(strLen - 1) << 24 | 0x0800000 - break - case 2: - i = str.charCodeAt(strLen - 2) << 24 | str.charCodeAt(strLen - 1) << 16 | 0x08000 - break - case 3: - i = str.charCodeAt(strLen - 3) << 24 | - str.charCodeAt(strLen - 2) << 16 | - str.charCodeAt(strLen - 1) << - 8 | 0x80 - break - } - - wordArray.push(i) - - while ((wordArray.length % 16) !== 14) { - wordArray.push(0) - } - - wordArray.push(strLen >>> 29) - wordArray.push((strLen << 3) & 0x0ffffffff) - - for (blockstart = 0; blockstart < wordArray.length; blockstart += 16) { - for (i = 0; i < 16; i++) { - W[i] = wordArray[blockstart + i] - } - for (i = 16; i <= 79; i++) { - W[i] = _rotLeft(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1) - } - - A = H0 - B = H1 - C = H2 - D = H3 - E = H4 - - for (i = 0; i <= 19; i++) { - temp = (_rotLeft(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff - E = D - D = C - C = _rotLeft(B, 30) - B = A - A = temp - } - - for (i = 20; i <= 39; i++) { - temp = (_rotLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff - E = D - D = C - C = _rotLeft(B, 30) - B = A - A = temp - } - - for (i = 40; i <= 59; i++) { - temp = (_rotLeft(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff - E = D - D = C - C = _rotLeft(B, 30) - B = A - A = temp - } - - for (i = 60; i <= 79; i++) { - temp = (_rotLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff - E = D - D = C - C = _rotLeft(B, 30) - B = A - A = temp - } - - H0 = (H0 + A) & 0x0ffffffff - H1 = (H1 + B) & 0x0ffffffff - H2 = (H2 + C) & 0x0ffffffff - H3 = (H3 + D) & 0x0ffffffff - H4 = (H4 + E) & 0x0ffffffff - } - - temp = _cvtHex(H0) + _cvtHex(H1) + _cvtHex(H2) + _cvtHex(H3) + _cvtHex(H4) - return temp.toLowerCase() - }; - - function showError(errMsg, nohide) - { - var errorMsg = document.getElementById('errorMsg'); - errorMsg.innerHTML = AC.htmlEntities(errMsg); - errorMsg.className = 'fade'; - - if (!nohide) - { - setTimeout(function() - { - errorMsg.className = ''; - }, 2000); - } - }; - - function onSelect() - { - if (activeTab == 'extUrl') - { - var hasErr = false; - var diagramUrl = document.getElementById('diagramUrl'); - - if (!diagramUrl.value) - { - diagramUrl.style.border = '1px solid red'; - hasErr = true; - } - - var diagramName = document.getElementById('diagramName'); - - if (!diagramName.value) - { - diagramName.style.border = '1px solid red'; - hasErr = true; - } - - if (hasErr) - { - return; - } - - theMacroData = { - baseUrl: baseUrl, - diagramName: diagramName.value, - diagramDisplayName: diagramName.value, - diagramUrl: diagramUrl.value, - includedDiagram: 1 - }; - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - } - else if (activeTab == 'gDrive') - { - gdEditor.doSubmit(); - } - else if (activeTab == 'oneDrive') - { - odEditor.doSubmit(); - } - else if (activeTab == 'upload') - { - attEditor.doSubmit(); - } - else if (selectedDiagramInfo != null) - { - var info = selectedDiagramInfo.info; - theMacroData = { - diagramName: info.name, - diagramDisplayName: info.displayName, - pageId: info.pageId, - custContentId: info.contentId || info.custContentId, - baseUrl: baseUrl, - includedDiagram: 1 - }; - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - } - else - { - showError('Please select a diagram to insert it.'); - } - }; - - function onSubmit() - { - if (activeTab == 'current') - { - if (theMacroData != null && curViewer != null) - { - spinner.spin(document.getElementById('current')); - AP.dialog.getButton('submit').disable(); - - var layerIds = [], pageId = curViewer.diagrams[curViewer.currentPage].getAttribute('id'); - - var model = curViewer.graph.getModel(); - var childCount = model.getChildCount(model.root); - - // Get visible layers - for (var i = 0; i < childCount; i++) - { - var layer = model.getChildAt(model.root, i); - - if (model.isVisible(layer)) - { - layerIds.push(layer.id); - } - } - - var aspect = pageId + ' ' + layerIds.join(' '); - var aspectHash = sha1(aspect); - theMacroData.aspect = aspect; - theMacroData.aspectHash = aspectHash; - theMacroData.imgPageId = confPageId; - - var bounds = curViewer.graph.view.graphBounds; - theMacroData.width = Math.round(bounds.width) || null; - theMacroData.height = Math.round(bounds.height) || null; - - function saveMacro() - { - AP.confluence.saveMacro(theMacroData); - AP.confluence.closeMacroEditor(); - }; - - function saveError() - { - spinner.stop(); - AP.dialog.getButton('submit').enable(); - showError('Saving failed, please try again later.') - }; - - function doSaveImage(imageData) - { - if (imageData == null) - { - saveError(); - return; - } - - AC.saveDiagram(confPageId, theMacroData.diagramName + '-' + aspectHash + '.png', AC.b64toBlob(imageData, 'image/png'), - saveMacro, saveError, false, 'image/png', 'draw.io aspect image' + (gAttVer != null? ' - ' + gAttVer : ''), false, draftPage); - }; - - function serverFallback() - { - - var acceptResponse = true; - - var timeoutThread = window.setTimeout(function() - { - acceptResponse = false; - doSaveImage(null); - }, 25000); - - var req = new mxXmlRequest(EXPORT_URL, 'format=png&base64=1' + - (layerIds != null? '&extras=' + encodeURIComponent(JSON.stringify({layerIds: layerIds})) : '') + - (pageId != null? '&pageId=' + pageId : '') + '&xml=' + encodeURIComponent(curViewer.xml)); - - req.send(function(req) - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - doSaveImage(req.getStatus() >= 200 && req.getStatus() <= 299? req.getText() : null); - } - }, - function() - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - doSaveImage(null); - } - }); - - }; - - function startSaving() - { - if (curViewer.editor.isExportToCanvas()) - { - curViewer.editor.exportToCanvas(function(canvas) - { - var data = canvas.toDataURL('image/png'); - doSaveImage(data.substring(data.lastIndexOf(',') + 1)); - } - , null, null, null, serverFallback); - } - else - { - serverFallback(); - } - }; - - if (theMacroData.service != null) - { - function doSave() - { - AC.saveDiagram(confPageId, theMacroData.diagramName, gSelFileContent, - startSaving, function(resp) - { - showError('Unexpected error. Cannot cannot save cached file'); - }, false, 'application/vnd.jgraph.mxfile.cached', 'Embedded draw.io diagram' + (gSelFileModifiedTS != null ? ' - ' + gSelFileModifiedTS : ''), false, draftPage); - }; - - if (editMode) - { - doSave() - } - else - { - //Confirm filename is unique for new files - AC.getPageAttachments(confPageId, function(attachments) - { - var fileExists = false; - var lc = theMacroData.diagramName.toLowerCase(); - - // Checks if any files will be overwritten - for (var i = 0; i < attachments.length && !fileExists; i++) - { - var an = attachments[i].title.toLowerCase(); - - if (an == lc) - { - fileExists = true; - } - } - - if (fileExists) - { - //Make filename unique - theMacroData.diagramName = Date.now() + '-' + theMacroData.diagramName; - } - - doSave(); - }, function(res) - { - showError('Unexpected error. Cannot cannot save cached file'); - }); - } - } - else - { - startSaving() - } - } - else - { - showError('Unexpected error. Cannot show diagram'); - } - } - else - { - showError('Please select a diagram to insert it.'); - } - }; - - function deselectDiagram() - { - selectedDiagramInfo = null; - - if (selectedElt != null) - { - selectedElt.style.backgroundColor = 'transparent'; - selectedElt.style.border = '1px solid #ddd'; - } - }; - - function fillDiagramsList(list, listDiv, top, emptyMsg) - { - listDiv.innerHTML = ''; - var div = document.createElement('div'); - div.style.border = '1px solid #d3d3d3'; - div.style.margin = '6px 0 0 -1px'; - div.style.padding = '6px'; - div.style.overflow = 'auto'; - div.style.position = 'absolute'; - div.style.bottom = '10px'; - div.style.right = '10px'; - div.style.left = '10px'; - div.style.top = top + 'px'; - - var w = 140; - var h = 140; - - function selectElement(elt, infoObj) - { - deselectDiagram(); - - selectedElt = elt; - selectedDiagramInfo = infoObj; - - selectedElt.style.backgroundColor = '#e6eff8'; - selectedElt.style.border = '2px solid #ccd9ea'; - }; - - function addButton(url, imgUrl, tooltip, infoObj) - { - var elt = document.createElement('div'); - elt.className = 'diagram'; - elt.style.height = w + 'px'; - elt.style.width = h + 'px'; - - elt.setAttribute('title', tooltip); - - elt.style.backgroundImage = 'url(' + imgUrl + ')'; - elt.style.backgroundSize = 'contain'; - elt.style.backgroundPosition = 'center center'; - elt.style.backgroundRepeat = 'no-repeat'; - - elt.addEventListener('click', function(evt) - { - selectElement(elt, infoObj); - }); - - elt.addEventListener('dblclick', function(evt) - { - selectedDiagramInfo = infoObj; - onSelect(); - }); - - div.appendChild(elt); - } - - for (var i = 0; i < list.length; i++) - { - addButton(list[i].url, list[i].imgUrl, list[i].title, list[i]); - } - - if (list.length == 0 && emptyMsg) - { - var msg = document.createElement('div'); - msg.style.width = '100%'; - msg.style.height = '100%'; - msg.style.textAlign = 'center'; - msg.innerHTML = AC.htmlEntities(emptyMsg); - - div.appendChild(msg); - } - - listDiv.appendChild(div); - return div; - } - - function activateTab() - { - deselectDiagram(); - showError('', true); - AP.dialog.getButton('selectBtn').show(); - AP.dialog.getButton('submit').hide(); - AP.dialog.getButton('submit').disable(); - - switch (activeTab) - { - case 'recent': - if (!recentLoaded) - { - recentLoaded = true; - AC.getRecentDiagrams(function(retList) - { - fillDiagramsList(retList, document.getElementById('recentList'), 50, 'No recent diagrams found!'); - }, function() - { - showError('Failed to fetch recent diagrams.', true); - }); - } - break; - case 'search': - if (!searchLoaded) - { - searchLoaded = true; - //fill the div with empty box - fillDiagramsList([], document.getElementById('searchList'), 80, 'Use the search box to find draw.io diagrams'); - } - break; - case 'gDrive': - if (gdEditor == null) - { - gdEditor = new GDriveEditor(function(selectedFile, width, height, autoSize, selFileContent) - { - gSelFileContent = selFileContent; - gSelFileModifiedTS = new Date(selectedFile.modifiedDate).getTime(); - gAttVer = null; - editMode = false; - //Upload is the same as embedding an existing draw.io macro but without content id - theMacroData = { - diagramName: selectedFile.title, - diagramDisplayName: selectedFile.title, - pageId: confPageId, - baseUrl: baseUrl, - service: 'GDrive', - sFileId: selectedFile.id, - aspect: selectedFile.aspect, - includedDiagram: 1 - }; - - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - }, null, 'GD', true, true); - } - else - { - gdEditor.spinner.stop(); - } - break; - case 'oneDrive': - if (odEditor == null) - { - odEditor = new OneDriveEditor(function(selectedFile, width, height, autoSize, selFileContent) - { - gSelFileContent = selFileContent; - gSelFileModifiedTS = new Date(selectedFile.lastModifiedDateTime).getTime(); - gAttVer = null; - editMode = false; - //Upload is the same as embedding an existing draw.io macro but without content id - theMacroData = { - diagramName: selectedFile.name, - diagramDisplayName: selectedFile.name, - pageId: confPageId, - baseUrl: baseUrl, - service: 'OneDrive', - sFileId: selectedFile.id, - odriveId: selectedFile.parentReference.driveId, - aspect: selectedFile.aspect, - includedDiagram: 1 - }; - - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - }, null, 'OD', true, true); - } - else - { - odEditor.spinner.stop(); - } - break; - case 'upload': - attEditor.spinner.stop(); - break; - case 'current': - AP.dialog.getButton('selectBtn').hide(); - AP.dialog.getButton('submit').show(); - - var div = document.getElementById('current'); - div.innerHTML = ''; - var container = document.createElement('div'); - // NOTE: Height must be specified with default value "auto" to force automatic fit in viewer - container.style.cssText = 'position:absolute;width:100%;height:auto;bottom:0px;top:45px;border:1px solid transparent;'; - div.appendChild(container); - spinner.spin(div); - - var pageId, layerIds; - - if (theMacroData.aspect != null) - { - var aspectArray = theMacroData.aspect.split(' '); - - if (aspectArray.length > 1) - { - pageId = aspectArray[0]; - layerIds = aspectArray.slice(1); - } - } - - function showFile(fileContent) - { - if (!async) - { - var doc = mxUtils.parseXml(fileContent); - - curViewer = new GraphViewer(container, doc.documentElement, - {highlight: '#3572b0', border: 8, 'auto-fit': true, - resize: false, nav: true, lightbox: false, title: (theMacroData.diagramDisplayName || theMacroData.diagramName), - 'toolbar-nohide': true, 'toolbar-position': 'top', toolbar: 'pages layers', - pageId: pageId, layerIds: layerIds - }); - - spinner.stop(); - AP.dialog.getButton('submit').enable(); - } - }; - - if (theMacroData.diagramUrl) - { - mxUtils.get(theMacroData.diagramUrl, function(req) - { - if (req.getStatus() >= 200 && req.getStatus() <= 299) - { - try - { - showFile(req.getText()); - } - catch(e) - { - showError('Unsupported file. Please check the specified URL', true); - spinner.stop(); - } - } - else - { - showError('Diagram not found or cannot be accessed. Please check the specified URL', true); - spinner.stop(); - } - }); - } - else if (theMacroData.service != null && gSelFileContent != null) - { - showFile(gSelFileContent); - } - else - { - //Get version - AC.getAttachmentInfo(theMacroData.pageId, theMacroData.diagramName, function(info) - { - gAttVer = info.version.number; - - AP.request({ - url: '/download/attachments/' + theMacroData.pageId + '/' + encodeURIComponent(theMacroData.diagramName), - success: showFile, - error : function() - { - showError('Cannot read the specified diagram. Please check you have read permission on that file.', true); - } - }); - }, function() - { - showError('Cannot fetch diagram info. Please check you have read permission on that file.', true); - }); - } - break; - } - } - - function openTab(evt) - { - var tabName = this.getAttribute('data-tabContetn'); - // Declare all variables - var i, tabcontent, tablinks; - - // Get all elements with class='tabcontent' and hide them - tabcontent = document.getElementsByClassName('tabcontent'); - for (i = 0; i < tabcontent.length; i++) { - tabcontent[i].style.display = 'none'; - } - - // Get all elements with class='tablinks' and remove the class 'active' - tablinks = document.getElementsByClassName('tablinks'); - for (i = 0; i < tablinks.length; i++) { - tablinks[i].className = tablinks[i].className.replace(' active', ''); - } - - // Show the current tab, and add an 'active' class to the button that opened the tab - document.getElementById(tabName).style.display = 'block'; - evt.currentTarget.className += ' active'; - - activeTab = tabName; - activateTab(); - } - - function doSearch() - { - var searchList = document.getElementById('searchList'); - var searchStr = document.getElementById('searchStr').value; - - if (searchStr != null && searchStr.length > 0) - { - spinner.spin(searchList); - - AC.searchDiagrams(searchStr, function(retList) - { - spinner.stop(); - fillDiagramsList(retList, searchList, 80, 'No diagrams found!'); - }, function() - { - showError('Searching failed. Please try again later.', true); - }); - } - else - { - showError('Please type a search string.'); - } - }; - - function showDiagFromUrl() - { - var diagramUrl = document.getElementById('diagramUrl'); - - if (!diagramUrl.value) - { - diagramUrl.style.border = '1px solid red'; - return; - } - - var extUrlDiagram = document.getElementById('extUrlDiagram'); - extUrlDiagram.innerHTML = ''; - var diagramFrame = document.createElement('iframe'); - diagramFrame.setAttribute('width', '100%'); - diagramFrame.setAttribute('height', '100%'); - diagramFrame.style.width = '100%'; - diagramFrame.style.height = '100%'; - diagramFrame.setAttribute('frameborder', '0'); - - diagramFrame.setAttribute('src', 'https://www.draw.io/?lightbox=1&toolbar-config=%7B"refreshBtn"%3Atrue%2C"fullscreenBtn"%3Atrue%2C"closeBtn"%3Atrue%7D&layers=1' + - '#U' + encodeURIComponent(diagramUrl.value)); - - extUrlDiagram.appendChild(diagramFrame); - }; - - //=======Upload========== - attEditor = new AttViewerEditor(function(selectedFile, selFileContent, editedFile, width, height, autoSize, isDrawio, aspect, onError) - { - //We only have add in Jira - if (selectedFile != null) - { - gSelFileContent = selFileContent; - gSelFileModifiedTS = null; - gAttVer = null; - editMode = false; - //Upload is the same as embedding an existing draw.io macro but without content id - theMacroData = { - diagramName: selectedFile.name, - diagramDisplayName: selectedFile.name, - pageId: confPageId, - baseUrl: baseUrl, - service: 'AttFile', - aspect: aspect, - includedDiagram: 1 - }; - - document.getElementById('currentTab').style.display = ''; - document.getElementById('currentTab').click(); - } - }, null, 'UD', true, true); - - //Staring the editor - //Setting events listeners - document.getElementById('searchBtn').addEventListener('click', doSearch); - document.getElementById('searchStr').addEventListener('keypress', function(e) - { - if (e.keyCode == 13) doSearch(); - }); - - document.getElementById('showDiagBtn').addEventListener('click', showDiagFromUrl); - - function resetBorder() - { - if (this.value) - this.style.border = ''; - }; - - var diagramUrl = document.getElementById('diagramUrl'); - var diagramName = document.getElementById('diagramName'); - - diagramUrl.addEventListener('keypress', resetBorder); - diagramName.addEventListener('keypress', resetBorder); - diagramUrl.addEventListener('change', resetBorder); - diagramName.addEventListener('change', resetBorder); - - var tabs = document.getElementsByClassName('tablinks'); - - for (var i = 0; i < tabs.length; i++) - { - tabs[i].addEventListener('click', openTab); - } - - AP.sizeToParent(true); - - AP.confluence.getMacroData(function (macroData) - { - if (macroData != null && macroData.includedDiagram != null) - { - theMacroData = macroData; - editMode = true; - - if (macroData.diagramUrl) - { - diagramUrl.value = macroData.diagramUrl; - diagramName.value = macroData.diagramName; - } - - function extractFileContents(resp, isPng) - { - if (isPng) - { - resp = 'data:image/png;base64,' + Editor.base64Encode (resp); - resp = AC.extractGraphModelFromPng(resp); - } - - gSelFileContent = resp; - async = false; - document.getElementById('currentTab').click(); - }; - - async = true; - gSelFileContent = ''; //To prevent fetching the cached file - - //Update file - if (macroData.service == 'GDrive') - { - GAC.getFileInfo(macroData.sFileId, function(fileInfo) - { - var isPng = fileInfo.mimeType == 'image/png'; - gSelFileModifiedTS = new Date(fileInfo.modifiedDate).getTime(); - - GAC.doAuthRequestPlain(fileInfo['downloadUrl'], 'GET', null, function(req) - { - extractFileContents(req.responseText, isPng); - }, function() - { - showError('Cannot read "' + fileInfo.title + '" file from Google Drive.', true); - }, null, isPng); - }, function() - { - showError('Fetching file info from Google Drive failed.', true); - }); - } - else if (macroData.service == 'OneDrive') - { - AC.getFileInfo(macroData.sFileId, macroData.odriveId, function(fileInfo) - { - var isPng = fileInfo.file.mimeType == 'image/png'; - gSelFileModifiedTS = new Date(fileInfo.lastModifiedDateTime).getTime(); - - var req = new XMLHttpRequest(); - req.open('GET', fileInfo['@microsoft.graph.downloadUrl']); - - req.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - extractFileContents(req.responseText, isPng); - } - else - { - showError('Cannot read "' + fileInfo.name + '" file from OneDrive.', true); - } - } - }; - - if (isPng && req.overrideMimeType) - { - req.overrideMimeType('text/plain; charset=x-user-defined'); - } - - req.send(); - }, function() - { - showError('Fetching file info from OneDrive failed.', true); - }); - } - else if (macroData.service == 'AttFile') - { - AP.request({ - url: '/download/attachments/' + theMacroData.pageId + '/' + encodeURIComponent(theMacroData.diagramName), - success: function(resp) - { - extractFileContents(resp); - }, - error : function() - { - showError('Cannot read the uploaded diagram.', true); - } - }); - } - else - { - async = false; - gSelFileContent = null; - } - - document.getElementById('currentTab').click(); - } - else - { - document.getElementById('currentTab').style.display = 'none'; - document.getElementById('recentTab').click(); - } - }); - - var selectBtn = AP.dialog.createButton({ - text: 'Select...', - identifier: 'selectBtn' - }); - selectBtn.bind(onSelect); - - AP.dialog.disableCloseOnSubmit(); - AP.events.on('dialog.submit', onSubmit); - AP.dialog.getButton('submit').hide(); - AP.dialog.getButton('submit').disable(); -}; \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/init-editor.js b/src/main/webapp/connect/confluence/init-editor.js deleted file mode 100644 index fe843317..00000000 --- a/src/main/webapp/connect/confluence/init-editor.js +++ /dev/null @@ -1,46 +0,0 @@ -var connectUrl = AC.getBaseUrl() + '/atlassian-connect'; -var head = document.getElementsByTagName('head')[0]; - -var script = document.createElement('script'); -script.setAttribute('data-options', 'resize:false;margin:false'); - -// Main -script.onload = function() -{ - // TODO: Try avoid this by using workaround in EditorUi.fileLoaded on line 2200 - //Firefox has a problem with focusing the can be fixed with a chrome dialog - if(navigator.userAgent.indexOf('Firefox/') >= 0) - { - AP.dialog.create( - { - key: 'splashEditor', - header: 'draw.io', - chrome: true, - width: "50%", - height: "50%", - }).on("close", function(flags) - { - AP.dialog.close(); - AP.confluence.closeMacroEditor(); - }); - AP.dialog.getButton('submit').hide(); - //Confluence refuse to hide cancel button!!! - AP.dialog.getButton('cancel').hide(); - } - else - { - AP.dialog.create( - { - key: 'macroEditor', - customData: {}, - chrome: false, - width: "100%", - height: "100%", - }).on("close", function(flags) - { - AP.confluence.closeMacroEditor(); - }); - } -}; -script.src = 'https://connect-cdn.atl-paas.net/all.js'; -head.appendChild(script); diff --git a/src/main/webapp/connect/confluence/initEditor.html b/src/main/webapp/connect/confluence/initEditor.html deleted file mode 100644 index f5b1b7ed..00000000 --- a/src/main/webapp/connect/confluence/initEditor.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - -draw.io Editor - - - - - - - diff --git a/src/main/webapp/connect/confluence/lucid-import.js b/src/main/webapp/connect/confluence/lucid-import.js deleted file mode 100644 index bdbad018..00000000 --- a/src/main/webapp/connect/confluence/lucid-import.js +++ /dev/null @@ -1,86 +0,0 @@ -//Logs uncaught errors -window.onerror = function(message, url, linenumber, colno, err) -{ - message = 'Confluence Cloud Lucid Mass Import: ' + ((message != null) ? message : ''); - - AC.logError(message, url, linenumber, colno, err); -}; - -var baseUrl = AC.getBaseUrl(); -var script = document.createElement('script'); - -script.onload = function() -{ - var importExtensionId = 'cnoplimhpndhhhnmoigbanpjeghjpohi'; - var extensionInstallUrl = 'https://chrome.google.com/webstore/detail/diagramsnet-and-drawio-im/cnoplimhpndhhhnmoigbanpjeghjpohi'; - var logDiv = $('#operationLog'); - - AP.sizeToParent(true); - - setTimeout(function() - { - AP.sizeToParent(true); - }, 5000); //Try resizing again after 5 sec since the first one fails sometimes - - function prepareImporter(response) - { - //JQuery is loaded in this page, so we can use it - var importBtn = $('#importBtn'); - - if (!response) //Extension is not installed - { - logDiv.html(mxResources.get('installFirst', ['' + mxResources.get('drawioChromeExt') + ''])); - } - else if (response.error) - { - if (response.msg == 'LucidNotFound' || response.msg == 'LucidDisconnected') - { - setTimeout(function() - { - chrome.runtime.sendMessage(importExtensionId, {msg: 'filesTree', allAsMap: true}, prepareImporter); - }, 1000); - } - else if (response.msg == 'AuthError') - { - logDiv.html(mxResources.get('loginFirstThen', ['Lucidchart', '' + mxResources.get('tryAgain') + ''])); - } - else - { - logDiv.html('' + mxResources.get('errFetchDocList') + ''); - } - } - else - { - importBtn.attr("disabled", null); - $('#loadingImg').hide(); - - importBtn.click(function() - { - $('#loadingImg').show(); - importBtn.prop('disabled', true); //Disable button to prevent concurrent execution - - LucidConnMassImporter(response.filesMap, importExtensionId, logDiv, function() - { - $('#loadingImg').hide(); - importBtn.prop('disabled', false); - }) - }); - } - }; - - getAndApplyTranslation(function() - { - if (typeof chrome === 'undefined') - { - logDiv.html('' + mxResources.get('chromeOnly') + ''); - } - else - { - chrome.runtime.sendMessage(importExtensionId, {msg: 'filesTree', allAsMap: true}, prepareImporter); - } - }); -}; - -script.src = 'https://connect-cdn.atl-paas.net/all.js'; -script.setAttribute('data-options', 'resize:false;margin:false'); -document.getElementsByTagName('head')[0].appendChild(script); diff --git a/src/main/webapp/connect/confluence/lucidMassImport.html b/src/main/webapp/connect/confluence/lucidMassImport.html deleted file mode 100644 index 13f013ba..00000000 --- a/src/main/webapp/connect/confluence/lucidMassImport.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - -
-

Lucidchart Import

-

Click the "Start Import" button to import all Lucidchart diagrams to draw.io.
- Please note that the import procedure will take some time and the browser window must remain open until the import is completed.
-

-

-
- - - diff --git a/src/main/webapp/connect/confluence/macro-editor.js b/src/main/webapp/connect/confluence/macro-editor.js deleted file mode 100644 index 7bdf5e64..00000000 --- a/src/main/webapp/connect/confluence/macro-editor.js +++ /dev/null @@ -1,181 +0,0 @@ -//Logs uncaught errors -window.onerror = function(message, url, linenumber, colno, err) -{ - message = 'Confluence Cloud Editor: ' + ((message != null) ? message : ''); - - AC.logError(message, url, linenumber, colno, err); -}; - -var xdm_e = AC.getSiteUrl(); -var baseUrl = AC.getBaseUrl(); -var license = AC.getUrlParam('lic', false); -var connectUrl = baseUrl + '/atlassian-connect'; -var head = document.getElementsByTagName('head')[0]; -var licenseValid = true; - -var script = document.createElement('script'); -script.setAttribute('data-options', 'resize:false;margin:false'); - -if (license != null && xdm_e != null) -{ - if (license == 'none') - { - licenseValid = false; - } - - var hostParse = document.createElement('a'); - hostParse.href = xdm_e; - var hostname = hostParse.hostname; - - if (hostname != null) - { - var xhr = new XMLHttpRequest(); - - xhr.onreadystatechange = function() - { - if (xhr.readyState == XMLHttpRequest.DONE && xhr.status >= 200 && xhr.status <= 299) - { - var resp = xhr.responseText; - - if (resp != null && resp.length > 0) - { - var lic = JSON.parse(resp); - - if (lic != null && lic.atlasCloudLic != null) - { - if (lic.atlasCloudLic != 'blocked') - { - licenseValid = true; - } - else - { - licenseValid = false; - } - } - } - } - }; - - xhr.open('POST', '/license?domain=' + hostname + '&confLicense=' + license, true); - xhr.send(null); - } -} - -// Main -script.onload = function() -{ - if (!licenseValid) - { - setTimeout(function() // XHR call doesn't work inside AP.Request - { - if (!licenseValid) - { - alert("Please install a license for the draw.io app"); - AP.dialog.close(); - } - }, 8000); - } - - AP.resize('100%', '100%'); - - var config = null; - var lang = null; - var SEN = null; - var installedDate = null; - var lastUpdated = null; - var allDone = 0; - - var startEditor = function () - { - allDone++; - - if (allDone == 2) - { - var isCustom = AC.getUrlParam('custom'); - - if (isCustom == "1") - { - var contentId = AC.getUrlParam('contentId') || AC.getUrlParam('custContentId'); - AP.dialog.getCustomData(function (customData) - { - AC.initAsync(baseUrl, customData.contentId || customData.custContentId || contentId, customData.macroData, config, lang); - }); - } - else - { - AC.initAsync(baseUrl, null, null, config, lang); - } - } - } - - AP.user.getLocale(function(locale) - { - lang = locale; - startEditor(); - }); - - AP.request({ - type: 'GET', - url: '/rest/api/content/search?cql=type%3Dpage%20and%20space%3DDRAWIOCONFIG%20and%20title%3DConfiguration', //type=page and space=DRAWIOCONFIG and title=Configuration. Search doesn't return 404 if not found - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - if (resp != null && resp.size == 1) - { - var configPageId = resp.results[0].id; - //load the configuration file - AP.request({ - type: 'GET', - url: '/download/attachments/' + configPageId + '/configuration.json', - contentType: 'application/json;charset=UTF-8', - success: function (fileContent) - { - config = fileContent; - startEditor(); - }, - error: startEditor //if there is an error loading the configuration, just load the editor normally. E.g., 404 when the space doesn't exist - }); - - } - else - { - startEditor(); - } - }, - error: startEditor //if there is an error loading the configuration, just load the editor normally. E.g., 404 when the space doesn't exist - }); - - AP.request({ - type: 'GET', - url: '/rest/atlassian-connect/1/addons/com.mxgraph.confluence.plugins.diagramly', - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - try - { - resp = JSON.parse(resp); - - if (resp != null && resp.license != null) - { - var xhr = new XMLHttpRequest(); - xhr.open('POST', '/license?licenseDump=' + encodeURIComponent(JSON.stringify(resp)), true); - xhr.send(null); - } - } - catch (e) - { - // just throw away if it breaks, not important - } - } - }); -}; -script.src = 'https://connect-cdn.atl-paas.net/all.js'; -head.appendChild(script); - -var link = document.createElement('link'); -link.type = 'text/css'; -link.rel = 'stylesheet'; -link.href = connectUrl + '/all.css'; -head.appendChild(link); diff --git a/src/main/webapp/connect/confluence/macroEditor-1-4-8.html b/src/main/webapp/connect/confluence/macroEditor-1-4-8.html deleted file mode 100644 index d31b19b8..00000000 --- a/src/main/webapp/connect/confluence/macroEditor-1-4-8.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - -draw.io Editor - - - - - - - diff --git a/src/main/webapp/connect/confluence/macroEditor.html b/src/main/webapp/connect/confluence/macroEditor.html deleted file mode 100644 index b12b53ba..00000000 --- a/src/main/webapp/connect/confluence/macroEditor.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - -Draw.io Editor - - - - - diff --git a/src/main/webapp/connect/confluence/prism/bililiteRange.fancytext.js b/src/main/webapp/connect/confluence/prism/bililiteRange.fancytext.js deleted file mode 100644 index fd23b07c..00000000 --- a/src/main/webapp/connect/confluence/prism/bililiteRange.fancytext.js +++ /dev/null @@ -1,91 +0,0 @@ -// Turn a textarea element into a pre element that can use a highlighter -// Designed for use with Prism (prismjs.com) -// usage: editor = bililiteRange.fancytext(element, Prism.highlightElement, threshold); -// the element should have the appropriate class=language-* for Prism. -// Version: 1.0 -// Documentation: http://bililite.com/blog/2013/12/16/simple-syntax-highlighting-editor-with-prism/ -// Copyright (c) 2013 Daniel Wachsstock -// depends: bililiteRange.js, bililiteRange.utils.js (the latter is only for autoindenting; if that's not used it is not necessary) - -// MIT license: -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: - -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -bililiteRange.fancyText = function(editor, highlighter, threshold){ - if (editor.tagName.toLowerCase() == 'textarea'){ - // turn the editor into an editable
, since that is what Prism works on
-		var replacement = document.createElement('pre');
-		replacement.setAttribute ('contenteditable', true);
-		[].forEach.call(editor.attributes, function(attr){
-			replacement.setAttribute(attr.name, attr.value);
-		});
-		replacement.textContent = editor.value;
-		editor.parentNode.replaceChild(replacement, editor);
-		editor = replacement;
-	}
-	// for large texts, it can be too slow to run the highlighter on every input event.
-	// use the code from http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
-	// to limit it to once every threshold milliseconds
-	function debounce (func, threshold){
-		if (!threshold) return func; // no debouncing
-		var timeout;
-		return function(){
-			var self = this, args = arguments;
-			clearTimeout(timeout);
-			timeout = setTimeout(function(){
-				func.apply(self, args);
-			}, threshold);
-		};
-	}
-
-	var rng = bililiteRange(editor);
-	function highlight(){
-		rng.bounds('selection');
-		// handle what Lea Verou calls "Dirty fix to #2"--seems to be Chrome issue with missing newlines
-		// from https://github.com/LeaVerou/dabblet/issues/2
-		if (!/\n$/.test(editor.textContent)) editor.textContent += '\n';
-		highlighter(editor);
-		rng.select();
-	}
-	if (highlighter){
-		highlight();
-		rng.listen('input', debounce(highlight, threshold));
-	}
-	rng.listen('paste', function(evt){
-    if (!evt.defaultPrevented) {
-			// Firefox changes newlines to br's on paste!
-			// Chrome pastes cr's! Nothing is easy.
-			rng.bounds('selection').
-				text(evt.clipboardData.getData("text/plain").replace(/\r/g,''), 'end').
-				select();
-			evt.preventDefault();
-		}
-	});
-	rng.listen('keydown', function(evt){
-		// avoid the fancy element-creation with newlines
-		if (evt.keyCode == 13 && !evt.defaultPrevented){
-			rng.bounds('selection').text('\n','end', rng.data().autoindent).select();
-			evt.preventDefault();
-		}
-	});
-
-	return editor;
-};
diff --git a/src/main/webapp/connect/confluence/prism/bililiteRange.js b/src/main/webapp/connect/confluence/prism/bililiteRange.js
deleted file mode 100644
index ebdeb697..00000000
--- a/src/main/webapp/connect/confluence/prism/bililiteRange.js
+++ /dev/null
@@ -1,763 +0,0 @@
-// Cross-broswer implementation of text ranges and selections
-// documentation: http://bililite.com/blog/2011/01/17/cross-browser-text-ranges-and-selections/
-// Version: 2.6
-// Copyright (c) 2013 Daniel Wachsstock
-// MIT license:
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-
-(function(){
-
-// a bit of weirdness with IE11: using 'focus' is flaky, even if I'm not bubbling, as far as I can tell.
-var focusEvent = 'onfocusin' in document.createElement('input') ? 'focusin' : 'focus';
-
-// IE11 normalize is buggy (http://connect.microsoft.com/IE/feedback/details/809424/node-normalize-removes-text-if-dashes-are-present)
-var n = document.createElement('div');
-n.appendChild(document.createTextNode('x-'));
-n.appendChild(document.createTextNode('x'));
-n.normalize();
-var canNormalize = n.firstChild.length == 3;
-
-
-bililiteRange = function(el, debug){
-	var ret;
-	if (debug){
-		ret = new NothingRange(); // Easier to force it to use the no-selection type than to try to find an old browser
-	}else if (window.getSelection && el.setSelectionRange){
-		// Standards. Element is an input or textarea 
-		// note that some input elements do not allow selections
-		try{
-			el.selectionStart; // even getting the selection in such an element will throw
-			ret = new InputRange();
-		}catch(e){
-			ret = new NothingRange();
-		}
-	}else if (window.getSelection){
-		// Standards, with any other kind of element
-		ret = new W3CRange();
-	}else if (document.selection){
-		// Internet Explorer
-		ret = new IERange();
-	}else{
-		// doesn't support selection
-		ret = new NothingRange();
-	}
-	ret._el = el;
-	// determine parent document, as implemented by John McLear 
-	ret._doc = el.ownerDocument;
-	ret._win = 'defaultView' in ret._doc ? ret._doc.defaultView : ret._doc.parentWindow;
-	ret._textProp = textProp(el);
-	ret._bounds = [0, ret.length()];
-	//  There's no way to detect whether a focus event happened as a result of a click (which should change the selection)
-	// or as a result of a keyboard event (a tab in) or a script  action (el.focus()). So we track it globally, which is a hack, and is likely to fail
-	// in edge cases (right-clicks, drag-n-drop), and is vulnerable to a lower-down handler preventing bubbling.
-	// I just don't know a better way.
-	// I'll hack my event-listening code below, rather than create an entire new bilililiteRange, potentially before the DOM has loaded
-	if (!('bililiteRangeMouseDown' in ret._doc)){
-		var _doc = {_el: ret._doc};
-		ret._doc.bililiteRangeMouseDown = false;
-		bililiteRange.fn.listen.call(_doc, 'mousedown', function() {
-			ret._doc.bililiteRangeMouseDown = true;
-		});
-		bililiteRange.fn.listen.call(_doc, 'mouseup', function() {
-			ret._doc.bililiteRangeMouseDown = false;
-		});
-	}
-	// note that bililiteRangeSelection is an array, which means that copying it only copies the address, which points to the original.
-	// make sure that we never let it (always do return [bililiteRangeSelection[0], bililiteRangeSelection[1]]), which means never returning
-	// this._bounds directly
-	if (!('bililiteRangeSelection' in el)){
-		// start tracking the selection
-		function trackSelection(evt){
-			if (evt && evt.which == 9){
-				// do tabs my way, by restoring the selection
-				// there's a flash of the browser's selection, but I don't see a way of avoiding that
-				//The following line is commented out in order for supporting inserting tabs in the editor
-				//ret._nativeSelect(ret._nativeRange(el.bililiteRangeSelection));
-			}else{
-				el.bililiteRangeSelection = ret._nativeSelection();
-			}
-		}
-		trackSelection();
-		// only IE does this right and allows us to grab the selection before blurring
-		if ('onbeforedeactivate' in el){
-			ret.listen('beforedeactivate', trackSelection);
-		}else{
-			// with standards-based browsers, have to listen for every user interaction
-			ret.listen('mouseup', trackSelection).listen('keyup', trackSelection);
-		}
-		ret.listen(focusEvent, function(){
-			// restore the correct selection when the element comes into focus (mouse clicks change the position of the selection)
-			// Note that Firefox will not fire the focus event until the window/tab is active even if el.focus() is called
-			// https://bugzilla.mozilla.org/show_bug.cgi?id=566671
-			if (!ret._doc.bililiteRangeMouseDown){
-				ret._nativeSelect(ret._nativeRange(el.bililiteRangeSelection));
-			}
-		});
-	}
-	if (!('oninput' in el)){
-		// give IE8 a chance. Note that this still fails in IE11, which has has oninput on contenteditable elements but does not 
-		// dispatch input events. See http://connect.microsoft.com/IE/feedback/details/794285/ie10-11-input-event-does-not-fire-on-div-with-contenteditable-set
-		// TODO: revisit this when I have IE11 running on my development machine
-		var inputhack = function() {ret.dispatch({type: 'input', bubbles: true}) };
-		ret.listen('keyup', inputhack);
-		ret.listen('cut', inputhack);
-		ret.listen('paste', inputhack);
-		ret.listen('drop', inputhack);
-		el.oninput = 'patched';
-	}
-	return ret;
-}
-
-function textProp(el){
-	// returns the property that contains the text of the element
-	// note that for  elements the text attribute represents the obsolete text color, not the textContent.
-	// we document that these routines do not work for  elements so that should not be relevant
-	if (typeof el.value != 'undefined') return 'value';
-	if (typeof el.text != 'undefined') return 'text';
-	if (typeof el.textContent != 'undefined') return 'textContent';
-	return 'innerText';
-}
-
-// base class
-function Range(){}
-Range.prototype = {
-	length: function() {
-		return this._el[this._textProp].replace(/\r/g, '').length; // need to correct for IE's CrLf weirdness
-	},
-	bounds: function(s){
-		if (bililiteRange.bounds[s]){
-			this._bounds = bililiteRange.bounds[s].apply(this);
-		}else if (s){
-			this._bounds = s; // don't do error checking now; things may change at a moment's notice
-		}else{
-			var b = [
-				Math.max(0, Math.min (this.length(), this._bounds[0])),
-				Math.max(0, Math.min (this.length(), this._bounds[1]))
-			];
-			b[1] = Math.max(b[0], b[1]);
-			return b; // need to constrain it to fit
-		}
-		return this; // allow for chaining
-	},
-	select: function(){
-		var b = this._el.bililiteRangeSelection = this.bounds();
-		if (this._el === this._doc.activeElement){
-			// only actually select if this element is active!
-			this._nativeSelect(this._nativeRange(b));
-		}
-		this.dispatch({type: 'select', bubbles: true});
-		return this; // allow for chaining
-	},
-	text: function(text, select){
-		if (arguments.length){
-			var bounds = this.bounds(), el = this._el;
-			// signal the input per DOM 3 input events, http://www.w3.org/TR/DOM-Level-3-Events/#h4_events-inputevents
-			// we add another field, bounds, which are the bounds of the original text before being changed.
-			this.dispatch({type: 'beforeinput', bubbles: true,
-			               data: text, bounds: bounds});
-			this._nativeSetText(text, this._nativeRange(bounds));
-			if (select == 'start'){
-				this.bounds ([bounds[0], bounds[0]]);
-			}else if (select == 'end'){
-				this.bounds ([bounds[0]+text.length, bounds[0]+text.length]);
-			}else if (select == 'all'){
-				this.bounds ([bounds[0], bounds[0]+text.length]);
-			}
-			this.dispatch({type: 'input', bubbles: true,
-			               data: text, bounds: bounds});
-			return this; // allow for chaining
-		}else{
-			return this._nativeGetText(this._nativeRange(this.bounds())).replace(/\r/g, ''); // need to correct for IE's CrLf weirdness
-		}
-	},
-	insertEOL: function (){
-		this._nativeEOL();
-		this._bounds = [this._bounds[0]+1, this._bounds[0]+1]; // move past the EOL marker
-		return this;
-	},
-	sendkeys: function (text){
-		var self = this;
-		this.data().sendkeysOriginalText = this.text();
-		this.data().sendkeysBounds = undefined;
-		function simplechar (rng, c){
-			if (/^{[^}]*}$/.test(c)) c = c.slice(1,-1);	// deal with unknown {key}s
-			for (var i =0; i < c.length; ++i){
-				var x = c.charCodeAt(i);
-				rng.dispatch({type: 'keypress', bubbles: true, keyCode: x, which: x, charCode: x});
-			}
-			rng.text(c, 'end');
-		}
-		text.replace(/{[^}]*}|[^{]+|{/g, function(part){
-			(bililiteRange.sendkeys[part] || simplechar)(self, part, simplechar);
-		});
-		this.bounds(this.data().sendkeysBounds);
-		this.dispatch({type: 'sendkeys', which: text});
-		return this;
-	},
-	top: function(){
-		return this._nativeTop(this._nativeRange(this.bounds()));
-	},
-	scrollIntoView: function(scroller){
-		var top = this.top();
-		// scroll into position if necessary
-		if (this._el.scrollTop > top || this._el.scrollTop+this._el.clientHeight < top){
-			if (scroller){
-				scroller.call(this._el, top);
-			}else{
-				this._el.scrollTop = top;
-			}
-		}
-		return this;
-	},
-	wrap: function (n){
-		this._nativeWrap(n, this._nativeRange(this.bounds()));
-		return this;
-	},
-	selection: function(text){
-		if (arguments.length){
-			return this.bounds('selection').text(text, 'end').select();
-		}else{
-			return this.bounds('selection').text();
-		}
-	},
-	clone: function(){
-		return bililiteRange(this._el).bounds(this.bounds());
-	},
-	all: function(text){
-		if (arguments.length){
-			this.dispatch ({type: 'beforeinput', bubbles: true, data: text});
-			this._el[this._textProp] = text;
-			this.dispatch ({type: 'input', bubbles: true, data: text});
-			return this;
-		}else{
-			return this._el[this._textProp].replace(/\r/g, ''); // need to correct for IE's CrLf weirdness
-		}
-	},
-	element: function() { return this._el },
-	// includes a quickie polyfill for CustomEvent for IE that isn't perfect but works for me
-	// IE10 allows custom events but not "new CustomEvent"; have to do it the old-fashioned way
-	dispatch: function(opts){
-		opts = opts || {};
-		var event = document.createEvent ? document.createEvent('CustomEvent') : this._doc.createEventObject();
-		event.initCustomEvent && event.initCustomEvent(opts.type, !!opts.bubbles, !!opts.cancelable, opts.detail);
-		for (var key in opts) event[key] = opts[key];
-		// dispatch event asynchronously (in the sense of on the next turn of the event loop; still should be fired in order of dispatch
-		var el = this._el;
-		setTimeout(function(){
-			try {
-				el.dispatchEvent ? el.dispatchEvent(event) : el.fireEvent("on" + opts.type, document.createEventObject());
-				}catch(e){
-				// IE8 will not let me fire custom events at all. Call them directly
-					var listeners = el['listen'+opts.type];
-					if (listeners) for (var i = 0; i < listeners.length; ++i){
-						listeners[i].call(el, event);
-					}
-				}
-		}, 0);
-		return this;
-	},
-	listen: function (type, func){
-		var el = this._el;
-		if (el.addEventListener){
-			el.addEventListener(type, func);
-		}else{
-			el.attachEvent("on" + type, func);
-			// IE8 can't even handle custom events created with createEventObject  (though it permits attachEvent), so we have to make our own
-			var listeners = el['listen'+type] = el['listen'+type] || [];
-			listeners.push(func);
-		}
-		return this;
-	},
-	dontlisten: function (type, func){
-		var el = this._el;
-		if (el.removeEventListener){
-			el.removeEventListener(type, func);
-		}else try{
-			el.detachEvent("on" + type, func);
-		}catch(e){
-			var listeners = el['listen'+type];
-			if (listeners) for (var i = 0; i < listeners.length; ++i){
-				if (listeners[i] === func) listeners[i] = function(){}; // replace with a noop
-			}
-		}
-		return this;
-	}
-};
-
-// allow extensions ala jQuery
-bililiteRange.fn = Range.prototype; // to allow monkey patching
-bililiteRange.extend = function(fns){
-	for (fn in fns) Range.prototype[fn] = fns[fn];
-};
-
-//bounds functions
-bililiteRange.bounds = {
-	all: function() { return [0, this.length()] },
-	start: function () { return [0,0] },
-	end: function () { return [this.length(), this.length()] },
-	selection: function(){
-		if (this._el === this._doc.activeElement){
-			this.bounds ('all'); // first select the whole thing for constraining
-			return this._nativeSelection();
-		}else{
-			return this._el.bililiteRangeSelection;
-		}
-	}
-};
-
-// sendkeys functions
-bililiteRange.sendkeys = {
-	'{enter}': function (rng){
-		rng.dispatch({type: 'keypress', bubbles: true, keyCode: '\n', which: '\n', charCode: '\n'});
-		rng.insertEOL();
-	},
-	'{tab}': function (rng, c, simplechar){
-		simplechar(rng, '\t'); // useful for inserting what would be whitespace
-	},
-	'{newline}': function (rng, c, simplechar){
-		simplechar(rng, '\n'); // useful for inserting what would be whitespace (and if I don't want to use insertEOL, which does some fancy things)
-	},
-	'{backspace}': function (rng){
-		var b = rng.bounds();
-		if (b[0] == b[1]) rng.bounds([b[0]-1, b[0]]); // no characters selected; it's just an insertion point. Remove the previous character
-		rng.text('', 'end'); // delete the characters and update the selection
-	},
-	'{del}': function (rng){
-		var b = rng.bounds();
-		if (b[0] == b[1]) rng.bounds([b[0], b[0]+1]); // no characters selected; it's just an insertion point. Remove the next character
-		rng.text('', 'end'); // delete the characters and update the selection
-	},
-	'{rightarrow}':  function (rng){
-		var b = rng.bounds();
-		if (b[0] == b[1]) ++b[1]; // no characters selected; it's just an insertion point. Move to the right
-		rng.bounds([b[1], b[1]]);
-	},
-	'{leftarrow}': function (rng){
-		var b = rng.bounds();
-		if (b[0] == b[1]) --b[0]; // no characters selected; it's just an insertion point. Move to the left
-		rng.bounds([b[0], b[0]]);
-	},
-	'{selectall}' : function (rng){
-		rng.bounds('all');
-	},
-	'{selection}': function (rng){
-		// insert the characters without the sendkeys processing
-		var s = rng.data().sendkeysOriginalText;
-		for (var i =0; i < s.length; ++i){
-			var x = s.charCodeAt(i);
-			rng.dispatch({type: 'keypress', bubbles: true, keyCode: x, which: x, charCode: x});
-		}
-		rng.text(s, 'end');
-	},
-	'{mark}' : function (rng){
-		rng.data().sendkeysBounds = rng.bounds();
-	}
-};
-// Synonyms from the proposed DOM standard (http://www.w3.org/TR/DOM-Level-3-Events-key/)
-bililiteRange.sendkeys['{Enter}'] = bililiteRange.sendkeys['{enter}'];
-bililiteRange.sendkeys['{Backspace}'] = bililiteRange.sendkeys['{backspace}'];
-bililiteRange.sendkeys['{Delete}'] = bililiteRange.sendkeys['{del}'];
-bililiteRange.sendkeys['{ArrowRight}'] = bililiteRange.sendkeys['{rightarrow}'];
-bililiteRange.sendkeys['{ArrowLeft}'] = bililiteRange.sendkeys['{leftarrow}'];
-
-function IERange(){}
-IERange.prototype = new Range();
-IERange.prototype._nativeRange = function (bounds){
-	var rng;
-	if (this._el.tagName == 'INPUT'){
-		// IE 8 is very inconsistent; textareas have createTextRange but it doesn't work
-		rng = this._el.createTextRange();
-	}else{
-		rng = this._doc.body.createTextRange ();
-		rng.moveToElementText(this._el);
-	}
-	if (bounds){
-		if (bounds[1] < 0) bounds[1] = 0; // IE tends to run elements out of bounds
-		if (bounds[0] > this.length()) bounds[0] = this.length();
-		if (bounds[1] < rng.text.replace(/\r/g, '').length){ // correct for IE's CrLf weirdness
-			// block-display elements have an invisible, uncounted end of element marker, so we move an extra one and use the current length of the range
-			rng.moveEnd ('character', -1);
-			rng.moveEnd ('character', bounds[1]-rng.text.replace(/\r/g, '').length);
-		}
-		if (bounds[0] > 0) rng.moveStart('character', bounds[0]);
-	}
-	return rng;					
-};
-IERange.prototype._nativeSelect = function (rng){
-	rng.select();
-};
-IERange.prototype._nativeSelection = function (){
-	// returns [start, end] for the selection constrained to be in element
-	var rng = this._nativeRange(); // range of the element to constrain to
-	var len = this.length();
-	var sel = this._doc.selection.createRange();
-	try{
-		return [
-			iestart(sel, rng),
-			ieend (sel, rng)
-		];
-	}catch (e){
-		// TODO: determine if this is still necessary, since we only call _nativeSelection if _el is active
-		// IE gets upset sometimes about comparing text to input elements, but the selections cannot overlap, so make a best guess
-		return (sel.parentElement().sourceIndex < this._el.sourceIndex) ? [0,0] : [len, len];
-	}
-};
-IERange.prototype._nativeGetText = function (rng){
-	return rng.text;
-};
-IERange.prototype._nativeSetText = function (text, rng){
-	rng.text = text;
-};
-IERange.prototype._nativeEOL = function(){
-	if ('value' in this._el){
-		this.text('\n'); // for input and textarea, insert it straight
-	}else{
-		this._nativeRange(this.bounds()).pasteHTML('\n
'); - } -}; -IERange.prototype._nativeTop = function(rng){ - var startrng = this._nativeRange([0,0]); - return rng.boundingTop - startrng.boundingTop; -} -IERange.prototype._nativeWrap = function(n, rng) { - // hacky to use string manipulation but I don't see another way to do it. - var div = document.createElement('div'); - div.appendChild(n); - // insert the existing range HTML after the first tag - var html = div.innerHTML.replace('><', '>'+rng.htmlText+'<'); - rng.pasteHTML(html); -}; - -// IE internals -function iestart(rng, constraint){ - // returns the position (in character) of the start of rng within constraint. If it's not in constraint, returns 0 if it's before, length if it's after - var len = constraint.text.replace(/\r/g, '').length; // correct for IE's CrLf weirdness - if (rng.compareEndPoints ('StartToStart', constraint) <= 0) return 0; // at or before the beginning - if (rng.compareEndPoints ('StartToEnd', constraint) >= 0) return len; - for (var i = 0; rng.compareEndPoints ('StartToStart', constraint) > 0; ++i, rng.moveStart('character', -1)); - return i; -} -function ieend (rng, constraint){ - // returns the position (in character) of the end of rng within constraint. If it's not in constraint, returns 0 if it's before, length if it's after - var len = constraint.text.replace(/\r/g, '').length; // correct for IE's CrLf weirdness - if (rng.compareEndPoints ('EndToEnd', constraint) >= 0) return len; // at or after the end - if (rng.compareEndPoints ('EndToStart', constraint) <= 0) return 0; - for (var i = 0; rng.compareEndPoints ('EndToStart', constraint) > 0; ++i, rng.moveEnd('character', -1)); - return i; -} - -// an input element in a standards document. "Native Range" is just the bounds array -function InputRange(){} -InputRange.prototype = new Range(); -InputRange.prototype._nativeRange = function(bounds) { - return bounds || [0, this.length()]; -}; -InputRange.prototype._nativeSelect = function (rng){ - this._el.setSelectionRange(rng[0], rng[1]); -}; -InputRange.prototype._nativeSelection = function(){ - return [this._el.selectionStart, this._el.selectionEnd]; -}; -InputRange.prototype._nativeGetText = function(rng){ - return this._el.value.substring(rng[0], rng[1]); -}; -InputRange.prototype._nativeSetText = function(text, rng){ - var val = this._el.value; - this._el.value = val.substring(0, rng[0]) + text + val.substring(rng[1]); -}; -InputRange.prototype._nativeEOL = function(){ - this.text('\n'); -}; -InputRange.prototype._nativeTop = function(rng){ - // I can't remember where I found this clever hack to find the location of text in a text area - var clone = this._el.cloneNode(true); - clone.style.visibility = 'hidden'; - clone.style.position = 'absolute'; - this._el.parentNode.insertBefore(clone, this._el); - clone.style.height = '1px'; - clone.value = this._el.value.slice(0, rng[0]); - var top = clone.scrollHeight; - // this gives the bottom of the text, so we have to subtract the height of a single line - clone.value = 'X'; - top -= clone.scrollHeight; - clone.parentNode.removeChild(clone); - return top; -} -InputRange.prototype._nativeWrap = function() {throw new Error("Cannot wrap in a text element")}; - -function W3CRange(){} -W3CRange.prototype = new Range(); -W3CRange.prototype._nativeRange = function (bounds){ - var rng = this._doc.createRange(); - rng.selectNodeContents(this._el); - if (bounds){ - w3cmoveBoundary (rng, bounds[0], true, this._el); - rng.collapse (true); - w3cmoveBoundary (rng, bounds[1]-bounds[0], false, this._el); - } - return rng; -}; -W3CRange.prototype._nativeSelect = function (rng){ - this._win.getSelection().removeAllRanges(); - this._win.getSelection().addRange (rng); -}; -W3CRange.prototype._nativeSelection = function (){ - // returns [start, end] for the selection constrained to be in element - var rng = this._nativeRange(); // range of the element to constrain to - if (this._win.getSelection().rangeCount == 0) return [this.length(), this.length()]; // append to the end - var sel = this._win.getSelection().getRangeAt(0); - return [ - w3cstart(sel, rng), - w3cend (sel, rng) - ]; - } -W3CRange.prototype._nativeGetText = function (rng){ - return String.prototype.slice.apply(this._el.textContent, this.bounds()); - // return rng.toString(); // this fails in IE11 since it insists on inserting \r's before \n's in Ranges. node.textContent works as expected -}; -W3CRange.prototype._nativeSetText = function (text, rng){ - rng.deleteContents(); - rng.insertNode (this._doc.createTextNode(text)); - if (canNormalize) this._el.normalize(); // merge the text with the surrounding text -}; -W3CRange.prototype._nativeEOL = function(){ - var rng = this._nativeRange(this.bounds()); - rng.deleteContents(); - var br = this._doc.createElement('br'); - br.setAttribute ('_moz_dirty', ''); // for Firefox - rng.insertNode (br); - rng.insertNode (this._doc.createTextNode('\n')); - rng.collapse (false); -}; -W3CRange.prototype._nativeTop = function(rng){ - if (this.length == 0) return 0; // no text, no scrolling - if (rng.toString() == ''){ - var textnode = this._doc.createTextNode('X'); - rng.insertNode (textnode); - } - var startrng = this._nativeRange([0,1]); - var top = rng.getBoundingClientRect().top - startrng.getBoundingClientRect().top; - if (textnode) textnode.parentNode.removeChild(textnode); - return top; -} -W3CRange.prototype._nativeWrap = function(n, rng) { - rng.surroundContents(n); -}; - -// W3C internals -function nextnode (node, root){ - // in-order traversal - // we've already visited node, so get kids then siblings - if (node.firstChild) return node.firstChild; - if (node.nextSibling) return node.nextSibling; - if (node===root) return null; - while (node.parentNode){ - // get uncles - node = node.parentNode; - if (node == root) return null; - if (node.nextSibling) return node.nextSibling; - } - return null; -} -function w3cmoveBoundary (rng, n, bStart, el){ - // move the boundary (bStart == true ? start : end) n characters forward, up to the end of element el. Forward only! - // if the start is moved after the end, then an exception is raised - if (n <= 0) return; - var node = rng[bStart ? 'startContainer' : 'endContainer']; - if (node.nodeType == 3){ - // we may be starting somewhere into the text - n += rng[bStart ? 'startOffset' : 'endOffset']; - } - while (node){ - if (node.nodeType == 3){ - var length = node.nodeValue.length; - if (n <= length){ - rng[bStart ? 'setStart' : 'setEnd'](node, n); - // special case: if we end next to a
, include that node. - if (n == length){ - // skip past zero-length text nodes - for (var next = nextnode (node, el); next && next.nodeType==3 && next.nodeValue.length == 0; next = nextnode(next, el)){ - rng[bStart ? 'setStartAfter' : 'setEndAfter'](next); - } - if (next && next.nodeType == 1 && next.nodeName == "BR") rng[bStart ? 'setStartAfter' : 'setEndAfter'](next); - } - return; - }else{ - rng[bStart ? 'setStartAfter' : 'setEndAfter'](node); // skip past this one - n -= length; // and eat these characters - } - } - node = nextnode (node, el); - } -} -var START_TO_START = 0; // from the w3c definitions -var START_TO_END = 1; -var END_TO_END = 2; -var END_TO_START = 3; -// from the Mozilla documentation, for range.compareBoundaryPoints(how, sourceRange) -// -1, 0, or 1, indicating whether the corresponding boundary-point of range is respectively before, equal to, or after the corresponding boundary-point of sourceRange. - // * Range.END_TO_END compares the end boundary-point of sourceRange to the end boundary-point of range. - // * Range.END_TO_START compares the end boundary-point of sourceRange to the start boundary-point of range. - // * Range.START_TO_END compares the start boundary-point of sourceRange to the end boundary-point of range. - // * Range.START_TO_START compares the start boundary-point of sourceRange to the start boundary-point of range. -function w3cstart(rng, constraint){ - if (rng.compareBoundaryPoints (START_TO_START, constraint) <= 0) return 0; // at or before the beginning - if (rng.compareBoundaryPoints (END_TO_START, constraint) >= 0) return constraint.toString().length; - rng = rng.cloneRange(); // don't change the original - rng.setEnd (constraint.endContainer, constraint.endOffset); // they now end at the same place - return constraint.toString().replace(/\r/g, '').length - rng.toString().replace(/\r/g, '').length; -} -function w3cend (rng, constraint){ - if (rng.compareBoundaryPoints (END_TO_END, constraint) >= 0) return constraint.toString().length; // at or after the end - if (rng.compareBoundaryPoints (START_TO_END, constraint) <= 0) return 0; - rng = rng.cloneRange(); // don't change the original - rng.setStart (constraint.startContainer, constraint.startOffset); // they now start at the same place - return rng.toString().replace(/\r/g, '').length; -} - -function NothingRange(){} -NothingRange.prototype = new Range(); -NothingRange.prototype._nativeRange = function(bounds) { - return bounds || [0,this.length()]; -}; -NothingRange.prototype._nativeSelect = function (rng){ // do nothing -}; -NothingRange.prototype._nativeSelection = function(){ - return [0,0]; -}; -NothingRange.prototype._nativeGetText = function (rng){ - return this._el[this._textProp].substring(rng[0], rng[1]); -}; -NothingRange.prototype._nativeSetText = function (text, rng){ - var val = this._el[this._textProp]; - this._el[this._textProp] = val.substring(0, rng[0]) + text + val.substring(rng[1]); -}; -NothingRange.prototype._nativeEOL = function(){ - this.text('\n'); -}; -NothingRange.prototype._nativeTop = function(){ - return 0; -}; -NothingRange.prototype._nativeWrap = function() {throw new Error("Wrapping not implemented")}; - - -// data for elements, similar to jQuery data, but allows for monitoring with custom events -var data = []; // to avoid attaching javascript objects to DOM elements, to avoid memory leaks -bililiteRange.fn.data = function(){ - var index = this.element().bililiteRangeData; - if (index == undefined){ - index = this.element().bililiteRangeData = data.length; - data[index] = new Data(this); - } - return data[index]; -} -try { - Object.defineProperty({},'foo',{}); // IE8 will throw an error - var Data = function(rng) { - // we use JSON.stringify to display the data values. To make some of those non-enumerable, we have to use properties - Object.defineProperty(this, 'values', { - value: {} - }); - Object.defineProperty(this, 'sourceRange', { - value: rng - }); - Object.defineProperty(this, 'toJSON', { - value: function(){ - var ret = {}; - for (var i in Data.prototype) if (i in this.values) ret[i] = this.values[i]; - return ret; - } - }); - // to display all the properties (not just those changed), use JSON.stringify(state.all) - Object.defineProperty(this, 'all', { - get: function(){ - var ret = {}; - for (var i in Data.prototype) ret[i] = this[i]; - return ret; - } - }); - } - - Data.prototype = {}; - Object.defineProperty(Data.prototype, 'values', { - value: {} - }); - Object.defineProperty(Data.prototype, 'monitored', { - value: {} - }); - - bililiteRange.data = function (name, newdesc){ - newdesc = newdesc || {}; - var desc = Object.getOwnPropertyDescriptor(Data.prototype, name) || {}; - if ('enumerable' in newdesc) desc.enumerable = !!newdesc.enumerable; - if (!('enumerable' in desc)) desc.enumerable = true; // default - if ('value' in newdesc) Data.prototype.values[name] = newdesc.value; - if ('monitored' in newdesc) Data.prototype.monitored[name] = newdesc.monitored; - desc.configurable = true; - desc.get = function (){ - if (name in this.values) return this.values[name]; - return Data.prototype.values[name]; - }; - desc.set = function (value){ - this.values[name] = value; - if (Data.prototype.monitored[name]) this.sourceRange.dispatch({ - type: 'bililiteRangeData', - bubbles: true, - detail: {name: name, value: value} - }); - } - Object.defineProperty(Data.prototype, name, desc); - } -}catch(err){ - // if we can't set object property properties, just use old-fashioned properties - Data = function(rng){ this.sourceRange = rng }; - Data.prototype = {}; - bililiteRange.data = function(name, newdesc){ - if ('value' in newdesc) Data.prototype[name] = newdesc.value; - } -} - -})(); - -// Polyfill for forEach, per Mozilla documentation. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Polyfill -if (!Array.prototype.forEach) -{ - Array.prototype.forEach = function(fun /*, thisArg */) - { - "use strict"; - - if (this === void 0 || this === null) - throw new TypeError(); - - var t = Object(this); - var len = t.length >>> 0; - if (typeof fun !== "function") - throw new TypeError(); - - var thisArg = arguments.length >= 2 ? arguments[1] : void 0; - for (var i = 0; i < len; i++) - { - if (i in t) - fun.call(thisArg, t[i], i, t); - } - }; -} diff --git a/src/main/webapp/connect/confluence/prism/bililiteRange.undo.js b/src/main/webapp/connect/confluence/prism/bililiteRange.undo.js deleted file mode 100644 index 63387869..00000000 --- a/src/main/webapp/connect/confluence/prism/bililiteRange.undo.js +++ /dev/null @@ -1,122 +0,0 @@ -// implements a simple undo stack for bililiteRange - -// version 1.2 -// Documentation at http://bililite.com/blog/2013/12/25/bililiterange-undo/ - -// depends on bililiteRange.js - -// Copyright (c) 2013 Daniel Wachsstock -// MIT license: -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: - -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -if (bililiteRange) (function(){ - -bililiteRange.data ('undos', {enumerable: false}); - -bililiteRange.fn.undo = function(n){ - if (arguments.length == 0) n = 1; // default - var state = getundostate(this); - if (n > 0){ - for (var i = 0; i < n; ++i) restore (state, 'undo', this); - }else if (n < 0){ - for (i = 0; i > n; --i) restore (state, 'redo', this); - } - return this; -}; - -function getundostate(rng){ - var undos = rng.data().undos; - if (undos) return undos; - var state = new undostate (rng); - setuplisteners (rng); - return state; -} - -function undostate (rng){ - // inefficiently just stores the whole text rather than trying to figure out a diff - this.text = rng.all(); - var laststate = rng.data().undos; - if (laststate && this.text == laststate.text) return; // is this too inefficient, to compare each time? - this.bounds = rng.bounds('selection').bounds(); - this.undo = this; // set up a doubly linked list that never ends (so undo with only one element on the list does nothing) - this.redo = this; - if (laststate) { - this.undo = laststate; - laststate.redo = this; - } - rng.data().undos = this; -} - -function restore (state, dir, rng){ - // dir is 'undo' or 'redo'; - rng.dispatch({type: dir}); // signal it - state = state[dir]; - state.lastevent = dir; // mark the undo/redo so we don't add the change in text to the undo stack - rng.data().undos = state; - rng.all(state.text).bounds(state.bounds).select(); // restore the old state -} - -function setuplisteners (rng){ - rng.listen('input', function(){ - var state = getundostate(rng), el = rng.element(), lastevent = state.lastevent; - delete state.lastevent; - switch (lastevent){ - // catch input events that we should not save (resulting from undo, redo and keypress events that are contiguous) - case 'undo': case 'redo': - return; // don't record the current input - case 'keypress': - // if the last event was also a keypress, drop that one (so we would undo back to the beginning of the typing) - if (state.penultimateevent == 'keypress') rng.data().undos = state.undo; - } - (new undostate(rng)).penultimateevent = lastevent; // record so we can check for keypress sequences - }).listen('keypress', function(evt){ - // key presses replace each other, which means that undo will undo all of them, unless the previous event was not a keypress (meaning we are starting a - // new series of typing) or we type a carriage return, which starts a new series of typing, or the new keypress is in a different place than the old one - if (evt.which < 32) return; // nonprinting characters; Firefox tends to send them all. We want them all undone individually - if (evt.altKey || evt.altGraphKey || evt.ctrlKey || evt.metaKey) return; - var bounds = rng.bounds('selection').bounds(); - if (bounds[0] != bounds[1]) return; // about to erase a selection; start a new undo sequence - var state = getundostate(rng); - // only mark this if the previous event was in the same place - if (state.bounds[0] != bounds[0]) return; - state.lastevent = 'keypress'; - }); -} - -// for use as an event handler -bililiteRange.undo = function (event){ - bililiteRange(event.target).undo(); - event.preventDefault(); -} -bililiteRange.redo = function (event){ - bililiteRange(event.target).undo(-1); - event.preventDefault(); -} - -// for debugging -function getstack(state, dir){ - dir = dir || 'undo'; - for (var ret = []; ret.push(state), state[dir] != state; state = state[dir]); - return ret; -} - -})(); \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/prism/bililiteRange.util.js b/src/main/webapp/connect/confluence/prism/bililiteRange.util.js deleted file mode 100644 index 95510a61..00000000 --- a/src/main/webapp/connect/confluence/prism/bililiteRange.util.js +++ /dev/null @@ -1,272 +0,0 @@ -// Text range utilities -// documentation: http://bililite.com/blog/2013/02/08/bililiterange-plugins/ -// depends on bililiteRange.js (http://bililite.com/blog/2011/01/17/cross-browser-text-ranges-and-selections/) -// Version: 1.3 -// Copyright (c) 2013 Daniel Wachsstock -// MIT license: -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: - -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -if (bililiteRange) (function(){ - -bililiteRange.bounds.EOL = function(){ - // set the range to the end of this line - // if we start at the end of a line, find will go to the next line! Check for that case first - this.bounds('startbounds'); - if (this.findprimitive (/$/mg, this.bounds())) return this.bounds(); - return this.find(/$/m, true).bounds(); // don't wrap -}; -bililiteRange.bounds.BOL = function(){ - // set the range to the beginning of this line - // if we start at the beginning of a line, findBack will go to the previous line! Check for that case first - this.bounds('startbounds'); - if (this.findprimitive (/^/mg, this.bounds())) return this.bounds(); - return this.findBack(/^/m, true).bounds(); // don't wrap -}; -bililiteRange.bounds.line = function(){ - this.bounds('BOL'); - var start = this.bounds()[0]; - this.bounds('EOL'); - return [start, this.bounds()[1]]; -}; -bililiteRange.bounds.startbounds = function(){ - return [this.bounds()[0], this.bounds()[0]]; -}; -bililiteRange.bounds.endbounds = function(){ - return [this.bounds()[1], this.bounds()[1]]; -}; - -// add autoindent option -var oldtext = bililiteRange.fn.text; -bililiteRange.fn.text = function (text, select, autoindent){ - if (!arguments.length) return oldtext.call (this); - if (autoindent) text = indent(text, this.indentation()); - return oldtext.call (this, text, select); -} - -bililiteRange.extend({ - - find: function(re, nowrap, backwards){ - // little hack: can put the "nowrap" as a flag on the RegExp itself, analagous to ignoreCase and multiline; overrides the parameter - if (re.nowrap !== undefined) nowrap = re.nowrap; - re = globalize(re); - var bounds = this.bounds(); - if (!backwards){ - var findprimitive = 'findprimitive'; - var initialbounds = [bounds[0], Number.MAX_VALUE]; - var fallbackbounds = [bounds[0]+1, Number.MAX_VALUE]; - }else{ - findprimitive = 'findprimitiveback'; - initialbounds = [0, bounds[0]]; - fallbackbounds = [0, bounds[0]-1]; - } - var match = this[findprimitive](re, initialbounds); - if (matchIs(match, bounds)){ // if the match is exactly the current string, it doesn't count - match = this[findprimitive](re, fallbackbounds); - } - if (!match && !nowrap) match = this[findprimitive](re, [0, Number.MAX_VALUE]); - if (matchIs(match, bounds)) match = false; // again, even with wrapping, don't find the identical segment - this.match = match; // remember this for the caller - if (match) this.bounds([match.index, match.index+match[0].length]); // select the found string - return this; - }, - - findBack: function (re, nowrap) { return this.find(re,nowrap,true) }, - - indentation: function(){ - // returns the whitespace at the start of this line - return /^\s*/.exec(this.clone().bounds('line').text())[0]; - }, - - indent: function (tabs){ - // tabs is the string to insert before each line of the range - var oldtext = this.text(), newtext = indent(oldtext, tabs), b = this.bounds(); - this.text(newtext); - // Need to indent the line containing the start of the range (indent only adds the tabs after newlines) - this.clone().bounds('BOL').text(tabs); - // Adjust bounds - return this.bounds([b[0]+tabs.length, b[1]+tabs.length+newtext.length-oldtext.length]); - }, - - unindent: function (n, tabSize){ - // remove n tabs or sets of tabSize spaces from the beginning of each line - tabSize = tabSize || this.data().tabSize || 8; // 8 is the browser default - // remove internal tabs - var oldtext = this.text(), newtext = unindent(oldtext, n, tabSize, false), b = this.bounds(); - var diffInternal = newtext.length-oldtext.length; - this.text(newtext).bounds([b[0], b[1]+diffInternal]); - // remove initial tabs - var line = this.clone().bounds('line'); - oldtext = line.text(); - newtext = unindent(oldtext, n, tabSize, true); - line.text(newtext); - var diffStart = newtext.length-oldtext.length; - return this.bounds([Math.max(line.bounds()[0], b[0]+diffStart), b[1]+diffInternal+diffStart]); - }, - - line:function(n){ - // set the bounds to the nth line or - // return the line number of the start of the bounds. Note that it is 1-indexed, the way ex writes it! - if (arguments.length){ - n = parseInt(n); - if (isNaN(n)) return this; - // if n is too large,set the bounds to the end; if too small, to the beginning - if (n > this.all().split('\n').length) return this.bounds('end'); - if (n < 1) return this.bounds([0,0]); - // move to the given line number, at same character number as the initial bounds. - var start = this.bounds(); - this.bounds('BOL'); - var c = start[0] - this.bounds()[0]; // character number - // so find n-1 newlines to get to the correct line, then c characters over (if we don't have that many, go to the end of the line) - var re = new RegExp('(.*\\n){'+(n-1)+'}(.{'+c+'}|.*$)', 'm'); - return this.bounds('all').find(re).bounds('endbounds'); - }else{ - // just count newlines before this.bounds - // If we are on the boundary between lines (i.e. after the newline), this counts the next line - return this.all().slice(0, this.bounds()[0]).split('\n').length; - } - }, - - live: function(on){ - var self = this; - if (arguments.length == 0 || on){ - this._oldtext = self.all(); // resync the text if it should be necessary - if (this._inputHandler) return this; // don't double-bind - this._inputHandler = function(ev){ - // first find the change. - var start, oldend, newend; - var newtext = self.all(); - if (newtext == self._oldtext) return; // no change - if (!ev.bounds){ - // "real" input events don't tell us the bounds (and until they really support DOM 3 events, not even the text. - // we have to start from scratch. - var change = diff (self._oldtext, newtext); - ev.bounds = change.bounds; // save it for future events - ev.data = change.data; - } - start = ev.bounds[0]; - oldend = ev.bounds[1]; - newend = ev.bounds[0]+ev.data.length; - self._oldtext = newtext; - // adjust bounds; this tries to emulate the algorithm that Microsoft Word uses for bookmarks - if (self._bounds[0] <= start){ - // no change - }else if (self._bounds[0] > oldend){ - self._bounds[0] += newend - oldend; - }else{ - self._bounds[0] = newend; - } - if (self._bounds[1] < start){ - // no change - }else if (self._bounds[1] >= oldend){ - self._bounds[1] += newend - oldend; - }else{ - self._bounds[1] = start; - } - }; - self.listen('input', self._inputHandler); - }else{ - self.dontlisten('input', self._inputHandler); - delete self._inputHandler; - } - return this; - }, - - findprimitive: function(re, bounds){ - // search for re within the bounds given. Return the result of the RegExp.exec call or false if not found. - // re needs to be global for this to work! - var text = this.all(); - re.lastIndex = bounds[0]; - var match = re.exec(text); - if (!match || match.index+match[0].length > bounds[1]) return false; - return match; - }, - - findprimitiveback: function (re, bounds){ - // no way to search backwards; have to search forward until we fail - var match = false; - do { - var lastmatch = match; - match = this.findprimitive(re, bounds); - bounds[0] = match.index+1; - }while (match); - return lastmatch; - } -}); - -// utilities -function globalize (re){ - // make a RegExp global, to allow multiple searches - return new RegExp(re.source, 'g'+(re.ignoreCase ? 'i' : '') + (re.multiline ? 'm' : '')); -} -function matchIs(match, bounds){ - // check if the match that we just found is the same as the existing bounds, since we shouldn't count that - // this way, "Find Next" won't keep coming back to the same string. - // I think this is the way that Word does it - return match && match.index == bounds[0] && match[0].length == bounds[1]-bounds[0]; -} - -function diff (oldtext, newtext){ - // Try to find the changed text , assuming it was a continuous change - // This is wrong for drag and drop, which only fires one input event for both removal and insertion - var oldlen = oldtext.length; - var newlen = newtext.length; - for (var i = 0; i < newlen && i < oldlen; ++i){ - if (newtext.charAt(i) != oldtext.charAt(i)) break; - } - var start = i; - for (i = 0; i < newlen && i < oldlen; ++i){ - var newpos = newlen-i-1, oldpos = oldlen-i-1; - if (newpos < start || oldpos < start) break; - if (newtext.charAt(newpos) != oldtext.charAt(oldpos)) break; - } - var oldend = oldlen-i; - var newend = newlen-i; - return {bounds: [start, oldend], data: newtext.slice(start, newend)} -}; -bililiteRange.diff = diff; // expose - -function indent(text, tabs){ - return text.replace(/\n/g, '\n'+tabs); -} -function unindent(str, count, tabwidth, start){ - // count can be an integer >= 0 or Infinity. - // (We delete up to 'count' tabs at the beginning of each line.) - // If invalid, defaults to 1. - // - // tabwidth can be an integer >= 1. - // (The number of spaces to consider a single tab.) - // If invalid, defaults to 4. - // - // Either can also be a string or number that rounds to that. - // - // start=true: unindent only the first line of the string. - // start=false: unindent any line in the string except the first. - tabwidth = Math.round(tabwidth); - count = Math.round(count); - if (!isFinite(tabwidth) || tabwidth < 1) tabwidth = 4; - if (isNaN(count) || count < 0) count = 1; - if (!isFinite(count)) count = ''; - var re = new RegExp((start ? '(^)' : '(\\n)') + '(?:\t| {'+tabwidth+'}){1,'+count+'}', 'g'); - return str.replace(re, '$1'); -} - -})(); \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/prism/prism.css b/src/main/webapp/connect/confluence/prism/prism.css deleted file mode 100644 index 9bc4fd1d..00000000 --- a/src/main/webapp/connect/confluence/prism/prism.css +++ /dev/null @@ -1,234 +0,0 @@ -/* PrismJS 1.16.0 -https://prismjs.com/download.html#themes=prism&languages=json&plugins=line-highlight+line-numbers */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - background: none; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - font-size: 1em; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - line-height: 1.5; - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #f5f2f0; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; - white-space: normal; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol, -.token.deleted { - color: #905; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.char, -.token.builtin, -.token.inserted { - color: #690; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string { - color: #9a6e3a; - background: hsla(0, 0%, 100%, .5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} - -.token.function, -.token.class-name { - color: #DD4A68; -} - -.token.regex, -.token.important, -.token.variable { - color: #e90; -} - -.token.important, -.token.bold { - font-weight: bold; -} -.token.italic { - font-style: italic; -} - -.token.entity { - cursor: help; -} - -pre[data-line] { - position: relative; - padding: 1em 0 1em 3em; -} - -.line-highlight { - position: absolute; - left: 0; - right: 0; - padding: inherit 0; - margin-top: 1em; /* Same as .prism’s padding-top */ - - background: hsla(24, 20%, 50%,.08); - background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); - - pointer-events: none; - - line-height: inherit; - white-space: pre; -} - - .line-highlight:before, - .line-highlight[data-end]:after { - content: attr(data-start); - position: absolute; - top: .4em; - left: .6em; - min-width: 1em; - padding: 0 .5em; - background-color: hsla(24, 20%, 50%,.4); - color: hsl(24, 20%, 95%); - font: bold 65%/1.5 sans-serif; - text-align: center; - vertical-align: .3em; - border-radius: 999px; - text-shadow: none; - box-shadow: 0 1px white; - } - - .line-highlight[data-end]:after { - content: attr(data-end); - top: auto; - bottom: .4em; - } - -.line-numbers .line-highlight:before, -.line-numbers .line-highlight:after { - content: none; -} - -pre[class*="language-"].line-numbers { - position: relative; - padding-left: 3.8em; - counter-reset: linenumber; -} - -pre[class*="language-"].line-numbers > code { - position: relative; - white-space: inherit; -} - -.line-numbers .line-numbers-rows { - position: absolute; - pointer-events: none; - top: 0; - font-size: 100%; - left: -3.8em; - width: 3em; /* works for line-numbers below 1000 lines */ - letter-spacing: -1px; - border-right: 1px solid #999; - - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -} - - .line-numbers-rows > span { - pointer-events: none; - display: block; - counter-increment: linenumber; - } - - .line-numbers-rows > span:before { - content: counter(linenumber); - color: #999; - display: block; - padding-right: 0.8em; - text-align: right; - } - diff --git a/src/main/webapp/connect/confluence/prism/prism.js b/src/main/webapp/connect/confluence/prism/prism.js deleted file mode 100644 index d270a860..00000000 --- a/src/main/webapp/connect/confluence/prism/prism.js +++ /dev/null @@ -1,6 +0,0 @@ -/* PrismJS 1.16.0 -https://prismjs.com/download.html#themes=prism&languages=json&plugins=line-highlight+line-numbers */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(g){var c=/\blang(?:uage)?-([\w-]+)\b/i,a=0,C={manual:g.Prism&&g.Prism.manual,disableWorkerMessageHandler:g.Prism&&g.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof M?new M(e.type,C.util.encode(e.content),e.alias):Array.isArray(e)?e.map(C.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(k instanceof M)){if(f&&y!=a.length-1){if(c.lastIndex=v,!(x=c.exec(e)))break;for(var b=x.index+(h?x[1].length:0),w=x.index+x[0].length,A=y,P=v,O=a.length;A"+t.content+""},!g.document)return g.addEventListener&&(C.disableWorkerMessageHandler||g.addEventListener("message",function(e){var a=JSON.parse(e.data),t=a.language,n=a.code,r=a.immediateClose;g.postMessage(C.highlight(n,C.languages[t],t)),r&&g.close()},!1)),C;var e=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return e&&(C.filename=e.src,C.manual||e.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(C.highlightAll):window.setTimeout(C.highlightAll,16):document.addEventListener("DOMContentLoaded",C.highlightAll))),C}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); -Prism.languages.json={comment:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,property:{pattern:/"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,greedy:!0},string:{pattern:/"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,greedy:!0},number:/-?\d+\.?\d*(e[+-]?\d+)?/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}}; -!function(){if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var t,h=function(){if(void 0===t){var e=document.createElement("div");e.style.fontSize="13px",e.style.lineHeight="1.5",e.style.padding=0,e.style.border=0,e.innerHTML=" 
 ",document.body.appendChild(e),t=38===e.offsetHeight,document.body.removeChild(e)}return t},l=0;Prism.hooks.add("before-sanity-check",function(e){var t=e.element.parentNode,n=t&&t.getAttribute("data-line");if(t&&n&&/pre/i.test(t.nodeName)){var i=0;r(".line-highlight",t).forEach(function(e){i+=e.textContent.length,e.parentNode.removeChild(e)}),i&&/^( \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}}),Prism.hooks.add("complete",function e(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){clearTimeout(l);var r=Prism.plugins.lineNumbers,o=t.plugins&&t.plugins.lineNumbers;g(n,"line-numbers")&&r&&!o?Prism.hooks.add("line-numbers",e):(a(n,i),l=setTimeout(s,1))}}),window.addEventListener("hashchange",s),window.addEventListener("resize",function(){var e=document.querySelectorAll("pre[data-line]");Array.prototype.forEach.call(e,function(e){a(e)})})}function r(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function g(e,t){return t=" "+t+" ",-1<(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)}function a(e,t,n){for(var i,r=(t="string"==typeof t?t:e.getAttribute("data-line")).replace(/\s+/g,"").split(","),o=+e.getAttribute("data-line-offset")||0,l=(h()?parseInt:parseFloat)(getComputedStyle(e).lineHeight),a=g(e,"line-numbers"),s=0;i=r[s++];){var d=i.split("-"),u=+d[0],c=+d[1]||u,m=e.querySelector('.line-highlight[data-range="'+i+'"]')||document.createElement("div");if(m.setAttribute("aria-hidden","true"),m.setAttribute("data-range",i),m.className=(n||"")+" line-highlight",a&&Prism.plugins.lineNumbers){var p=Prism.plugins.lineNumbers.getLine(e,u),f=Prism.plugins.lineNumbers.getLine(e,c);p&&(m.style.top=p.offsetTop+"px"),f&&(m.style.height=f.offsetTop-p.offsetTop+f.offsetHeight+"px")}else m.setAttribute("data-start",u),u");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,n.hasAttribute("data-start")&&(n.style.counterReset="linenumber "+(parseInt(n.getAttribute("data-start"),10)-1)),e.element.appendChild(l),m(n),Prism.hooks.run("line-numbers",e)}}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(e,t){if("PRE"===e.tagName&&e.classList.contains(l)){var n=e.querySelector(".line-numbers-rows"),r=parseInt(e.getAttribute("data-start"),10)||1,s=r+(n.children.length-1);t - - - -draw.io Editor - - - - - - - diff --git a/src/main/webapp/connect/confluence/support.html b/src/main/webapp/connect/confluence/support.html deleted file mode 100644 index f11416ec..00000000 --- a/src/main/webapp/connect/confluence/support.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - draw.io Support - - -
-
- -
-

- draw.io Support -

-
- draw.io add-on for Confluence (Version: and License SEN: ) -
-
-
-
-
-
-
-
-

Getting Support

-
-
-
-
    -
  • For support requests relating to installation, data load/save, broken functionality problems, post to our service desk. -
  • Please include the draw.io version and SEN shown on this page to speed up the support process.
  • -
  • Support requests should be routed via an admin, wherever possible.
  • -
-

-
-
-
-

Helpful resources for Admins

-
- -
-

Helpful resources for Users

-
-
-
- - -

-
-
-
-
-
-
- - \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/support.js b/src/main/webapp/connect/confluence/support.js deleted file mode 100644 index f30fb213..00000000 --- a/src/main/webapp/connect/confluence/support.js +++ /dev/null @@ -1,17 +0,0 @@ -AP.request({ - type: 'GET', - url: '/rest/atlassian-connect/1/addons/com.mxgraph.confluence.plugins.diagramly', - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - document.getElementById('drawioLic').innerHTML = resp.license? resp.license.supportEntitlementNumber : 'Unlicensed'; - document.getElementById('drawioVersion').innerHTML = resp.version; - } -}); - -window.intercomSettings = { - app_id: "fz6gxyi6" -}; - -(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/fz6gxyi6';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})(); diff --git a/src/main/webapp/connect/confluence/viewer-1-4-42.html b/src/main/webapp/connect/confluence/viewer-1-4-42.html deleted file mode 100644 index 57a39acb..00000000 --- a/src/main/webapp/connect/confluence/viewer-1-4-42.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - -draw.io Viewer - - - - - - - - - - - - - - - diff --git a/src/main/webapp/connect/confluence/viewer-1-4-8.html b/src/main/webapp/connect/confluence/viewer-1-4-8.html deleted file mode 100644 index b7650726..00000000 --- a/src/main/webapp/connect/confluence/viewer-1-4-8.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - -draw.io Viewer - - - - - - - - - - - - - - - - diff --git a/src/main/webapp/connect/confluence/viewer-init.js b/src/main/webapp/connect/confluence/viewer-init.js deleted file mode 100644 index 60a0d234..00000000 --- a/src/main/webapp/connect/confluence/viewer-init.js +++ /dev/null @@ -1,47 +0,0 @@ -// Parses URL parameters -function getUrlParam(param, treatEmptyAsNull) -{ - var result = (new RegExp(param + '=([^&]*)')).exec(window.location.search); - - if (result != null && result.length > 0) - { - var val = decodeURIComponent(result[1].replace(/\+/g, '%20')); - return treatEmptyAsNull && val != null && val.length == 0 ? null : val; - } - - return null; -}; - -function getBaseUrl() -{ - var baseUrl = getUrlParam('xdm_e', true) + getUrlParam('cp', true); - //Ensure baseUrl belongs to attlasian (*.jira.com and *.atlassian.net) - //Since we add cp to xdm_e, we had to ensure that there is a slash after the domain. Since if xdm_e is ok, cp can corrupt is such as cp = '.fakedomain.com' such that baseUrl is atlassian.net.fakedomain.com - if (/^https:\/\/([^\.])+\.jira\.com\//.test(baseUrl + '/') || /^https:\/\/([^\.])+\.atlassian\.net\//.test(baseUrl + '/')) - { - return baseUrl; - } - throw 'Invalid baseUrl!'; -}; - -// Sets global environment variables -RESOURCE_BASE = '/resources/dia'; -STENCIL_PATH = '/stencils'; -SHAPES_PATH = '/shapes'; -IMAGE_PATH = '/images'; -OPEN_URL = '/import'; -PROXY_URL = '/proxy'; -SAVE_URL = '/save'; - -// Absolute for font conversion in lightbox to work -PROXY_URL = '/proxy'; - -var lightbox = getUrlParam('lightbox') == '1'; -var customContent = getUrlParam('custom') == '1'; - -if (lightbox) -{ - document.body.style.backgroundImage = 'url(/images/drawlogo-text-bottom.svg)'; - document.body.style.backgroundPosition = 'center 30%'; - document.body.style.backgroundSize = '128px'; -} diff --git a/src/main/webapp/connect/confluence/viewer.js b/src/main/webapp/connect/confluence/viewer.js deleted file mode 100644 index 90ca89b9..00000000 --- a/src/main/webapp/connect/confluence/viewer.js +++ /dev/null @@ -1,1415 +0,0 @@ -(function() -{ - // Logs uncaught errors - EditorUi.enableLogging = true; - - window.onerror = function(message, url, linenumber, colno, err) - { - message = 'Confluence Cloud: ' + ((message != null) ? message : ''); - - EditorUi.logError(message, url, linenumber, colno, err); - }; - - var EXPORT_URL = 'https://exp.draw.io/ImageExport4/export'; - - // Enables dynamic loading of shapes and stencils (same domain) - mxStencilRegistry.dynamicLoading = true; - - // Loads the Atlassian API - var script = document.createElement('script'); - var baseUrl = getBaseUrl(); - - // Loads the attachment and renders the diagram - var diagramWidth = parseFloat(getUrlParam('width')); - var diagramHeight = parseFloat(getUrlParam('height')); - var diagramName = getUrlParam('diagramName'); - var displayName = getUrlParam('displayName'); - - //ceoId and owningPageId are IDs of the page that potentially hold the attachment - //they will differ when page history is shown, ceoId will be historical version ID, - //owningPageId will be the ID of the current version that holds the attachment - //ceoId is used as fallback in case owningPageId is not set(should be very rare) - var ceoId = getUrlParam('ceoId'); - var owningPageId = getUrlParam('owningPageId'); - var revision = getUrlParam('revision'); - - var tbStyle = getUrlParam('tbstyle') || 'top'; - var links = getUrlParam('links') || 'auto'; - var enableLightbox = getUrlParam('lbox') != '0'; - var simpleViewer = getUrlParam('simple') == '1'; - var tbHeight = (tbStyle == 'top' && !simpleViewer) ? GraphViewer.prototype.toolbarHeight : 0; - var zoom = parseFloat(getUrlParam('zoom') || 1); - var border = (simpleViewer) ? 0 : 8; - var pCenter = getUrlParam('pCenter') == '1'; - - var contentId = getUrlParam('contentId') || getUrlParam('custContentId'); - var contentVer = getUrlParam('contentVer'); - var linkedMode = getUrlParam('linked') == '1'; - var diagramUrl = getUrlParam('diagramUrl'); - var csvFileUrl = getUrlParam('csvFileUrl'); - var inComment = getUrlParam('inComment') == '1'; - var aspect = getUrlParam('aspect'); - var imgPageId = getUrlParam('imgPageId'); - var aspectHash = getUrlParam('aspectHash'); - var attVer = getUrlParam('attVer', true); - var service = getUrlParam('service', true); - var sFileId = getUrlParam('sFileId', true); - var odriveId = getUrlParam('odriveId', true); - var userCanEdit = {}; //0: Unknown, 1: Yes, -1: No. For each pageId - // Workaround for blocked referrer in iframe - Graph.prototype.baseUrl = baseUrl + '/pages/viewpage.action?pageId=' + owningPageId; - - var openPageImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4goKFCgQ6ZBdjgAAAvJJREFUWMPFlz+IFHcUxz/vt7Nzu7fuKYqGM7HQKBISUc8gwcYiRcDKJliqRYRUkkYtUgRUCIekCQFbxUIDFxBCimAKBUtRJEVQLyRGZV31yO1e9vbPzO+b4obLnl682bm99TW/md/Me+/7vr/3Z8boEkkTwDayiQFV4KCZ1TNZkHRXy5cHvfgM/md/EzDdg51/gDvADuBdSZPA+0DLzJSFgXIG9m4nuleT9Z6k0lJ6jv7LUeBikkt33wSA0MwOJyC2SJqUVJJkgwIggATEBWBLkh/FQQH4ry7NjiQgtgK/DgpAfREQ3wKbJf0uaSRNGS5H7kuaeWmvAUTAZuAGsGslAAwl68Yl3tu5UgzsXsRemLRogCbwC/BRTwCefBkWyyP6ChG97r2Z8fCVyVCr2em3z7SbXc2qk7YVz0uhqDEHJyLvF46dVoj8XHDmBEMt6Cr1MHAUh+MfgFtZZsErha1u752Q0md3cIW5hPbNaWrn95IrNgDf1Q2yD6PXS34Dwei2rlp+i/rUekZG/8I535Op/vUBg9rTAO+tJ7VsDEQV4hcP8a1GEkYBRRUsEDPVPOX1ndSWMwAQeCFX4tGp9yCX551z91AbLBDeQ60aEm6MsP4dgQHCbBhYxfCnPzL90zhujcOVY2o/f8OGzy8jimAlJE/9WZ6onesTAwLCTYR7jkOuSH77x0TXLiWZLqKpCqWxA0TVsyiapX79O3z0lMbzvEG7HwA8wQfHKOz/Yn5r7aGveXzy+/lrzFj9yTFwDt+epXn9LGbWxyPwLzVCxYAlJCRF71zS8eL+l6Fqfy64j2emIDAsMOL684XPXvyRKvr0R+DAT17h8fEJOlE+8dLECnORVsb3Qa4wx4T3WChCl64bBmnyH4GsyarRHI2/O7QbBjnNDzoLPTDbpeVTk7skAC8qztlvAbkWwMi6iFoUSJF1TdpFKHMMEVPN+mdUZgVE0g1JGthH6XKqoLVC/nzaHLgpabbPzmNgf1oAHw7qCP4Fs6J7VGnK/oIAAAAASUVORK5CYII='; - - if (!lightbox) - { - document.body.style.backgroundImage = 'url(/images/aui-wait.gif)'; - document.body.style.backgroundPosition = 'left top'; - document.body.style.backgroundSize = 'auto auto'; - } - - function main() - { - // Sets initial placeholder size to allow for scrollbars in fit to page width - AP.resize('100%', (lightbox || customContent) ? '100%' : (diagramHeight * zoom + tbHeight + 2)); - - function showError(msg) - { - document.body.style.backgroundImage = 'none'; - document.body.style.padding = '4px'; - mxUtils.write(document.body, msg); - AP.resize('100%', 24); - }; - - //keeping the block of AP.require to mimimize the number of changes! - { - //This is a workaround Jira Service Desk preview which has no context. - //AP.navigator.getLocation will just log an error and callback function won't be called - var ignoreNavFallback = false; - var isServiceDesk = false; //In service desk, we cannot show dialogs as we cannot pass customData - - var fallbackTimeoutThread = window.setTimeout(function() - { - if (!ignoreNavFallback) - { - isServiceDesk = true; - startViewer(); - } - }, 500); //allow 0.5 sec for AP.navigator.getLocation - - // Uses pageId from current page as page in macro may be outdated after export - AP.navigator.getLocation(function (data) - { - ignoreNavFallback = true; - window.clearTimeout(fallbackTimeoutThread); - startViewer(data); - }); - - function startViewer(data) - { - var candidateId = (owningPageId != null && owningPageId.length > 0) ? owningPageId : ceoId; - - if (!linkedMode && data != null && data.target != null && data.context != null) - { - candidateId = data.context.contentId; - } - - function showExtDiagram(name, url) - { - mxUtils.get(url, function(req) - { - if (req.getStatus() >= 200 && req.getStatus() <= 299) - { - try - { - var xml = req.getText(); - - document.body.style.backgroundImage = 'none'; - - //In case we want to load another diagram - var oldContainer = document.getElementById("drawIODiagram"); - - if (oldContainer != null) - { - oldContainer.parentNode.removeChild(oldContainer); - } - // LATER: Fix horizontal alignment ignored with 100% width of iframe - // LATER: Fix page scrolling on touch device if trigger event on diagram - // LATER: Hide toolbar after second container click for iOS - // LATER: Disable responsive resize while lightbox shows - var container = document.createElement('div'); - container.id = "drawIODiagram"; - container.style.cssText = 'position:absolute;' + - 'max-width:100%;border:1px solid transparent;'; - document.body.appendChild(container); - var doc = mxUtils.parseXml(xml); - - var config = {highlight: '#3572b0', 'toolbar-position': tbStyle, - nav: true, zoom: zoom}; - - config.lightbox = false; - config.toolbar = 'pages zoom layers'; - config.border = border; - config.title = name; - config.resize = true; - - if (aspect != null) - { - //Set pageId and layers - var aspectArray = aspect.split(' '); - - if (aspectArray.length > 1) - { - config.pageId = aspectArray[0]; - config.layerIds = aspectArray.slice(1); - } - } - - var viewer = new GraphViewer(container, doc.documentElement, config); - - // Handles resize of iframe after zoom - var graphDoResizeContainer = viewer.graph.doResizeContainer; - - function updateHeight(height) - { - AP.resize('100%', Math.ceil(height) + tbHeight + 2); - }; - - viewer.graph.doResizeContainer = function(width, height) - { - graphDoResizeContainer.apply(this, arguments); - updateHeight(height); - }; - - // Updates the size of the iframe in responsive cases - viewer.updateContainerHeight = function(container, height) - { - updateHeight(height); - }; - - updateHeight(container.offsetHeight); - } - catch(e) - { - showError(e.message); - } - } - else - { - if (req.getStatus() == 404) - { - showError(mxResources.get('fileNotFound')); - } - } - }, function() - { - showError(mxResources.get('unknownError')); - }, false, 25000, function() - { - showError(mxResources.get('confTimeout')); - }); - }; - - // Loads the given XML into the viewer - function showDiagram(id, backupId, name, revision, links, retryParams, displayName, contentId, spaceKey, openComments, aspect) - { - //Check if the user can edit this diagram - if (userCanEdit[id] == null) - { - if (inComment || (owningPageId != null && candidateId != owningPageId)) //TODO If the page id in the macro doesn't match the current page, we cannot edit it, fix this by allowing finding macro by owningPageId - { - userCanEdit[id] = -1; //TODO enable editing macros in comments externally (requires finding which comment it belongs to and editing that comment content) - } - else - { - var acceptPermResponse = true; - - var permTimer = setTimeout(function() - { - acceptPermResponse = false; - userCanEdit[id] = 0; - showDiagram(id, backupId, name, revision, links, retryParams, displayName, contentId, spaceKey, openComments, aspect); - }, 5000); //Five second timeout - - AC.userCanEdit(id, function(canEdit) - { - if (acceptPermResponse) - { - window.clearTimeout(permTimer); - userCanEdit[id] = canEdit? 1 : -1; - showDiagram(id, backupId, name, revision, links, retryParams, displayName, contentId, spaceKey, openComments, aspect); - } - }, function() - { - if (acceptPermResponse) - { - window.clearTimeout(permTimer); - userCanEdit[id] = 0; - showDiagram(id, backupId, name, revision, links, retryParams, displayName, contentId, spaceKey, openComments, aspect); - } - }); - - return; - } - } - - displayName = displayName || name; - retryParams = retryParams || {}; //so we can use it without NPE check - - var aspectPageId = null, aspectLayerIds = null; - - if (aspect != null) - { - //Set pageId and layers - var aspectArray = aspect.split(' '); - - if (aspectArray.length > 1) - { - aspectPageId = aspectArray[0]; - aspectLayerIds = aspectArray.slice(1); - } - } - - if (id != null) - { - id = id.toString(); - } - - if (id != null && id.length > 0 && name != null && name.length > 0) - { - // Option currently not available in the UI - if (simpleViewer) - { - document.body.style.backgroundImage = 'none'; - var img = document.createElement('img'); - img.style.cssText = 'max-width:100%;'; - img.setAttribute('src', baseUrl + '/download/attachments/' + id + '/' - + encodeURIComponent(name) + ".png?api=v2" - + (revision != null ? "&version=" + revision : "")); - - if (zoom != 1) - { - img.style.width = Math.round(diagramWidth * zoom) + 'px'; - } - - document.body.appendChild(img); - } - else - { - var timeout = 25000; - var serverName = getUrlParam('xdm_e'); - var index1 = serverName.indexOf('//'); - - if (index1 > 0) - { - var index2 = serverName.indexOf('/', index1 + 2); - - if (index2 > index1) - { - serverName = serverName.substring(index1 + 2, index2); - } - else - { - serverName = serverName.substring(index1 + 2); - } - } - - var acceptResponse = true; - - var timeoutThread = window.setTimeout(function() - { - acceptResponse = false; - - if (lightbox) - { - AC.showNotification({ - title: mxResources.get('confTimeout'), - body: mxResources.get('confSrvTakeTooLong', [serverName]), - type: 'error', - close: 'manual' - }); - - //TODO find how to listen to flag close event, currently just close the dialog immidiately - //AP.events.on('flag.close', function() - //{ - AP.dialog.close(); - //}); - } - else - { - showError(mxResources.get('confTimeout') + ': ' + - mxResources.get('confSrvTakeTooLong', [serverName])); - } - }, timeout); - - AP.request( - { - url: '/download/attachments/' + id + '/' + encodeURIComponent(name) + - ((revision != null && revision.length > 0) ? '?version=' + revision : ''), - success: function(xml) - { - window.clearTimeout(timeoutThread); - - if (acceptResponse) - { - document.body.style.backgroundImage = 'none'; - - var openParentPageFunc = function() - { - var openURL = function(pageURL) - { - try - { - top.window.location.href = pageURL; - } - catch(e) //In case of a security exception - { - window.location = pageURL; - } - }; - - AP.request({ - type: 'GET', - url: '/rest/api/content/' + id, - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - if (userCanEdit[id] != -1) - { - openURL(baseUrl + '/spaces/' + encodeURIComponent(spaceKey) + '/pages/edit/' + id); - } - else - { - //Open in view mode - openURL(baseUrl + '/spaces/' + encodeURIComponent(spaceKey) + '/pages/' + id); - } - }, - error: function (resp) - { - //On error, we assume it is a draft page - openURL(baseUrl + '/spaces/' + encodeURIComponent(spaceKey) + '/pages/create?draftId=' + id); - //TODO we can confirm page exist with another request + "?status=draft" and show error message if page cannot be found - } - }); - }; - - function monitorPopup(editWin) - { - if (editWin != null) - { - var checkClosedTimer = setInterval(function() - { - if (editWin.closed !== false) - { - clearInterval(checkClosedTimer); - location.reload(); - } - }, 200); - } - }; - - var editFunc = function() - { - if (lightbox) - { - AP.dialog.close({noBack: true, openEditorId: contentId}); - } - else - { - //We support editing Google Drive, OneDrive only - if (linkedMode) - { - var editWin = null; - - if (service == 'GDrive') - { - editWin = window.open('https://' + window.location.hostname + '/#G' + encodeURIComponent(sFileId)); - } - else if (service == 'OneDrive') - { - editWin = window.open('https://' + window.location.hostname + '/#W' + encodeURIComponent(odriveId + '/' + sFileId)); - } - - monitorPopup(editWin); - return; - } - - AP.dialog.create( - { - key: 'customContentEditor', - //sending pageId and revision to verify custom content matches opened diagram - customData: {contentId: contentId, - macroData: { - width: diagramWidth, - height: diagramHeight, - diagramName: name, - diagramDisplayName: displayName, - pageId: id, - revision: revision, - tbstyle: tbStyle, - links: links, - simple: simpleViewer, - lbox: enableLightbox, - zoom: zoom, - contentVer: contentVer, - contentId: contentId, - custContentId: contentId, - aspect: aspect - } - }, - chrome: false, - width: "100%", - height: "100%", - }).on("close", function(flags) - { - //refresh the viewer - if (flags && flags.newRev && flags.newContentVer && flags.newContentId) - { - contentVer = flags.newContentVer; - contentId = flags.newContentId; - showDiagram(id, backupId, name, flags.newRev, links, retryParams, displayName, contentId, null, null, flags.newAspect); - } - }); - } - }; - - var commentsWindow = null; - - //Comments are only shown in lightbox mode - if (lightbox) - { - //Adjust some functions such that it can be instanciated without UI - EditorUi.prototype.createUi = function(){}; - EditorUi.prototype.addTrees = function(){}; - EditorUi.prototype.updateActionStates = function(){}; - var editorUi = new EditorUi(); - AC.loadPlugins(editorUi); - - //Plugins doesn't have callbacks, so we use this hack. TODO Improve this - function waitForUser() - { - if (editorUi.getCurrentUser().email == null) - { - setTimeout(waitForUser, 100); - } - else if (openComments) //Open the comments window here when the user is ready - { - openCommentsFunc(); - } - } - - waitForUser(); - } - - var openCommentsFunc = function(e) - { - if (commentsWindow != null) - { - commentsWindow.window.setVisible(commentsWindow.window.isVisible()? false : true); - } - else - { - var busyIcon = null; - //Show busy icon - try - { - if (e && e.target) - { - busyIcon = document.createElement('img'); - busyIcon.src = '/images/spin.gif'; - e.target.parentNode.appendChild(busyIcon); - } - } catch(e){} - - var spaceKey, pageId, pageType, contentVer; - - editorUi.saveComments = function(comments, success, error) - { - AC.saveCustomContent(spaceKey, pageId, pageType, name, displayName, revision, - contentId, contentVer, - function(responseText) - { - var content = JSON.parse(responseText); - - contentId = content.id; - contentVer = content.version.number; - - success(); - }, error, comments, true); - }; - - function createCommentsWindow() - { - commentsWindow = new CommentsWindow(editorUi, document.body.offsetWidth - 380, 120, 300, 350); - commentsWindow.window.setVisible(true); - //Lightbox Viewer has 999 zIndex - commentsWindow.window.getElement().style.zIndex = 2000; - - if (busyIcon != null) - { - busyIcon.parentNode.removeChild(busyIcon); - busyIcon = null; - } - }; - - //Get current diagram information which is needed for comments - //TODO Viewer should use AC to load diagrams, then this won't be needed - AC.getAttachmentInfo(id, name, function(info) - { - AC.curDiagVer = info.version.number; - AC.curDiagId = info.id; - }, function() - { - AC.curDiagId = false; - }); - - editorUi.initComments(contentId, function(spaceKey_p, pageId_p, pageType_p, contentVer_p) - { - spaceKey = spaceKey_p; pageId = pageId_p; pageType = pageType_p; contentVer = contentVer_p; - createCommentsWindow(); - }, createCommentsWindow); - } - }; - - if (lightbox) - { - var config = {highlight: '#3572b0', nav: true, lightbox: false}; - - var lbBtns = []; - - if (spaceKey != null && spaceKey.length > 0) - { - if (userCanEdit[id] != -1) - { - lbBtns.push({icon: Editor.editLargeImage, tooltip: mxResources.get('edit'), fn: editFunc}); - } - - lbBtns.push({icon: openPageImg, tooltip: mxResources.get('confGotoPage'), fn: openParentPageFunc}); - } - - lbBtns.push({icon: Editor.commentImageInverted, tooltip: mxResources.get('comments'), fn: openCommentsFunc}); - EditorUi.prototype.lightboxToolbarActions = lbBtns; - - if (links != 'auto') - { - config.target = links; - } - - config.pageId = aspectPageId; - config.layerIds = aspectLayerIds; - - var viewer = new GraphViewer(null, null, config); - - viewer.lightboxChrome = false; - viewer.xml = xml; - - // Enables layers via flag to avoid toolbar - viewer.layersEnabled = true; - - var ui = viewer.showLocalLightbox(); - // Destroy lightbox with ui instance - var destroy = ui.destroy; - ui.destroy = function() - { - AP.dialog.close(); - destroy.apply(this, arguments); - }; - - // Workaround for ignored header toolbar height for iframe - ui.editor.graph.container.style.bottom = '51px'; - } - else - { - //In case we want to load another diagram - var oldContainer = document.getElementById("drawIODiagram"); - - if (oldContainer != null) - { - oldContainer.parentNode.removeChild(oldContainer); - } - // LATER: Fix horizontal alignment ignored with 100% width of iframe - // LATER: Fix page scrolling on touch device if trigger event on diagram - // LATER: Hide toolbar after second container click for iOS - // LATER: Disable responsive resize while lightbox shows - var container = document.createElement('div'); - container.id = "drawIODiagram"; - //There is an issue with AP.resize when custom content is shown. It works only once! - if (customContent) { - document.body.style.overflow = "auto"; - } - container.style.cssText = (customContent? '' : 'position:absolute;') + - 'max-width:100%;border:1px solid transparent;'; - document.body.appendChild(container); - var doc = mxUtils.parseXml(xml); - - var config = {highlight: '#3572b0', 'toolbar-position': tbStyle, - nav: true, border: 2, zoom: zoom}; - - if (pCenter) - { - config['auto-fit'] = true; - config['resize'] = false; - container.style.width = '100%'; - } - - if (tbStyle == 'top') - { - config.title = displayName; - } - - if (links != 'auto') - { - config.target = links; - } - - if (!enableLightbox) - { - config.lightbox = false; - } - - if (tbStyle != 'hidden') - { - config.toolbar = 'pages zoom layers'; - config.border = border; - - if (enableLightbox) - { - config.toolbar += ' lightbox'; - } - } - else - { - // Workaround for invalid width if no toolbar is present - var updateContainerWidth = GraphViewer.prototype.updateContainerWidth; - - GraphViewer.prototype.updateContainerWidth = function(container, width) - { - width += 3; - updateContainerWidth.apply(this, arguments); - }; - - config.resize = true; - } - - - if ((userCanEdit[id] != -1 //We treat 0 (unknown as allowed since anyway the editor will show an error on save) - && contentId != null && contentId.length > 0 && tbStyle != 'hidden' && !linkedMode && !isServiceDesk) || - - (service != null && service.length > 0 && service != 'AttFile')) - { - config.toolbar = 'edit ' + config.toolbar; - var editImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAD1BMVEUAAAAAAAAQEBBycnIgICBqwj3hAAAAAXRSTlMAQObYZgAAADlJREFUCNdjoBwoChrAmCyGggJwYWVBBSiTSVDICKFa0AEuLCiEJKyAX5gBSZgBSZgBKGwMBKQ7HAAWzQSfKKAyBgAAAABJRU5ErkJggg=='; - - config['toolbar-buttons'] = - { - 'edit': {title: mxResources.get('edit'), enabled: true, - image: editImage, handler: editFunc} - }; - } - else if (linkedMode && contentId != null && contentId.length > 0) - { - config.toolbar = 'gotoPage ' + config.toolbar; - var gotoPageImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAYAAACpF6WWAAAMfHpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHja7ZlrbiS7DYX/axVZgt6UlqMnkB1k+fkole22xzN37k0QBEHcsKu7uoqieMjDw7JZ//j7Nn/jJ7pQTExScs3Z8hNrrL7xptj7c4/OxvP3fkjPd+7zefP+hedU4Bjux7ye6xvn08cNEp/z/fN5I+OxUx5D7t3w+Qm6sr5/riuPoeDvefd8NvW5r8WX7Ty/fjxmH+NfP0chGDNhL3jjV3DB8rfoKuH+Nn4zf12oXORCOGc8f2Pw38fOvL/9Erz3d19iZ9tzPnwOhbH5uSB/iVF+R+nz+fC+jP+M2sfKn75gv9u+/rzEbu9Z9l53dy1mIpXNs6m3rZx3XNgJZTi3ZV7Cb+K9nFflVdjiALEJmp3XMK46r6u76KZrbrt1jsMNXIx+eeHo/fDhnCtBfPUjKARRX257CTVMEwpoDFALisi7L+6sW896wxVWno4rvcOY444fXua7k3/l9W5ob01d52x5jxV+ec0a3FDk9C9XAYjbT0zTie95mZe8sS/ABhBMJ8yFDTbbr4me3EduhYNz4Lpko7G3NJzMxwAhYu2EMy6AgM0uJJedFe/FOeJYwKfhuQ/RdxBwKfnpzAabEDLgFK9rc4+4c61P/p6GWgAiUTQCNDU0wIoxkT8SCznUUkjRpJRyklRSTS2HHHPKOUtWjmoSJEqSLCJFqrQSSiyp5CKllFpa9TVAYanmKqaWWmtrLNow3bi7cUVr3ffQY089d+ml194G6TPiSCMPGWXU0aafYVL+M08xs8w623KLVFpxpZWXrLLqaptc22HHnXbessuuu72j9qD6GTX3Bblfo+Ye1BSxeK6TD9Q4LfJmwimdJMUMxHx0IC6KAAntFTNbXIxekVPMbPUURfKg5pKCM50iBoJxOZ+2e8fuA7lf4mZS/FO4+Z8hZxS6fwdyRqF7kPsRt29Qm+10lHAA0irUmNqwITYuWKX50rQn/eWj+VcN/N/Q/w39Nxvqbe0i0vyioHhbvPQ0Y5t77EKTSA2SmGv0ku0qIdTk7Y4+d4hmbYF5jOxRJiyyaXpp0Sc5NtdQhyKVD2314fUNbKdMC1OIfiqtSWFxtEIYGDHFw6KwF5aWb73JcE0skiFaNzpX+F62xdK0n65E15R0zJylrUmyVxyx68eRcC1UFzPNoH+1ZO21RSSONWuvPbzDojkmm/2wd631Im0GpVfsxOhqDlPVsNxtsmMkDHs8+8WFas6W2XDYy6UhJeJ4cSxYg7sRoyXPCvnBd3tp3NRGHSHu3ugGXvWHFIJdJgs5OYG9y3wT2Jd12NJZydq7FtTIWmbWDu9PDwGXfnYMzWM8hDXqCaSEnU7oj9GfBd98jf4PwWeWGHmlRAq5GVOgAe5E7q3UX70037gZfw56b3WOMHMZJaiTrZJKYbmIGMWj+gmzKA8uak5xud7VN1hIjI3KcctqcEuWEQP6iLMTX3fxU+IkbxBYuadU1VLOo7ssrnLwguZPg0VBjpNFQ6z9SSoALVPyTsNNHXMIafoTR2oPnwmt1tsyRKyPEyX8LasXf6tQdWeZokV4SpDvUd9Ma26NTbvv/Oo0p31f3xrLLuZBbIVNugAyKzSAwdouOVQ87lJWTHNAEGgDcXiSiw0xt0RaUq4NNUK6dHdwWxr43TWLYumNFfJ0u1fN3Nr30HurvpvogRSJ+loh9u61bzPU7CaoGOLdmOGwO4n/rut4SUT3dpo1PqMDEAeT05u0YidtSqIM25gjinFlttK7MO1xCejaslAbVn33qSU30UYVHdSUr9Adje21fJCfMhQ3DcWk1jTYLB+DtGVb73OXToh9OOhCHlLweV14fwqj+R18iZ8i/AawFvUXgCmRN4xfifYXKCNH21yuBaJnr8fDHkOUQEg1pNaXG+zXbk3v++WOTitqlXR5bqYqbuZmIeOlVkmMthFpIGsiZJXq7ui23FYaZw0h+iTDWD00MC8K6yglpNUr9EYcyYHqEokzSl10FsGj1tnUoQJ1Z6o74ZLbuVJ205mTo7StbkXGGdCd7DVsOGUqvtF8j+gJL3nyBqmG9zOotIDwFO0B1fwBqv/JohUG9u1Nz5NmE8qgTCs8LWcjg3qYum6Mh3H3dHM2WjezBOtl17tlP+Q/UVxVpBsfM02L4FNJ84DuWg+o/iCwF20sDEZ4sAkBxU4lwbJDMmHXR0Cy8+qn05mKbNgFob2UF7fz6PQMNcdpB0Tfc0DmW6nMDN2GOVImc/oC/yUa5NBQEn5mk1MkHXOdk74Q1xzadrr3pE/aEW/cal1qK2w0bkl9eRlrpe0nzKTkQzOgKUD+DCBb41vTiIwyw+bOBAcPgzTNvDYCN4ZOElPNl7mVf/LMa2GmM2dQ0d4wtxTnm/jQGEvYV5M051hEXneXegt59oIYgIaw0Bl2ADClBdGlCpLWTXLVHPoicMSHvagXSo1sxpWRBb01NaLa5rZWxyE7ao1xKy9mMhwCNirQaH5Tgup6ExQXZYqRHXSrXhvP3tJJMU2gwK4yUYarNbmZeqO20KnZZ0hKWugIrdP8yKlWB7ytIbpU5n8z2c1fp7LPTGZ+pLLkmTFj09l1TH3KmR32lDjmXs33SK4sEj0wHY8ZfaRVZTFaBSRH8vCDMHFq4z69v8ypjQjbwEudgRmL1ZlxAq5DPWwyJ9Pa9LMzfiuDkbD0jhYmO3HkntRYyEQAKylCbrkmy3RebUbJdUEGce3hvNpISIjJaH+Ne4StqgH/SerjkSbayuEKHJLPpw6HeimVSR9aQlkQQjmhbeSk0aChm6g3p0ChwRtzcg4UmvMDiGdjpGZCz3PT2lFH6Sy0cxxuTxzcQbdt2DcMB3FKHzfdEEvqIG2U8nB0hWZz8HFCMuXsNWTZqtoQnKNlYogE3UZVkmhLcIMahnIPRHIhyr0vfI3Uw6n2SUHPHa/mK5p4g0iEnkJBZ1Mxs8bhXfeL/oO2G8TzFKjzFeaqjW3SsVGA3BsuXwdipiKr7Zu5eDSF7QPtQsPBl0qt1AGA45j2NZtOwv7B0byegMfQEUcrRXZ1ugkFJXd8gMPe2ojKTJqI9i6aSH9Urajwk659NKGaAtWaGH1438IJHgxcYilQMZ2WCBanpVpZyhOo1JZngDJq28UvF2hEqlXhJlDHtE+mlVYL+oazV0hTD3LTGY+yPgSiFVpZOlVUC9teaaAji6OOB19CsFfV2dPVz5fnOSMOB0Hxk9kxp34adnF3zrAzsbvqtEDHJFnmxcnRkY+6OO2cHoADWgEQBa6ZSVLR1nOulWUaYVI5ylnNI6XOyAC3OhoOQUrLQqrbK78uGCTpJOooNvYU8nWbBFLw1wE/6HQW6DFxHX3w5FHd1z8/v+YRgwtpozPN2WVWClX2vhTafnfWNq8nfpYjJ0XEps+y4bNqII/on7Tb4aOnOK2vRx440SElZZl0C9foPD7knNMs3ESbD4zrGbFMxzg0yCi62kErjKxyaNf8jL1os6b1hkIf2sOZPi2TD/FmHniuoYzQklwYvBlK4hYK0hLwHVVGb0sleJmECnEh6/Si1u/KMIESMFce+tPxj3XcMhvhyDy1feyQn2faGDn6HZc+kkWs1wO+gw6W2ssSiUzVyRgmwGfbxqo4a6BMliWCdOyto2OGojludwXeWfMOyCsnlUbJay0oOhBWYMCA27szNFp7Mxt9/HYLKe96bhBy2f5LXHqtiaBT0LSpijwYnfuHIQeDGleh5UizqMM988nJ3n3Lg1zLIcPldUwkKmnPPSO30Yqz5yHyyCbWtaIORkmnXqZoN/is9DSv4GWutpcvmceWPhZAsv1AgMng5B5na6QZA9pJsynPkOPpXbadjP2Do3k98bO+/tbWVUfjhCJLD+Xaqh2bbu7LMrS7KKWMGONosQynKesZQKv2Ppmu67879QmRn8fTRbJrV6c73scfTjXpML/4+sqK3zLjp/mVmaMP6e20hgo7cWmFD0cSmmftPnPTuu09X1kz0gwqV2mIZQRL0X1c8HzPLlufLq1Hq3QI7mQdQ7gO6ZQIOL26aElw9VAukscWx8fWeLf1WHrsaDs6lrQnvFoiQ6+tH/0a3/tlrmN/1i8SZt/nbEgZ1+aVNRDAZWLRqV6/7OcJFur9kkVYXflr6sMFlOvhwtxogPqo6rnOfHuhPpxqQRd6VsGbswpHVtE7fLmJO2Y+580tGM3coxmYtXSoAV/6ZV+x81NQj1X/36b/Gype/6OLkNexCVmm/tlD/v53q+nXx/8xQyQO4z+B/ifITJ01AbaSPwAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAd0SU1FB+QGExECLJHnOcMAAAGuSURBVDjLrZU/jxJRFMV/lzeBAJHGwkJCLCTEngaNCYmuH8APsAkWNttsZ2Hc2q9AsKKbwj+tNtpYWSvJxIQCqKgmy8DMmzdvbFh3JTDsjpzkNe+ee3LufTf3wSXSa54AeEYGZEP0HfA9g38feL0Wfg58YQ9S4HgP5+Ga9wNY7HJcIB9OgK/Ae+DoUKIR8AL4BnwAnh5C9A5wG3gD/AI+Ak8ugk5O0c9b7j4Bt/KI/twsdY0j4FWm0+Fw+MBxnJeZo5KmaK3Per3eOXD3amyraKFQuJckyWmapgA0m01KpRK+7zOZTC44KKXeAueb+XvLFxHa7TaO4zCfz/E8j3K5nJlzrZ7GcYy1liiKCIIAEaFSqezk7x0ppRTj8Zh+v4/v+wAsFguiKMrntF6v02g0GI1GGGNYLpd0Oh1msxnT6RQRuZlotVql2+0iIogInufRarWo1WoEQcBgMMBae7PyrbUYY7DWkiTJP701xux0mel0tVrhui5hGBKGISKC67oUi0XiOM71+ksR+X3VsYigtUZr/XfUlFLJIfbpLhyv87c6fZxzcz3K+k7+FwLwB1ZLqi6RnWxfAAAAAElFTkSuQmCC'; - - config['toolbar-buttons'] = - { - 'gotoPage': {title: mxResources.get('confGotoPage'), enabled: true, - image: gotoPageImg, handler: function() - { - //Check if the parent page has its macro - AC.findMacroInPage(id, name, false, function(macroFound, originalBody, matchingMacros, page) - { - var editWin = null; - var spaceKey = page._expandable && page._expandable.space? page._expandable.space.substr(page._expandable.space.lastIndexOf('/') + 1) : ''; - - if (macroFound) - { - editWin = window.open(baseUrl + '/spaces/' + encodeURIComponent(spaceKey) + '/pages/edit/' + id); - } - else - { - editWin = window.open(baseUrl + '/pages/viewpageattachments.action?pageId=' + id + '&activeContentType=ac:com.mxgraph.confluence.plugins.diagramly:drawio-diagram'); - } - - monitorPopup(editWin); - }); - }} - }; - } - - config.pageId = aspectPageId; - config.layerIds = aspectLayerIds; - - var viewer = new GraphViewer(container, doc.documentElement, config); - - // Handles resize of iframe after zoom - var graphDoResizeContainer = viewer.graph.doResizeContainer; - - function updateHeight(height) - { - AP.resize('100%', Math.ceil(height) + tbHeight + 2); - }; - - viewer.graph.doResizeContainer = function(width, height) - { - graphDoResizeContainer.apply(this, arguments); - updateHeight(height); - }; - - // Updates the size of the iframe in responsive cases - viewer.updateContainerHeight = function(container, height) - { - updateHeight(height); - }; - - updateHeight(container.offsetHeight); - - var orignShowLightbox = viewer.showLightbox; - - viewer.showLightbox = function(openComments) - { - //Revert back to opening the lightbox in a new tab since we cannot open Confluence dialogs as there is no custom data - if (isServiceDesk) - { - orignShowLightbox.call(this, false); //Open in new tab without edit option - return; - } - - //Create an aspect reflecting current view - var curPageDiagram = viewer.diagrams[viewer.currentPage]; - var curAspect = null; - - if (curPageDiagram != null) - { - var layerIds = [], pageId = curPageDiagram.getAttribute('id'); - - var model = viewer.graph.getModel(); - var childCount = model.getChildCount(model.root); - - // Get visible layers - for (var i = 0; i < childCount; i++) - { - var layer = model.getChildAt(model.root, i); - - if (model.isVisible(layer)) - { - layerIds.push(layer.id); - } - } - - curAspect = pageId + ' ' + layerIds.join(' '); - } - else - { - EditorUi.logEvent('CONF_VIEWER_CURRENT_PAGE_NOT_FOUND: current page = ' + viewer.currentPage + ', diagrams length = ' + viewer.diagrams.length); - } - - AP.dialog.create( - { - header: displayName, - key: 'lightbox', - size: 'fullscreen', - customData: {id: id, name: name, revision: revision, aspect: curAspect, links: links, displayName: displayName, contentId: contentId, custContentId: contentId, openComments: openComments}, - chrome: true - }); - }; - - //Handle Anchor links - var origCustomLinkClicked = viewer.graph.customLinkClicked; - - viewer.graph.customLinkClicked = function(href) - { - if (href.substring(0, 23) == 'data:confluence/anchor,') - { - AC.gotoAnchor(href.substring(23)); - return true; - } - else - { - return origCustomLinkClicked.apply(this, arguments); - } - }; - - //Check embedded diagrams preview image is in sync in the background - if (linkedMode && (diagramUrl == null || diagramUrl.length == 0)) - { - var imgAttVer = null, curAttVer = null; - - function checkImgVer() - { - if (imgAttVer != null && curAttVer != null && curAttVer != imgAttVer) - { - updateImage(); - } - } - - function updateImage() - { - //Update the image - function doSaveImage(imageData) - { - if (imageData != null) - { - AC.saveDiagram(imgPageId, name + (aspectHash? '-' + aspectHash : '') + '.png', AC.b64toBlob(imageData, 'image/png'), - ignoreFn, ignoreFn, false, 'image/png', 'draw.io aspect image' + (curAttVer != null? ' - ' + curAttVer : ''), false, false); - } - }; - - function serverFallback() - { - var req = new mxXmlRequest(EXPORT_URL, 'format=png&base64=1' + - (aspectLayerIds != null? '&extras=' + encodeURIComponent(JSON.stringify({layerIds: aspectLayerIds})) : '') + - (aspectPageId != null? '&pageId=' + aspectPageId : '') + '&xml=' + encodeURIComponent(xml)); - - req.send(function(req) - { - doSaveImage(req.getStatus() >= 200 && req.getStatus() <= 299? req.getText() : null); - }, ignoreFn); - - }; - - if (viewer.editor.isExportToCanvas()) - { - viewer.editor.exportToCanvas(function(canvas) - { - var data = canvas.toDataURL('image/png'); - doSaveImage(data.substring(data.lastIndexOf(',') + 1)); - } - , null, null, null, serverFallback); - } - else - { - serverFallback(); - } - }; - - function ignoreFn(){}; - - function renderAndCache(newXml, timestamp, isPng) - { - if (isPng) - { - newXml = 'data:image/png;base64,' + Editor.base64Encode (newXml); - newXml = AC.extractGraphModelFromPng(newXml); - } - - //render diagram - viewer.setXmlNode(mxUtils.parseXml(newXml).documentElement); - //Apply aspect (layers) again - viewer.showLayers(viewer.graph); - //Update xml (used for server rendering) - xml = newXml; - //Save diagram - AC.saveDiagram(id, name, newXml, - updateImage, function(resp) - { - showError(mxResources.get('confSaveCacheFailed')); - }, false, 'application/vnd.jgraph.mxfile.cached', 'Embedded draw.io diagram' + (timestamp? ' - ' + timestamp : ''), false, false); - }; - - if (csvFileUrl) - { - var cachedCsv, curCsv; - - function checkCsvChange() - { - if (cachedCsv != null && curCsv != null && cachedCsv != curCsv) - { - AC.importCsv(curCsv, function(csvModel, xml) - { - AC.saveDiagram(id, name + '.csv', curCsv, - function() - { - renderAndCache(xml); - }, function() - { - console.log('Cachinng csv file failed durinng saving'); - }, false, 'text/csv', 'Embedded draw.io diagram (CSV)', false, false); - }, - function() - { - console.log('Fetched csv file has invalid format'); - }); - } - }; - - //Fetch csv file and re-generate if changed (Ignore errors and log them only) - AP.request( - { - url: '/download/attachments/' + id + '/' + encodeURIComponent(name + '.csv'), - success: function(csv) - { - cachedCsv = csv; - checkCsvChange(); - }, - error: function() - { - cachedCsv = ""; //Force re-generation - checkCsvChange(); - } - }); - - mxUtils.get(csvFileUrl, function(req) - { - if (req.getStatus() >= 200 && req.getStatus() <= 299) - { - curCsv = req.getText(); - checkCsvChange(); - } - else - { - console.log('Failed to fetch csv file from ' + csvFileUrl + ' Error: ' + req.getStatus()); - } - }, function() - { - console.log('Failed to fetch csv file from ' + csvFileUrl); - }, false, 25000, function() - { - console.log('Failed to fetch csv file (timeout) from ' + csvFileUrl); - }); - } - else if (service != null) - { - if (service == 'GDrive') - { - GAC.getFileInfo(sFileId, function(fileInfo) - { - var isPng = fileInfo.mimeType == 'image/png'; - var timestamp = new Date(fileInfo.modifiedDate).getTime(); - viewer.updateTitle(fileInfo.title); - - AC.getAttachmentInfo(id, name, function(info) - { - var cachedTS = null; - - try - { - cachedTS = parseInt(info.metadata.comment.split(' - ').pop()); - } - catch(e) {} //ignore - - //If cache is old or invalid, fetch the current version - if (timestamp != cachedTS) - { - GAC.doAuthRequestPlain(fileInfo['downloadUrl'], 'GET', null, function(req) - { - renderAndCache(req.responseText, timestamp, isPng); - }, function() - { - showError(mxResources.get('confReadFileErr', [name, 'Google Drive'])); - }, null, isPng); - } - }, function() - { - showError(mxResources.get('confCheckCacheFailed')); - }); - }, function() - { - showError(mxResources.get('confGetInfoFailed', ['Google Drive'])); - }); - } - else if (service == 'OneDrive') - { - AC.getFileInfo(sFileId, odriveId, function(fileInfo) - { - var isPng = fileInfo.file.mimeType == 'image/png'; - var timestamp = new Date(fileInfo.lastModifiedDateTime).getTime(); - viewer.updateTitle(fileInfo.name); - - AC.getAttachmentInfo(id, name, function(info) - { - var cachedTS = null; - - try - { - cachedTS = parseInt(info.metadata.comment.split(' - ').pop()); - } - catch(e) {} //ignore - - //If cache is old or invalid, fetch the current version - if (timestamp != cachedTS) - { - var req = new XMLHttpRequest(); - req.open('GET', fileInfo['@microsoft.graph.downloadUrl']); - - req.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - renderAndCache(req.responseText, timestamp, isPng); - } - else - { - showError(mxResources.get('confReadFileErr', [name, 'OneDrive'])); - } - } - }; - - if (isPng && req.overrideMimeType) - { - req.overrideMimeType('text/plain; charset=x-user-defined'); - } - - req.send(); - } - }, function() - { - showError(mxResources.get('confCheckCacheFailed')); - }); - }, function() - { - showError(mxResources.get('confGetInfoFailed', ['OneDrive'])); - }); - } - } - else - { - //The case of referring to a diagram in another page - - //Get image version from attachment comment - AC.getAttachmentInfo(imgPageId, name + '-' + aspectHash + '.png', function(info) - { - try - { - imgAttVer = parseInt(info.metadata.comment.split(' - ').pop()); - } - catch(e) {} //ignore - - imgAttVer = imgAttVer || attVer; - checkImgVer(); - }, ignoreFn); - - //Get version - AC.getAttachmentInfo(id, name, function(info) - { - curAttVer = info.version.number; - checkImgVer(); - }, ignoreFn); - } - } - - //If there are comments, show the comments icon - function addCommentsIcon() - { - var commentsIcon = document.createElement('img'); - commentsIcon.style.cssText = 'position:absolute;bottom: 5px; right: 5px;opacity: 0.25; cursor: pointer'; - commentsIcon.setAttribute('title', mxResources.get('showComments')); - commentsIcon.src = Editor.commentImage; - commentsIcon.addEventListener('click', function() - { - viewer.showLightbox(true); - }); - container.appendChild(commentsIcon); - }; - - AC.hasUnresolvedComments(id, contentId, name, function(hasUnresolvedComments) - { - if (hasUnresolvedComments) - { - addCommentsIcon(); - } - }, function(){}); //Nothing to do in case of an error - } - } - }, - error: function (err) - { - window.clearTimeout(timeoutThread); - - if (err.status == 404) - { - if (/(^\s|\s$)/.test(name)) - { - showDiagram(id, backupId, name.trim(), revision, links, retryParams, displayName, contentId, spaceKey, openComments, aspect) - } - //Copied pages are reset to revision 1, in addition, copy&paste pages saves diagrams imported from another page - //So, try revision 1 first - else if (revision > 1) - { - showDiagram(id, backupId, name, null, links, {revision: revision}, displayName, contentId, null, null, aspect); - } - else if (backupId != null) - { - //Since attachment wasn't found in this page, it is better to save it to this page - showDiagram(backupId, null, name, revision || retryParams.revision, links, {saveIt: true, pageId: id}, displayName, contentId, null, null, aspect); - } - else //All alternatives failed, so this diagram is not found - { - document.body.style.backgroundImage = 'none'; - showError(mxResources.get('diagNotFound')); - } - } - else if (err.status == 0) - { - document.body.style.backgroundImage = 'none'; - - if (linkedMode) //When the embedded diagram refers to a page that current user has no permissions to view, and error status 0 is returned - { - showError(mxResources.get('confNoPermErr', [id])); - } - else // This can happen when a macro has a pageId (backupId) that the current user doesn't have access to it AND the diagram itself is deleted from this page (e.g, macro is copy/paste) - // , so show a more meaningful error with a dot to differentiate - { - showError(mxResources.get('diagNotFound') + '.'); - } - } - else if (acceptResponse) - { - document.body.style.backgroundImage = 'none'; - showError(mxResources.get('confError', ['HTTP ' + err.status])); - } - } - }); - } - } - else - { - showError(mxResources.get('confError', ['Invalid descriptor'])); - } - }; - - if (customContent) - { - AP.request({ - type: 'GET', - url: '/rest/api/content/' + contentId + '/?expand=body.storage', - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - var info = JSON.parse(decodeURIComponent(resp.body.storage.value)); - var spaceKey = resp._expandable && resp._expandable.space? resp._expandable.space.substr(resp._expandable.space.lastIndexOf('/') + 1) : ""; - - AP.dialog.create( - { - header: resp.title, - key: 'lightbox', - size: 'fullscreen', - //custom content can load old versions which will be overridden by version check - customData: {id: info.pageId, name: info.diagramName, revision: info.version, aspect: info.aspect, links: links, - displayName: resp.title, spaceKey: spaceKey, retryParams: {dontCheckVer: true}, contentId: contentId, custContentId: contentId, inComment: info.inComment}, - chrome: true - }).on("close", function(flags) - { - if (flags && flags.noBack) - { - if (flags.openEditorId) - { - //setTimeout is needed such that the current dialog closes completely - //without it, the on close event is not called! - setTimeout(function() - { - AP.dialog.create( - { - key: 'customContentEditor', - customData: {contentId: flags.openEditorId, custContentId: flags.openEditorId}, - chrome: false, - width: "100%", - height: "100%", - }).on("close", function(flags) - { - if (flags && flags.noBack) - { - if (!flags.noBackOnClose) - { - //Go back after user (closes/clicks the link in) the flag - AP.events.on('flag.close', function(){ - AP.history.go(-1); - }); - AP.events.on('flag.action', function(){ - AP.history.go(-1); - }); - } - } - else - { - AP.history.go(-1); - } - }); - }, 10); - } - } - else - { - AP.history.go(-1); - } - }); - }, - error: function (resp) - { - AC.showNotification({ - title: mxResources.get('error'), - body: mxResources.get('diagNotFound'), - type: 'error' - }); - - //give the user some time to read the error! - setTimeout(function() - { - AP.history.go(-1); - }, 500); - } - }); - } - else if (lightbox) - { - // Gets the paramters from the customData object in lightbox mode - // LATER: Add XML to custom data (does not seem to work) - AP.dialog.getCustomData(function (customData) { - inComment = customData.inComment; - showDiagram(customData.id, customData.id, customData.name, customData.revision, - customData.links, customData.retryParams, customData.displayName, customData.contentId || customData.custContentId, - customData.spaceKey, customData.openComments, customData.aspect); - }); - } - else - { - //TODO We cache diagramUrl file now, so handle its change detection and caching if the file doesn't exists - if (diagramUrl) - { - showExtDiagram(diagramName, diagramUrl); - } - else - { - showDiagram(candidateId, (owningPageId != null && owningPageId.length > 0) ? owningPageId : ceoId, diagramName, revision, links, null, displayName, contentId, null, null, aspect); - } - } - }; - }; - }; - - // Prefetches asynchronous requests so that below code runs synchronous - // Loading the correct bundle (one file) via the fallback system in mxResources. The stylesheet - // is compiled into JS in the build process and is only needed for local development. - var bundleLoaded = false; - var scriptLoaded = false; - var fontsLoaded = false; - var validSize = document.documentElement.offsetWidth > 0; - - function mainBarrier() - { - if (validSize && bundleLoaded && scriptLoaded && fontsLoaded) - { - main(); - } - }; - - // Disables delayed rendering since the container is created on the fly - GraphViewer.prototype.checkVisibleState = false; - - // Workaround for collapsed panel is to delay main until size is not 0 - if (!validSize) - { - var listener = function() - { - if (document.documentElement.offsetWidth > 0) - { - window.removeEventListener('resize', listener); - validSize = true; - mainBarrier(); - } - }; - - window.addEventListener('resize', listener); - } - - script.onload = function() - { - AP.user.getLocale(function(lang) - { - // Overrides browser language with Confluence user language - if (lang != null) - { - var dash = lang.indexOf('_'); - - if (dash >= 0) - { - mxLanguage = lang.substring(0, dash); - } - } - - mxResources.loadDefaultBundle = false; - var bundle = mxResources.getDefaultBundle(RESOURCE_BASE, mxLanguage) || - mxResources.getSpecialBundle(RESOURCE_BASE, mxLanguage); - - mxUtils.getAll([bundle], function(xhr) - { - // Adds bundle text to resources - mxResources.parse(xhr[0].getText()); - bundleLoaded = true; - mainBarrier(); - }); - }); - - // Workaround for Google Chrome triggering - // no resize event if height is set to 0 - if (mxClient.IS_GC && !validSize) - { - AP.resize('100%', 1); - } - - // Checks configuration and loads fontCss - // While this is executed in parallel it still adds unnecessary - // calls since it is only needed if global fontCss is used - AP.request({ - type: 'GET', - url: '/rest/api/content/search?cql=type%3Dpage%20and%20space%3DDRAWIOCONFIG%20and%20title%3DConfiguration', //type=page and space=DRAWIOCONFIG and title=Configuration. Search doesn't return 404 if not found - contentType: 'application/json;charset=UTF-8', - success: function (resp) - { - resp = JSON.parse(resp); - - if (resp.size == 1) - { - var configPageId = resp.results[0].id; - - // Loads the configuration file - AP.request({ - type: 'GET', - url: '/download/attachments/' + configPageId + '/configuration.json', - contentType: 'application/json;charset=UTF-8', - success: function (fileContent) - { - try - { - var config = JSON.parse(fileContent); - Editor.configureFontCss(config.fontCss); - fontsLoaded = true; - mainBarrier(); - } - catch (e) - { - console.log('Configuration error', e); - fontsLoaded = true; - mainBarrier(); - } - }, - error: function() - { - fontsLoaded = true; - mainBarrier(); - } - }); - } - else - { - fontsLoaded = true; - mainBarrier(); - } - }, error: function() - { - fontsLoaded = true; - mainBarrier(); - }}); - - scriptLoaded = true; - mainBarrier(); - }; - - script.src = 'https://connect-cdn.atl-paas.net/all.js'; - script.setAttribute('data-options', 'resize:false;margin:false'); - document.getElementsByTagName('head')[0].appendChild(script); -})(); \ No newline at end of file diff --git a/src/main/webapp/connect/confluence/viewer2.html b/src/main/webapp/connect/confluence/viewer2.html deleted file mode 100644 index 0abc577f..00000000 --- a/src/main/webapp/connect/confluence/viewer2.html +++ /dev/null @@ -1,214 +0,0 @@ - - - - -Draw.io Viewer - - - - - - - - diff --git a/src/main/webapp/connect/gdrive_common/editor.js b/src/main/webapp/connect/gdrive_common/editor.js deleted file mode 100644 index 564a67dd..00000000 --- a/src/main/webapp/connect/gdrive_common/editor.js +++ /dev/null @@ -1,547 +0,0 @@ -function GDriveEditor(onSubmit, getFileInfoFn, idSuffix, notStandalone, drawioOnly, genImage) -{ - idSuffix = idSuffix || ''; - var noThumbImg = '/images/google-drive-logo.svg'; - - var opts = - { - lines: 12, // The number of lines to draw - length: 8, // The length of each line - width: 3, // The line thickness - radius: 5, // The radius of the inner circle - rotate: 0, // The rotation offset - color: '#000', // #rgb or #rrggbb - speed: 1, // Rounds per second - trail: 60, // Afterglow percentage - shadow: false, // Whether to render a shadow - hwaccel: false, // Whether to use hardware acceleration - className: 'spinner', // The CSS class to assign to the spinner - zIndex: 2e9 // The z-index (defaults to 2000000000) - }; - - var spinner = new Spinner(opts); - window.spinner = spinner; //TODO Remove this, it is used in the GAC - this.spinner = spinner; - spinner.spin(GAC.$('#spinner-container' + idSuffix)); - - var head = document.getElementsByTagName('head')[0]; - - // Handles timeouts - var acceptResponse = true; - - var timeoutHandler = function() - { - acceptResponse = false; - spinner.stop(); - alert('The connection has timed out'); - }; - - var timeoutThread = window.setTimeout(timeoutHandler, 25000); - - var selectedFile = null, selFileContent = null; - var curViewer = null; - var status = document.getElementById('status'); - - function debug(msg) - { - if (status != null) - { - mxUtils.write(status, msg); - mxUtils.br(status); - } - }; - - function showError(elem, errMsg) - { - elem.innerHTML = ' ' + - GAC.htmlEntities(errMsg); - }; - - function setPreview(file) - { - if (typeof AP != 'undefined') - { - AP.dialog.getButton('submit').enable(); - var altSubmitBtn = AP.dialog.getButton('altSubmitBtn'); - - if (altSubmitBtn) altSubmitBtn.enable(); - } - - var thumbImg = GAC.$('#thumbImg' + idSuffix); - - thumbImg.onerror = function() - { - this.onerror = null; - this.src = noThumbImg; - }; - - thumbImg.src = file.thumbnailLink; - - var prevDiv = GAC.$('#preview' + idSuffix); - prevDiv.innerHTML = ''; - var iframe = document.createElement('iframe'); - iframe.src = file.embedLink; - iframe.setAttribute('frameborder', '0'); - iframe.width = '100%'; - iframe.height = '100%'; - prevDiv.appendChild(iframe); - - var autoSizeCheck = GAC.$('#autoSize' + idSuffix); - autoSizeCheck.checked = false; - autoSizeCheck.setAttribute('disabled', 'disabled'); - autoSizeChanged(false); - curViewer = null; - }; - - function prevDrawioFile(doc, prevDiv, file, aspect) - { - spinner.stop(); - - var thumbImg = GAC.$('#thumbImg' + idSuffix); - - thumbImg.onerror = function() - { - this.onerror = null; - this.src = noThumbImg; - }; - - thumbImg.src = file.thumbnailLink; - - var container = document.createElement('div'); - // NOTE: Height must be specified with default value "auto" to force automatic fit in viewer - container.style.cssText = 'position:absolute;width:auto;left:0px;right:0px;height:auto;bottom:0px;top:0px;border:1px solid transparent;'; - prevDiv.appendChild(container); - - var pageId, layerIds; - - if (aspect != null) - { - var aspectArray = aspect.split(' '); - - if (aspectArray.length > 1) - { - pageId = aspectArray[0]; - layerIds = aspectArray.slice(1); - } - } - - Graph.prototype.shadowId = 'googleDriveDropShadow'; - var viewer = new GraphViewer(container, doc.documentElement, - {highlight: '#3572b0', border: 8, 'auto-fit': true, - resize: false, nav: true, lightbox: false, title: file.title, - 'toolbar-nohide': true, 'toolbar-position': 'top', toolbar: 'pages layers', - pageId: pageId, layerIds: layerIds}); - - viewer.graph.addListener('size', function() - { - var root = this.view.getDrawPane().ownerSVGElement; - - if (root != null) - { - root.style.minHeight = ''; - } - }); - - curViewer = viewer; - - if (typeof AP != 'undefined') - { - AP.dialog.getButton('submit').enable(); - var altSubmitBtn = AP.dialog.getButton('altSubmitBtn'); - - if (altSubmitBtn) altSubmitBtn.enable(); - } - }; - - // Waits for both APIs to load in parallel - function main() - { - if ((notStandalone || typeof window.AP !== 'undefined') && typeof window.google != 'undefined') - { - try - { - window.clearTimeout(timeoutThread); - - //Google Drive Auth before proceeding - GAC.confirmGDAuth(mainAuth, function() - { - alert('Error authenticating to Google Drive!'); //TODO better error handling - }); - - if (status != null) - { - status.style.display = 'none'; - } - } - catch (e) - { - debug('Error in main: ' + e.message); - } - } - }; - - function genericOnSubmit() - { - var hasError = false; - //this cannot happen as the submit button is disabled until a file is selected - if (selectedFile == null) - { - GAC.$('#filenameError' + idSuffix).innerHTML = "Please select a file"; - hasError = true; - } - - var width = parseInt(GAC.$('#width' + idSuffix).value); - var height = parseInt(GAC.$('#height' + idSuffix).value); - var autoSize = GAC.$('#autoSize' + idSuffix).checked; - - if (!autoSize && (isNaN(width) || width <= 0)) - { - GAC.$('#widthError' + idSuffix).innerHTML = "Width must be greater than zero"; - hasError = true; - } - - if (!autoSize && (isNaN(height) || height <= 0)) - { - GAC.$('#heightError' + idSuffix).innerHTML = "Height must be greater than zero"; - hasError = true; - } - - if (hasError) - { - return; - } - - if (curViewer != null) - { - var layerIds = []; - - var model = curViewer.graph.getModel(); - var childCount = model.getChildCount(model.root); - - // Get visible layers - for (var i = 0; i < childCount; i++) - { - var layer = model.getChildAt(model.root, i); - - if (model.isVisible(layer)) - { - layerIds.push(layer.id); - } - } - - selectedFile.aspect = curViewer.diagrams[curViewer.currentPage].getAttribute('id') + ' ' + layerIds.join(' '); - - if (autoSize) - { - var bounds = curViewer.graph.view.graphBounds; - width = Math.round(bounds.width) || null; - height = Math.round(bounds.height) || null; - } - } - - spinner.spin(GAC.$('#preview' + idSuffix)); - - var image = null; - - function finalize() - { - onSubmit(selectedFile, width, height, autoSize, selFileContent, image); - }; - - if (genImage && curViewer.editor.isExportToCanvas()) - { - curViewer.editor.exportToCanvas(function(canvas) - { - var data = canvas.toDataURL('image/png'); - image = data.substring(data.lastIndexOf(',') + 1); - finalize(); - } - , null, null, null, finalize); - } - else - { - finalize() - } - } - - this.doSubmit = genericOnSubmit; - - function mainAuth() - { - if (acceptResponse) - { - spinner.stop(); - - var chooseLink = document.getElementById('chooseLink'); - - if (chooseLink != null) - { - chooseLink.style.display = ''; - } - - GAC.$('#filePicker' + idSuffix).removeAttribute('disabled'); - - GAC.$('#filePicker' + idSuffix).addEventListener('click', function(evt) - { - evt.preventDefault(); - - GAC.pickFile(function(file) - { - function handleNonDrawFile() //If the file is not a draw.io diagram - { - if (drawioOnly) - { - selectedFile = null; - spinner.stop(); - AC.$('#filenameError' + idSuffix).innerHTML = 'Not a draw.io diagram file'; - } - else - { - setPreview(file); - } - - drawioCheck.checked = false; - }; - - function setAutosize() - { - drawioCheck.checked = true; - drawioCheck.setAttribute('disabled', 'disabled'); - var autoSizeCheck = GAC.$('#autoSize' + idSuffix); - autoSizeCheck.checked = true; - autoSizeCheck.removeAttribute('disabled'); - autoSizeChanged(true); - }; - - selectedFile = file; - GAC.$('#filenameError' + idSuffix).innerHTML = ""; - GAC.$('#filename' + idSuffix).value = file.title; - var mimeType = file.mimeType; - var drawioCheck = GAC.$('#useDrawio' + idSuffix); - drawioCheck.removeAttribute('disabled'); - var useDrawio = drawioOnly? false : drawioCheck.checked; - var prevDiv = GAC.$('#preview' + idSuffix); - prevDiv.innerHTML = ''; - spinner.spin(prevDiv); - - if (!drawioOnly && typeof convertVSDXtoMX != 'undefined' && /\.v(dx|sdx?)$/i.test(file.title)) //In Google Drive, all vsdx files are previewed with draw.io - { - GAC.getBinaryFile(file, function(blobFile) - { - convertVSDXtoMX(blobFile, file.title, function(xml) - { - selectedFile.isDrawio = true; - selFileContent = xml; - prevDrawioFile(mxUtils.parseXml(xml), prevDiv, file); - setAutosize(); - }, handleNonDrawFile); - }, handleNonDrawFile); - } - //Handle draw.io potential files (html & xml) - else if (useDrawio || mimeType == 'text/html' || mimeType == 'text/xml' || mimeType == 'application/xml' - || mimeType == 'image/png' || mimeType == 'application/vnd.jgraph.mxfile' - || /\.svg$/i.test(file.title) || /\.html$/i.test(file.title) || /\.xml$/i.test(file.title) - || /\.png$/i.test(file.title) || /\.drawio$/i.test(file.title)) - { - GAC.checkDrawioFile(file, function(doc, cnt) - { - selFileContent = cnt; - prevDrawioFile(doc, prevDiv, file); - setAutosize(); - }, handleNonDrawFile); - } - else - { - handleNonDrawFile(); - } - }, true); //Allow folder selection. If it's not needed in Jira use !notStandalone - }); - - function removeErrMsg() - { - GAC.$('#' + this.id + 'Error' + idSuffix).innerHTML = ""; - }; - - GAC.$('#width' + idSuffix).addEventListener('change', removeErrMsg); - GAC.$('#height' + idSuffix).addEventListener('change', removeErrMsg); - - if (getFileInfoFn) - { - getFileInfoFn(function(fileInfo) - { - var altSubmitBtn = AP.dialog.createButton({ - text: fileInfo? 'Save' : 'Insert', - identifier: 'altSubmitBtn' - }); - altSubmitBtn.bind(genericOnSubmit); - altSubmitBtn.disable(); - - if (fileInfo && fileInfo.fileId) - { - var autoSize = fileInfo.autoSize == '1'; - GAC.$('#width' + idSuffix).value = fileInfo.width; - GAC.$('#height' + idSuffix).value = fileInfo.height; - GAC.$('#filename' + idSuffix).value = fileInfo.filename; - fileInfo.isDrawio = fileInfo.isDrawio == '1'; - GAC.$('#useDrawio' + idSuffix).checked = fileInfo.isDrawio; - GAC.$('#autoSize' + idSuffix).checked = autoSize; - autoSizeChanged(autoSize); - - var prevDiv = GAC.$('#preview' + idSuffix); - prevDiv.innerHTML = ''; - spinner.spin(prevDiv); - - GAC.getFileInfo(fileInfo.fileId, function(file) - { - function filePrevErr(err) - { - showError(prevDiv, 'Cannot load file preview.'); - }; - - selectedFile = file; - - if (typeof convertVSDXtoMX != 'undefined' && /\.v(dx|sdx?)$/i.test(fileInfo.filename)) //In Google Drive, all vsdx files are previewed with draw.io - { - GAC.getBinaryFile(file, function(blobFile) - { - convertVSDXtoMX(blobFile, fileInfo.filename, function(xml) - { - selFileContent = xml; - prevDrawioFile(mxUtils.parseXml(xml), prevDiv, file, fileInfo.aspect); - }, filePrevErr); - }, filePrevErr); - } - else if (fileInfo.isDrawio) - { - GAC.getDrawioFileDoc(file, function(doc, cnt) - { - selFileContent = cnt; - prevDrawioFile(doc, prevDiv, file, fileInfo.aspect); - }, filePrevErr); - } - else - { - setPreview(file); - } - }, - function(err) - { - if (err && (err.status == 403 || err.status == 400)) //400 is returned when a business account file is accessed via a personal account - { - showError(prevDiv, 'Error: Access Denied. You do not have permission to access this file "'+ fileInfo.filename +'".'); - } - else - { - showError(prevDiv, 'Cannot load file preview.'); - } - }); - } - }); - } - } - }; - - this.loadDrawioFile = function(fileInfo) - { - GAC.$('#filename' + idSuffix).value = fileInfo.diagramDisplayName; - GAC.$('#autoSize' + idSuffix).checked = true; - var prevDiv = GAC.$('#preview' + idSuffix); - prevDiv.innerHTML = ''; - spinner.spin(prevDiv); - - GAC.getFileInfo(fileInfo.sFileId, function(file) - { - selectedFile = file; - GAC.$('#filename' + idSuffix).value = file.title; - - GAC.getDrawioFileDoc(file, function(doc, cnt) - { - selFileContent = cnt; - prevDrawioFile(doc, prevDiv, file, fileInfo.aspect); - }, function() - { - showError(prevDiv, 'Cannot read "' + file.title + '" file from Google Drive.'); - }); - }, function() - { - showError(prevDiv, 'Fetching file info from Google Drive failed.'); - }); - }; - - function autoSizeChanged(isChecked) - { - if(isChecked) - { - GAC.$('#width' + idSuffix).setAttribute('disabled', 'disabled'); - GAC.$('#height' + idSuffix).setAttribute('disabled', 'disabled'); - } - else - { - GAC.$('#width' + idSuffix).removeAttribute('disabled'); - GAC.$('#height' + idSuffix).removeAttribute('disabled'); - } - }; - - GAC.$('#autoSize' + idSuffix).addEventListener('change', function(evt) - { - autoSizeChanged(this.checked); - }); - - var signOut = GAC.$('#signout' + idSuffix); - - if (signOut) - { - signOut.addEventListener('click', function(evt) - { - evt.preventDefault(); - GAC.setPersistentAuth(null); - main(); //To show auth button again - }); - } - - function loadAtlassianApi() - { - var script = document.createElement("script"); - - script.onload = function() - { - AP.dialog.disableCloseOnSubmit(); - - //TODO when conf bug of submit is fixed, re-enable this and remove the button above - if (getFileInfoFn) - { - AP.dialog.getButton('submit').hide(); - } - - AP.events.on('dialog.submit', genericOnSubmit); - AP.dialog.getButton('submit').disable(); - debug('Atlassian API loaded...'); - main(); - }; - - script.src = 'https://connect-cdn.atl-paas.net/all.js'; - script.setAttribute('data-options', 'resize:false;margin:false'); - head.appendChild(script); - }; - - function loadGoogleApi() - { - window.onGApiLoad = function() - { - debug('Google API loaded...'); - gapi.load('picker', main); - }; - var script = document.createElement("script"); - script.src = "https://apis.google.com/js/api.js?onload=onGApiLoad"; - head.appendChild(script); - }; - - // Loads APIs in parallel and waits in main - if (!notStandalone) - { - loadAtlassianApi(); - } - - loadGoogleApi(); -}; - diff --git a/src/main/webapp/connect/gdrive_common/gac.js b/src/main/webapp/connect/gdrive_common/gac.js deleted file mode 100644 index 175b9290..00000000 --- a/src/main/webapp/connect/gdrive_common/gac.js +++ /dev/null @@ -1,564 +0,0 @@ -//TODO Some functions are the same as OneDrive AC except for minor changes [sometimes only the URLs and constants are different] -// (note also that google doesn't return the refresh token with every request + in office add-in we save the local storage differently) -var GAC = {}; - -GAC.host = window.location.host; -GAC.clientId = '850530949725.apps.googleusercontent.com'; -GAC.redirectUri = window.location.protocol + '//' + GAC.host + '/google'; -GAC.scopes = ['https://www.googleapis.com/auth/drive.readonly', - 'https://www.googleapis.com/auth/userinfo.profile']; -GAC.isLocalStorage = typeof(Storage) != 'undefined'; -GAC.authLSKeyName = 'oDrawGDrive'; //Should be the same name as in draw.io -GAC.GDriveBaseUrl = 'https://www.googleapis.com/drive/v2'; -GAC.reqQueue = []; -GAC.authOnProgress = false; - -if (typeof CAC === 'undefined') -{ - throw 'CAC object not found, please include file new_common/cac.js'; -} -else -{ - CAC.applyCAC(GAC); -} - -GAC.authGDrive = function(success, error, direct) -{ - GAC.reqQueue.push({success: success, error: error}); - - if (GAC.authOnProgress) - { - return; - } - - GAC.authOnProgress = true; - - if (window.onGoogleDriveCallback == null) - { - var authStep2 = function(state) - { - var acceptAuthResponse = true; - - var url = 'https://accounts.google.com/o/oauth2/v2/auth?client_id=' + GAC.clientId + - '&redirect_uri=' + encodeURIComponent(GAC.redirectUri) + - '&response_type=code&access_type=offline&prompt=consent%20select_account&include_granted_scopes=true' + - '&scope=' + encodeURIComponent(GAC.scopes.join(' ')) + - '&state=' + encodeURIComponent('cId=' + GAC.clientId + '&domain=' + GAC.host + '&ver=2&token=' + state); //To identify which app/domain is used - - var width = 525, - height = 525, - screenX = window.screenX, - screenY = window.screenY, - outerWidth = window.outerWidth, - outerHeight = window.outerHeight; - - var left = screenX + Math.max(outerWidth - width, 0) / 2; - var top = screenY + Math.max(outerHeight - height, 0) / 2; - - var features = ['width=' + width, 'height=' + height, - 'top=' + top, 'left=' + left, - 'status=no', 'resizable=yes', - 'toolbar=no', 'menubar=no', - 'scrollbars=yes']; - var popup = window.open(url, 'gdauth', features.join(',')); - - if (popup != null) - { - window.onGoogleDriveCallback = function(authInfo) - { - try - { - if (acceptAuthResponse) - { - window.onGoogleDriveCallback = null; - acceptAuthResponse = false; - - try - { - if (authInfo == null) - { - error({message: 'Access Denied', retry: auth}); - } - else - { - GAC.token = authInfo.access_token; - authInfo.expires = Date.now() + parseInt(authInfo.expires_in) * 1000; - authInfo.remember = true; - authInfo.token = authInfo.access_token; - authInfo.refreshToken = authInfo.refresh_token; - GAC.setPersistentAuth(authInfo); - - for (var i = 0; i < GAC.reqQueue.length; i++) - { - GAC.reqQueue[i].success(); - } - - GAC.reqQueue = []; - GAC.authOnProgress = false; - } - } - catch (e) - { - error(e); - } - finally - { - popup.close(); - } - } - else - { - popup.close(); - } - } - finally - { - authDialog.parentNode.removeChild(authDialog); - } - }; - - popup.focus(); - } - else - { - alert('Error: Google Authentication window blocked'); - } - }; - - var auth = function() - { - var req = new XMLHttpRequest(); - req.open('GET', GAC.redirectUri + '?getState=1'); - - req.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - authStep2(req.responseText); - } - else - { - error(this); - } - } - }; - - req.send(); - }; - - if (direct) - { - auth(); - } - else - { - if (window.spinner != null) - { - spinner.stop(); - } - - var authDialog = document.createElement('div'); - var btn = document.createElement('button'); - btn.innerHTML = 'Authorize draw.io to access Google Drive'; - btn.className = 'aui-button aui-button-primary'; - authDialog.appendChild(btn); - - function adjustAuthBtn() - { - var w = window.innerWidth, h = window.innerHeight; - authDialog.style.cssText = 'position: absolute; top: 0px; left: 0px; width: '+ w +'px; height: '+ h +'px; background: #fff;opacity: 0.85;z-index: 9999;'; - btn.style.cssText = 'position: absolute; width: 320px; height: 50px; top: '+ (h/2 - 25) +'px; left: '+ (w/2 - 160) +'px;opacity: 1;'; - } - - btn.addEventListener('click', function(evt) - { - auth(); - //Remove the event handler since the user already used the button - window.removeEventListener("resize", adjustAuthBtn); - }); - - window.addEventListener('resize', adjustAuthBtn); - adjustAuthBtn(); - document.body.appendChild(authDialog); - } - } - else - { - error({message: 'Busy'}); - } -}; - -//JSON request with auth -GAC.doAuthRequest = function(url, method, params, success, error) -{ - GAC.doAuthRequestPlain(GAC.GDriveBaseUrl + url, method, params, function(req) - { - success(JSON.parse(req.responseText)); - }, error); -}; - -//JSON request with auth -GAC.doAuthRequestPlain = function(url, method, params, success, error, contentType, isBinary, retryCount, isBlob, failIfNotAuth) -{ - retryCount = retryCount || 0; - - if (retryCount > 4) - { - //Since we tried multiple times, the token itself maybe corrupted - GAC.setPersistentAuth(null); - error(); - return; - } - - if (GAC.token == null) - { - var token = GAC.getPersistentToken(); - - if (token == null) - { - if (failIfNotAuth) - { - error({authNeeded: true}); - } - else - { - GAC.authGDrive(function() - { - //Retry request after authentication - GAC.doAuthRequestPlain(url, method, params, success, error, contentType, isBinary, ++retryCount, isBlob); - }, error); - } - return; - } - else - { - GAC.token = token; - } - } - - var req = new XMLHttpRequest(); - req.open(method, url); - req.setRequestHeader('Authorization', 'Bearer ' + GAC.token); - req.setRequestHeader('Content-Type', contentType || 'application/json;charset=UTF-8'); - - req.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - success(req); - } - else if (this.status == 401) // (Unauthorized) [e.g, invalid token] - { - //Try refresh token before asking for new authentication - var authInfo = GAC.getPersistentAuth(); - - if (authInfo != null && authInfo.refreshToken != null) - { - function doRefreshToken(state) - { - var req2 = new XMLHttpRequest(); - req2.open('GET', GAC.redirectUri + '?refresh_token=' + authInfo.refreshToken + - '&state=' + encodeURIComponent('cId=' + GAC.clientId + '&domain=' + GAC.host + '&ver=2&token=' + state)); //To identify which app/domain is used - - req2.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - var newAuthInfo = JSON.parse(req2.responseText); - GAC.token = newAuthInfo.access_token; - //Update existing authInfo and save it - authInfo.access_token = newAuthInfo.access_token; - authInfo.refresh_token = newAuthInfo.refresh_token; - authInfo.expires = Date.now() + newAuthInfo.expires_in * 1000; - authInfo.token = authInfo.access_token; - authInfo.refreshToken = authInfo.refresh_token; - GAC.setPersistentAuth(authInfo); - //Retry request with refreshed token - GAC.doAuthRequestPlain(url, method, params, success, error, contentType, isBinary, ++retryCount, isBlob); - } - else // (Unauthorized) [e.g, invalid refresh token] (sometimes, the server returns errors other than 401 (e.g. 500)) - { - if (failIfNotAuth) - { - error({authNeeded: true}); - } - else - { - GAC.authGDrive(function() - { - //Retry request after authentication - GAC.doAuthRequestPlain(url, method, params, success, error, contentType, isBinary, ++retryCount, isBlob); - }, error); - } - } - } - } - - req2.send(); - }; - - var req2 = new XMLHttpRequest(); - req2.open('GET', GAC.redirectUri + '?getState=1'); - - req2.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - doRefreshToken(req2.responseText); - } - else - { - error(this); - } - } - }; - - req2.send(); - } - else - { - if (failIfNotAuth) - { - error({authNeeded: true}); - } - else - { - GAC.authGDrive(function() - { - //Retry request after authentication - GAC.doAuthRequestPlain(url, method, params, success, error, contentType, isBinary, ++retryCount, isBlob); - }, error); - } - } - } - else - { - error(this); - } - } - }; - - if (isBinary && req.overrideMimeType) - { - req.overrideMimeType('text/plain; charset=x-user-defined'); - } - - if (isBlob) - { - req.responseType = 'blob'; - } - - req.send(params != null? JSON.stringify(params) : null); -}; - -GAC.showError = function(err) -{ - alert('Error: ' + e.message); -}; - -GAC.getFileInfo = function(id, success, error) -{ - GAC.doAuthRequest('/files/' + id + - '?fields=id,title,mimeType,modifiedDate,downloadUrl,thumbnailLink,webViewLink,embedLink,fileSize,lastModifyingUser,owners' + - '&supportsAllDrives=true', - 'GET', null, function(obj) - { - success(obj); - }, error); -}; - -GAC.setOrigin = function(origin) -{ - GAC.origin = origin; -}; - -GAC.getOrigin = function() -{ - return GAC.origin || GAC.getUrlParam('xdm_e', true) || (window.location.protocol + '//' + window.location.host); -}; - -GAC.pickFile = function(fn, acceptFolders) -{ - acceptFolders = acceptFolders || false; - - var view1 = new google.picker.DocsView(google.picker.ViewId.FOLDERS) - .setParent('root') - .setIncludeFolders(true) - .setSelectFolderEnabled(acceptFolders) - .setMimeTypes('*/*'); - - var view2 = new google.picker.DocsView() - .setIncludeFolders(true) - .setSelectFolderEnabled(acceptFolders) - - var view3 = new google.picker.DocsView() - .setEnableDrives(true) - .setIncludeFolders(true) - .setSelectFolderEnabled(acceptFolders) - - var dim = GAC.getDocDim(); - - var builder = new google.picker.PickerBuilder() - .addView(view1) - .addView(view2) - .addView(view3) - .setOAuthToken(GAC.token) - .enableFeature(google.picker.Feature.SUPPORT_DRIVES) - .setCallback(function(data) - { - if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) - { - picker.setVisible(false); - var doc = data[google.picker.Response.DOCUMENTS][0]; - - GAC.getFileInfo(doc.id, function(fullDoc) - { - fn(fullDoc); - }, function() - { - fn(doc); - }); - } - }) - .setOrigin(GAC.getOrigin()) - .setSize(dim.w - 10, dim.h - 10); - - picker = builder.build(); - picker.setVisible(true); -}; - -GAC.confirmGDAuth = function(success, error, failIfNotAuth) -{ - GAC.doAuthRequestPlain('https://www.googleapis.com/oauth2/v2/userinfo', - 'GET', null, success, error, null, null, null, null, failIfNotAuth); -}; - -//This function depends on having GraphViewer loaded -GAC.extractGraphModelFromPng = function(pngData) -{ - return Editor.extractGraphModelFromPng(pngData); -}; - -GAC.getBinaryFile = function(file, success, error) -{ - if (file['downloadUrl'] == null) - { - GAC.getFileInfo(file.id, function(completeFile) - { - GAC.getBinaryFile(completeFile, success, error); - }, error); - - return; - } - - GAC.doAuthRequestPlain(file['downloadUrl'], 'GET', null, function(req) - { - success(req.response); - }, error, null, null, null, true); -}; - -//This function depends on having GraphViewer loaded -GAC.getDrawioFileDoc = function(file, success, error, doCheck) -{ - if (file['downloadUrl'] == null) - { - GAC.getFileInfo(file.id, function(completeFile) - { - GAC.getDrawioFileDoc(completeFile, success, error, doCheck); - }, error); - - return; - } - - var isPng = file.mimeType == 'image/png'; - - GAC.doAuthRequestPlain(file['downloadUrl'], 'GET', null, function(req) - { - try - { - var cnt = req.responseText; - - if (isPng) - { - cnt = 'data:image/png;base64,' + Editor.base64Encode (cnt); - cnt = GAC.extractGraphModelFromPng(cnt); - } - - var doc = mxUtils.parseXml(cnt); - - if (!doCheck || new Editor().extractGraphModel(doc.documentElement) != null) - { - file.isDrawio = true; - success(doc, cnt, true); - return; - } - } - catch(e) {} //on error and if the doc is null, the following line will call the error - - error(); - - }, error, null, isPng); -}; - -//This function depends on having GraphViewer loaded -GAC.checkDrawioFile = function(file, success, error) -{ - GAC.getDrawioFileDoc(file, success, error, true); -}; - -GAC.setPersistentAuth = function(authInfo) -{ - if (GAC.isLocalStorage) - { - if (authInfo != null) - { - //Google Auth doesn't return the refresh_token with every request, so we need to copy it when auth info is saved - if (authInfo.refreshToken == null) - { - var curInfo = GAC.getPersistentAuth(); - - if (curInfo != null) authInfo.refreshToken = curInfo.refreshToken; - } - - localStorage.setItem('.' + GAC.authLSKeyName, JSON.stringify(authInfo)); - } - else - { - GAC.token = null; - localStorage.removeItem('.' + GAC.authLSKeyName); - } - } -}; - -GAC.getPersistentToken = function() -{ - var authInfo = GAC.getPersistentAuth(); - var token = null; - - if (authInfo != null) - { - token = authInfo.access_token; - } - - return token; -}; - -GAC.getPersistentAuth = function() -{ - var authInfo = null; - - if (GAC.isLocalStorage) - { - authInfo = JSON.parse(localStorage.getItem('.' + GAC.authLSKeyName)); - } - - return authInfo; -}; diff --git a/src/main/webapp/connect/gdriveconnector/ac.js b/src/main/webapp/connect/gdriveconnector/ac.js deleted file mode 100644 index ab77b943..00000000 --- a/src/main/webapp/connect/gdriveconnector/ac.js +++ /dev/null @@ -1,44 +0,0 @@ -var AC = {}; - -AC.getUrlParam = function(param, escape, url){ - try{ - var url = url || window.location.search; - var regex = new RegExp(param + '=([^&]+)'), - data = regex.exec(url)[1]; - // decode URI with plus sign fix. - return (escape) ? window.decodeURIComponent(data.replace(/\+/g, '%20')) : data; - } catch (e){ - return undefined; - } -}; - -AC.getMetaTag = function(name) { - return document.getElementsByTagName('meta')[name].getAttribute('content'); -}; - -AC.getMacroData = function(fn) { - AP.confluence.getMacroData(fn); -} - -AC.getBaseUrl = function() -{ - var baseUrl = AC.getUrlParam('xdm_e', true) + AC.getUrlParam('cp', true); - //Ensure baseUrl belongs to attlasian (*.jira.com and *.atlassian.net) - //Since we add cp to xdm_e, we had to ensure that there is a slash after the domain. Since if xdm_e is ok, cp can corrupt is such as cp = '.fakedomain.com' such that baseUrl is atlassian.net.fakedomain.com - if (/^https:\/\/([^\.])+\.jira\.com\//.test(baseUrl + '/') || /^https:\/\/([^\.])+\.atlassian\.net\//.test(baseUrl + '/')) - { - return baseUrl; - } - throw 'Invalid baseUrl!'; -}; - -AC.getSiteUrl = function() -{ - var siteUrl = AC.getUrlParam('xdm_e', true); - //Ensure siteUrl belongs to attlasian (*.jira.com and *.atlassian.net) - if (/^https:\/\/([^\.])+\.jira\.com$/.test(siteUrl) || /^https:\/\/([^\.])+\.atlassian\.net$/.test(siteUrl)) - { - return siteUrl; - } - throw 'Invalid siteUrl!'; -}; diff --git a/src/main/webapp/connect/gdriveconnector/att-macroEditor.html b/src/main/webapp/connect/gdriveconnector/att-macroEditor.html deleted file mode 100644 index 3313e96d..00000000 --- a/src/main/webapp/connect/gdriveconnector/att-macroEditor.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - -Diagram Upload Editor - - - - - - - - - - -
-
-
-
- - - - -
-
Diagram file name
-
-
-
- -
Width of the viewer (px)
-
-
-
- -
Height of the viewer (px)
-
-
-
- - -
-
-
-
-
- -
- - - - diff --git a/src/main/webapp/connect/gdriveconnector/att-viewer.html b/src/main/webapp/connect/gdriveconnector/att-viewer.html deleted file mode 100644 index 98fe7016..00000000 --- a/src/main/webapp/connect/gdriveconnector/att-viewer.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - -Diagram Upload Viewer - - - - - - - - - - - diff --git a/src/main/webapp/connect/gdriveconnector/att-viewer.js b/src/main/webapp/connect/gdriveconnector/att-viewer.js deleted file mode 100644 index a56b55f5..00000000 --- a/src/main/webapp/connect/gdriveconnector/att-viewer.js +++ /dev/null @@ -1,278 +0,0 @@ -(function(){ - var lightbox = AC.getUrlParam('lightbox') == '1'; - - if (lightbox) - { - document.body.style.backgroundImage = 'url(/images/drawlogo-text-bottom.svg)'; - document.body.style.backgroundPosition = 'center 30%'; - document.body.style.backgroundSize = '128px'; - } - - var connectUrl = AC.getBaseUrl() + '/atlassian-connect'; - var head = document.getElementsByTagName('head')[0]; - - var script = document.createElement('script'); - script.onload = main; - script.src = 'https://connect-cdn.atl-paas.net/all.js'; - script.setAttribute('data-options', 'resize:false;margin:false'); - head.appendChild(script); - - var link = document.createElement('link'); - link.type = 'text/css'; - link.rel = 'stylesheet'; - link.href = connectUrl + '/all.css'; - head.appendChild(link); - - function showError(errMsg) - { - document.body.style.backgroundImage = 'none'; - document.body.innerHTML = ' ' + - AC.htmlEntities(errMsg); - AP.resize('100%', '20'); - }; - - function viewAttachment(attId, attVer, pageId, width, height, filename, mimeType, autoSize, isDrawio, aspect) - { - document.body.innerHTML = ''; - document.body.style.backgroundImage = 'url(/connect/gdriveconnector/spinner.gif)'; - document.body.style.backgroundSize = null; - - AP.request({ - url: '/download/attachments/' + pageId + '/' + encodeURIComponent(filename) + - '?version=' + attVer, - success: function(resp) - { - if (isDrawio) - { - var isPng = mimeType == 'image/png'; - - //TODO This code is shared with Google Drive viewer also, abstract it - try - { - if (isPng) - { - resp = AC.extractGraphModelFromPng(resp); - } - - var viewerPageId, layerIds; - - if (aspect != null) - { - var aspectArray = aspect.split(' '); - - if (aspectArray.length > 1) - { - viewerPageId = aspectArray[0]; - layerIds = aspectArray.slice(1); - } - } - - if (lightbox) - { - AP.resize('100%', '100%'); - - var config = {highlight: '#3572b0', nav: true, lightbox: false, - pageId: viewerPageId, layerIds: layerIds}; - - var viewer = new GraphViewer(null, null, config); - viewer.lightboxChrome = false; - viewer.xml = resp; - - // Enables layers via flag to avoid toolbar - viewer.layersEnabled = true; - - var ui = viewer.showLocalLightbox(); - // Destroy lightbox with ui instance - var destroy = ui.destroy; - ui.destroy = function() - { - AP.dialog.close(); - destroy.apply(this, arguments); - }; - - // Workaround for ignored header toolbar height for iframe - ui.editor.graph.container.style.bottom = '51px'; - } - else - { - var refreshImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAhFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8qm6wAAAAK3RSTlMABr4XDQoC07pc+/Yq5dzYtaiSjXlkMx4U8u/NwrKZf1gl8eDKb2lOR0Q6/VKNjQAAAKlJREFUGNOtjlcOwjAQBd1jOwnpvdNh738/kuA4iE/EfI1Gu9JD/4RTyr+bNxDHCS8FKp62CXWAlSYj0n6MNZziLOt90EC2OgXQ5osoF/aagr/GgsBeRUpSsUgeSikHbG4xFpssamCU0lIYZVuMDkFw9oxeTaUOgE74e0T1+Ki1wvOl8iHituojVDJJiAuNhwxlG9+Jhhm3sxGJiaFy7MMuvjFksavRD7wAhtIMKUShI2QAAAAASUVORK5CYII='; - - var btnDefs = { - 'refresh': {title: 'Refresh', - image: refreshImg, handler: function() - { - viewAttachment(attId, attVer, pageId, width, height, filename, mimeType, autoSize, isDrawio, aspect); - } - } - }; - - var tbHeight = GraphViewer.prototype.toolbarHeight; - var doc = mxUtils.parseXml(resp); - - var container = document.createElement('div'); - - container.style.cssText = 'position:absolute;max-width:100%;border:1px solid transparent;'; - document.body.appendChild(container); - - var config = {highlight: '#3572b0', 'toolbar-position': 'top', - nav: true, border: 2, title: filename, lightbox: true, - toolbar: 'pages refresh zoom layers lightbox', 'toolbar-buttons': btnDefs, - pageId: viewerPageId, layerIds: layerIds}; - - if (!autoSize) - { - config['auto-fit'] = true; - config.resize = false; - } - - var viewer = new GraphViewer(container, doc.documentElement, config); - - viewer.showLightbox = function() - { - //Create an aspect reflecting current view - var layerIds = [], viewerPageId = viewer.diagrams[viewer.currentPage].getAttribute('id'); - - var model = viewer.graph.getModel(); - var childCount = model.getChildCount(model.root); - - // Get visible layers - for (var i = 0; i < childCount; i++) - { - var layer = model.getChildAt(model.root, i); - - if (model.isVisible(layer)) - { - layerIds.push(layer.id); - } - } - - var curAspect = viewerPageId + ' ' + layerIds.join(' '); - - AP.dialog.create( - { - header: filename, - key: 'DULightbox', - size: 'fullscreen', - customData: {attId: attId, pageId: pageId, filename: filename, attVer: attVer, - width: width, height: height, mimeType: mimeType, aspect: curAspect}, - chrome: true - }); - }; - - // Handles resize of iframe after zoom - var graphDoResizeContainer = viewer.graph.doResizeContainer; - - if (!autoSize) - { - AP.resize(width, height); - viewer.graph.doResizeContainer(width, height); - } - else - { - function updateHeight(height) - { - AP.resize('100%', Math.ceil(height) + tbHeight + 4); - }; - - viewer.graph.doResizeContainer = function(width, height) - { - graphDoResizeContainer.apply(this, arguments); - updateHeight(height); - }; - - // Updates the size of the iframe in responsive cases - viewer.updateContainerHeight = function(container, height) - { - updateHeight(height); - }; - - updateHeight(container.offsetHeight); - } - } - - document.body.style.backgroundImage = 'none'; - } - catch(e) - { - console.log(e); - showError('Attachment file "' + filename + '" is corrupted'); - } - } - else - { - var img = new Image(); - - img.onload = function() - { - document.body.style.backgroundImage = 'none'; - - if (!autoSize) - { - var s = Math.min(width / img.width, height / img.height); - - img.width = s * img.width; - img.height = s * img.height; - - img.style.verticalAlign = 'middle'; - document.body.style.lineHeight = height + 'px'; - document.body.style.textAlign = 'center'; - - AP.resize(width, height); - } - else - { - AP.resize(img.width, img.height); - } - - document.body.appendChild(img); - }; - - img.onerror = function() - { - showError('Attachment file "' + filename + '" is corrupted'); - }; - - img.src = resp; - } - }, - error: function() - { - showError('Failed to load attachment file "' + filename + '"'); - } - }); - }; - - function main() - { - if (lightbox) - { - AP.dialog.getCustomData(function (customData) { - viewAttachment(customData.attId, customData.attVer, customData.pageId, customData.width, - customData.height, customData.filename, customData.mimeType, null, true, customData.aspect); - }); - } - else - { - var pageId = AC.getUrlParam('pageId'); - var attId = AC.getUrlParam('attId'); - var attVer = AC.getUrlParam('attVer'); - var width = AC.getUrlParam('width'); - var height = AC.getUrlParam('height'); - var filename = AC.getUrlParam('filename', true); - var mimeType = AC.getUrlParam('mimeType', true) || ''; - var isDrawio = AC.getUrlParam('isDrawio') == '1'; - var aspect = AC.getUrlParam('aspect', true); - var autoSize = AC.getUrlParam('autoSize') == '1'; - - if (attId == null || attVer == null) - { - showError('Error: Missing File ID'); - } - else - { - viewAttachment(attId, attVer, pageId, width, - height, filename, mimeType, autoSize, isDrawio, aspect); - } - } - } -})(); \ No newline at end of file diff --git a/src/main/webapp/connect/gdriveconnector/images/gdriveconnector.png b/src/main/webapp/connect/gdriveconnector/images/gdriveconnector.png deleted file mode 100644 index aaa7c270..00000000 Binary files a/src/main/webapp/connect/gdriveconnector/images/gdriveconnector.png and /dev/null differ diff --git a/src/main/webapp/connect/gdriveconnector/images/gdriveconnector.svg b/src/main/webapp/connect/gdriveconnector/images/gdriveconnector.svg deleted file mode 100644 index 51413a71..00000000 --- a/src/main/webapp/connect/gdriveconnector/images/gdriveconnector.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/webapp/connect/gdriveconnector/macroEditor.html b/src/main/webapp/connect/gdriveconnector/macroEditor.html deleted file mode 100644 index d1494c71..00000000 --- a/src/main/webapp/connect/gdriveconnector/macroEditor.html +++ /dev/null @@ -1,145 +0,0 @@ - - - - -GDrive Connector Editor - - - - - - - - - - -
-
-
-
- - - -
-
Google Drive file name
-
-
-
- -
Width of the viewer (px)
-
-
-
- -
Height of the viewer (px)
-
-
-
- - -
-
- -
- -
-
-
- - -
-
-
-
- - - Loading... -
-
- - - - diff --git a/src/main/webapp/connect/gdriveconnector/od-macroEditor.html b/src/main/webapp/connect/gdriveconnector/od-macroEditor.html deleted file mode 100644 index f6f133d9..00000000 --- a/src/main/webapp/connect/gdriveconnector/od-macroEditor.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - -OneDrive Connector Editor - - - - - - - - - - -
-
-
-
- - - -
-
OneDrive file name
-
-
-
- -
Width of the viewer (px)
-
-
-
- -
Height of the viewer (px)
-
-
-
- - -
-
- -
- -
-
-
- - -
-
-
- -
- - - - diff --git a/src/main/webapp/connect/gdriveconnector/od-viewer.html b/src/main/webapp/connect/gdriveconnector/od-viewer.html deleted file mode 100644 index 048c43cf..00000000 --- a/src/main/webapp/connect/gdriveconnector/od-viewer.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - -OneDrive Connector Viewer - - - - - - - - - - - - diff --git a/src/main/webapp/connect/gdriveconnector/od-viewer.js b/src/main/webapp/connect/gdriveconnector/od-viewer.js deleted file mode 100644 index 23780353..00000000 --- a/src/main/webapp/connect/gdriveconnector/od-viewer.js +++ /dev/null @@ -1,350 +0,0 @@ -(function(){ - var lightbox = AC.getUrlParam('lightbox') == '1'; - - if (lightbox) - { - document.body.style.backgroundImage = 'url(/images/drawlogo-text-bottom.svg)'; - document.body.style.backgroundPosition = 'center 30%'; - document.body.style.backgroundSize = '128px'; - } - - var connectUrl = AC.getBaseUrl() + '/atlassian-connect'; - var head = document.getElementsByTagName("head")[0]; - - var script = document.createElement("script"); - - script.onload = function() - { - AC.getCurPageId(function(pageId, draftPage) - { - confPageId = pageId; - isDraft = draftPage; - - main(); - }); - }; - - script.src = 'https://connect-cdn.atl-paas.net/all.js'; - script.setAttribute('data-options', 'resize:false;margin:false'); - head.appendChild(script); - - var link = document.createElement("link"); - link.type = "text/css"; - link.rel = "stylesheet"; - link.href = connectUrl + '/all.css'; - head.appendChild(link); - - var confPageId, isDraft; - - function showError(errMsg) - { - document.body.style.backgroundImage = 'none'; - document.body.innerHTML = ' ' + - AC.htmlEntities(errMsg); - AP.resize('100%', '20'); - }; - - function getFileInfoErr(err) - { - if (err && (err.status == 403 || err.status == 400)) //400 is returned when a business account file is accessed via a personal account - { - showError('Error: Access Denied. You do not have permission to access this file.'); - } - else - { - showError('Error: Cannot get file information.'); - } - }; - - function showDiagram(fileId, driveId, width, height, name, mimeType, autoSize, aspect) - { - document.body.innerHTML = ''; - document.body.style.backgroundImage = 'url(/connect/gdriveconnector/spinner.gif)'; - document.body.style.backgroundSize = null; - - AC.getFileInfo(fileId, driveId, function(fileInfo) - { - var isPng = fileInfo.file.mimeType == 'image/png'; - var isVsdx = /\.v(dx|sdx?)$/i.test(name); - - function cacheAndRender(fileContent, timestamp, filename) - { - timestamp = String(timestamp); - renderDiagram(fileContent); - - AC.uploadCachedMxFile(fileContent, timestamp + '_' + filename, AC.noop, AC.noop); - - //Delete old cached file - AC.delOldCachedFiles(confPageId, filename, timestamp); - }; - - //TODO This code is shared with Google Drive viewer also, abstract it - function renderDiagram(resp) - { - try - { - if (isPng) - { - resp = 'data:image/png;base64,' + Editor.base64Encode (resp); - resp = AC.extractGraphModelFromPng(resp); - } - - var pageId, layerIds; - - if (aspect != null) - { - var aspectArray = aspect.split(' '); - - if (aspectArray.length > 1) - { - pageId = aspectArray[0]; - layerIds = aspectArray.slice(1); - } - } - - if (lightbox) - { - AP.resize('100%', '100%'); - - var config = {highlight: '#3572b0', nav: true, lightbox: false, - pageId: pageId, layerIds: layerIds}; - - EditorUi.prototype.lightboxToolbarActions = [{icon: Editor.editLargeImage, tooltip: mxResources.get('edit'), fn: function() - { - window.open('https://' + window.location.hostname + '/#W' + encodeURIComponent(driveId + '/' + fileId)); - }}]; - - var viewer = new GraphViewer(null, null, config); - viewer.lightboxChrome = false; - viewer.xml = resp; - - // Enables layers via flag to avoid toolbar - viewer.layersEnabled = true; - - var ui = viewer.showLocalLightbox(); - // Destroy lightbox with ui instance - var destroy = ui.destroy; - ui.destroy = function() - { - AP.dialog.close(); - destroy.apply(this, arguments); - }; - - // Workaround for ignored header toolbar height for iframe - ui.editor.graph.container.style.bottom = '51px'; - } - else - { - var refreshImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAhFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8qm6wAAAAK3RSTlMABr4XDQoC07pc+/Yq5dzYtaiSjXlkMx4U8u/NwrKZf1gl8eDKb2lOR0Q6/VKNjQAAAKlJREFUGNOtjlcOwjAQBd1jOwnpvdNh738/kuA4iE/EfI1Gu9JD/4RTyr+bNxDHCS8FKp62CXWAlSYj0n6MNZziLOt90EC2OgXQ5osoF/aagr/GgsBeRUpSsUgeSikHbG4xFpssamCU0lIYZVuMDkFw9oxeTaUOgE74e0T1+Ki1wvOl8iHituojVDJJiAuNhwxlG9+Jhhm3sxGJiaFy7MMuvjFksavRD7wAhtIMKUShI2QAAAAASUVORK5CYII='; - - var btnDefs = { - 'refresh': {title: 'Refresh', - image: refreshImg, handler: function() - { - showDiagram(fileId, driveId, width, height, name, mimeType, autoSize, aspect); - } - } - }; - - var tbHeight = GraphViewer.prototype.toolbarHeight; - var doc = mxUtils.parseXml(resp); - - var container = document.createElement('div'); - - container.style.cssText = 'position:absolute;max-width:100%;border:1px solid transparent;'; - document.body.appendChild(container); - - var config = {highlight: '#3572b0', 'toolbar-position': 'top', - nav: true, border: 2, title: name, lightbox: true, - toolbar: 'pages refresh zoom layers lightbox', 'toolbar-buttons': btnDefs, - pageId: pageId, layerIds: layerIds}; - - if (!autoSize) - { - config['auto-fit'] = true; - config.resize = false; - } - - var viewer = new GraphViewer(container, doc.documentElement, config); - - viewer.showLightbox = function() - { - //Create an aspect reflecting current view - var layerIds = [], pageId = viewer.diagrams[viewer.currentPage].getAttribute('id'); - - var model = viewer.graph.getModel(); - var childCount = model.getChildCount(model.root); - - // Get visible layers - for (var i = 0; i < childCount; i++) - { - var layer = model.getChildAt(model.root, i); - - if (model.isVisible(layer)) - { - layerIds.push(layer.id); - } - } - - var curAspect = pageId + ' ' + layerIds.join(' '); - - AP.dialog.create( - { - header: name, - key: 'lightbox', - size: 'fullscreen', - customData: {fileId: fileId, driveId: driveId, name: name, width: width, - height: height, mimeType: mimeType, aspect: curAspect}, - chrome: true - }); - }; - - // Handles resize of iframe after zoom - var graphDoResizeContainer = viewer.graph.doResizeContainer; - - if (!autoSize) - { - AP.resize(width, height); - viewer.graph.doResizeContainer(width, height); - } - else - { - function updateHeight(height) - { - AP.resize('100%', Math.ceil(height) + tbHeight + 4); - }; - - viewer.graph.doResizeContainer = function(width, height) - { - graphDoResizeContainer.apply(this, arguments); - updateHeight(height); - }; - - // Updates the size of the iframe in responsive cases - viewer.updateContainerHeight = function(container, height) - { - updateHeight(height); - }; - - updateHeight(container.offsetHeight); - } - } - - document.body.style.backgroundImage = 'none'; - } - catch(e) - { - console.log(e); - showError('File "' + name + '" is corrupted'); - } - }; - - function loadFileErr() - { - showError('Failed to load OneDrive file "' + name + '"'); - }; - - var timestamp = new Date(fileInfo.lastModifiedDateTime).getTime(); - - AP.request({ - url: '/download/attachments/' + confPageId + '/' + encodeURIComponent(timestamp + '_' + fileInfo.name), - success: renderDiagram, - error : function() //Not found (e.g, file updated), fetch and cache - { - var req = new XMLHttpRequest(); - req.open('GET', fileInfo['@microsoft.graph.downloadUrl']); - - if (isVsdx) - { - req.responseType = 'blob'; - } - - req.onreadystatechange = function() - { - if (this.readyState == 4) - { - if (this.status >= 200 && this.status <= 299) - { - if (isVsdx) - { - convertVSDXtoMX(req.response, name, function(content) - { - cacheAndRender(content, timestamp, name); - }, loadFileErr); - } - else - { - cacheAndRender(req.responseText, timestamp, name); - } - } - else - { - loadFileErr(); - } - } - }; - - if (isPng && req.overrideMimeType) - { - req.overrideMimeType('text/plain; charset=x-user-defined'); - } - - req.send(); - } - }); - }, getFileInfoErr); - }; - - function main() - { - if (lightbox) - { - AP.dialog.getCustomData(function (customData) { - showDiagram(customData.fileId, customData.driveId, customData.width, customData.height, - customData.name, customData.mimeType, null, customData.aspect); - }); - } - else - { - var fileId = AC.getUrlParam('fileId'); - var driveId = AC.getUrlParam('driveId'); - var width = AC.getUrlParam('width'); - var height = AC.getUrlParam('height'); - var name = AC.getUrlParam('filename', true); - var mimeType = AC.getUrlParam('mimeType', true) || ''; - var isDrawio = AC.getUrlParam('isDrawio'); - isDrawio = isDrawio == 'true' || isDrawio == '1'; - var aspect = AC.getUrlParam('aspect', true); - var autoSize = AC.getUrlParam('autoSize') == '1'; - var embeddedUrl = AC.getUrlParam('embeddedUrl', true); - - if (fileId == null || driveId == null) - { - showError('Error: Missing File ID'); - } - else - { - if (isDrawio) - { - showDiagram(fileId, driveId, width, height, name, mimeType, autoSize, aspect); - } - else if (embeddedUrl) - { - AP.resize(width, height); - window.location.href = embeddedUrl; - } - else - { - AP.resize(width, height); - AC.getPreviewUrl(fileId, driveId, function(url) - { - window.location.href = url; - }, function() - { - showError('Error: Cannot get file preview.'); - }); - } - } - } - }; -})(); diff --git a/src/main/webapp/connect/gdriveconnector/plugin.json b/src/main/webapp/connect/gdriveconnector/plugin.json deleted file mode 100644 index 503f60fa..00000000 --- a/src/main/webapp/connect/gdriveconnector/plugin.json +++ /dev/null @@ -1,400 +0,0 @@ -{ - "name": "Diagram Viewer for Confluence", - "description": "Deprecated Google Connector", - "key": "com.mxgraph.confluence.plugins.driveconnector", - "baseUrl": "https://www.draw.io", - "apiMigrations": { - "gdpr": true - }, - "vendor": - { - "name": "Seibert Media", - "url": "https://info.seibert-media.net" - }, - "version": "1.0.3", - "authentication": - { - "type": "none" - }, - "modules": - { - "generalPages": - [ - { - "key": "lightbox", - "url": "/connect/gdriveconnector/od-viewer.html?lightbox=1", - "location": "hidden", - "name": { - "value": "Lightbox" - } - }, - { - "key": "GDLightbox", - "location": "hidden", - "url": "/connect/gdriveconnector/viewer.html?lightbox=1", - "name": { - "value": "Lightbox", - "i18n": "lightbox" - } - }, - { - "key": "DULightbox", - "location": "hidden", - "url": "/connect/gdriveconnector/att-viewer.html?lightbox=1", - "name": { - "value": "Lightbox", - "i18n": "lightbox" - } - }, - { - "key": "macroEditor", - "url": "/connect/gdriveconnector/od-macroEditor.html", - "location": "hidden", - "name": { - "value": "OneDrive Editor" - } - } - ], - "dynamicContentMacros": - [ - { - "name": - { - "value": "Unused" - }, - "url": "/connect/gdriveconnector/viewer.html?fileId=${fileId}&filename=${filename}&width=${width}&height=${height}&mimeType=${mimeType}¯oVer={macroVer}&isDrawio=${isDrawio}&autoSize=${autoSize}&aspect=${aspect}", - "width": "600px", - "height": "400px", - "description": - { - "value": "Unused" - }, "icon": - { - "width": 80, - "height": 80, - "url": "/images/stop-flat-icon-80.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": true, - "key": "gdriveconnector", - "editor": { - "url": "/connect/gdriveconnector/macroEditor.html", - "width": "80%", - "height": "60%" - }, - "parameters": - [ - { - "identifier": "fileId", - "name": - { - "value": "Google Drive file ID" - }, - "type": "string", - "hidden": true, - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "mimeType", - "name": - { - "value": "Google Drive file mime type" - }, - "type": "string", - "hidden": true - }, - { - "identifier": "filename", - "name": - { - "value": "Name of the Google Drive file" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "isDrawio", - "name": - { - "value": "Is the file a draw.io file" - }, - "type": "boolean", - "hidden": true, - "defaultValue": "false" - }, - { - "identifier": "macroVer", - "name": - { - "value": "Macro Version" - }, - "type": "string", - "hidden": true - }, - { - "identifier": "width", - "name": - { - "value": "width" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Height" - }, - "type": "string" - }, - { - "identifier": "autoSize", - "name": - { - "value": "Auto Size" - }, - "type": "string", - "hidden": true - } - ] - }, - { - "name": - { - "value": "Unused" - }, - "url": "/connect/gdriveconnector/od-viewer.html?fileId=${fileId}&driveId=${driveId}&filename=${filename}&width=${width}&height=${height}&mimeType=${mimeType}&isDrawio=${isDrawio}&embeddedUrl=${embeddedUrl}&autoSize=${autoSize}&aspect=${aspect}", - "width": "600px", - "height": "400px", - "description": - { - "value": "Unused" - }, "icon": - { - "width": 80, - "height": 80, - "url": "/images/stop-flat-icon-80.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": true, - "key": "onedriveconnector", - "parameters": - [ - { - "identifier": "filename", - "name": - { - "value": "Name of the OneDrive file" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "fileId", - "name": - { - "value": "OneDrive file ID" - }, - "type": "string", - "hidden": true, - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "driveId", - "name": - { - "value": "OneDrive drive ID" - }, - "type": "string", - "hidden": true, - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "mimeType", - "name": - { - "value": "OneDrive file mime type" - }, - "type": "string", - "hidden": true - }, - { - "identifier": "width", - "name": - { - "value": "width" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Height" - }, - "type": "string" - }, - { - "identifier": "isDrawio", - "name": - { - "value": "Is the file a draw.io file" - }, - "type": "boolean", - "hidden": true, - "defaultValue": "false" - }, - { - "identifier": "embeddedUrl", - "name": - { - "value": "Embedded Url for personal accounts" - }, - "type": "string" - }, - { - "identifier": "autoSize", - "name": - { - "value": "Auto Size" - }, - "type": "string", - "hidden": true - } - ], - "editor": { - "url": "/connect/gdriveconnector/od-macroEditor.html", - "width": "80%", - "height": "60%" - } - }, - { - "name": - { - "value": "Unused" - }, - "url": "/connect/gdriveconnector/att-viewer.html?pageId=${page.id}&attId=${attId}&attVer=${attVer}&filename=${filename}&width=${width}&height=${height}&mimeType=${mimeType}&isDrawio=${isDrawio}&autoSize=${autoSize}&aspect=${aspect}", - "width": "600px", - "height": "400px", - "description": - { - "value": "Unused" - }, "icon": - { - "width": 80, - "height": 80, - "url": "/images/stop-flat-icon-80.png" - }, - "categories": [ - "visuals" - ], - "outputType": "block", - "featured": true, - "key": "attviewerconnector", - "parameters": - [ - { - "identifier": "filename", - "name": - { - "value": "Name of the diagram file" - }, - "type": "string", - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "attId", - "name": - { - "value": "Attachment file ID" - }, - "type": "string", - "hidden": true, - "required": true, - "multiple": false, - "defaultValue": "None" - }, - { - "identifier": "attVer", - "name": - { - "value": "Attachment file version" - }, - "type": "string", - "hidden": true - }, - { - "identifier": "mimeType", - "name": - { - "value": "Attachment file mime type" - }, - "type": "string", - "hidden": true - }, - { - "identifier": "isDrawio", - "name": - { - "value": "Is the file a draw.io file" - }, - "type": "boolean", - "hidden": true, - "defaultValue": "false" - }, - { - "identifier": "width", - "name": - { - "value": "width" - }, - "type": "string" - }, - { - "identifier": "height", - "name": - { - "value": "Height" - }, - "type": "string" - }, - { - "identifier": "autoSize", - "name": - { - "value": "Auto Size" - }, - "type": "string", - "hidden": true - } - ], - "editor": { - "url": "/connect/gdriveconnector/att-macroEditor.html", - "width": "80%", - "height": "60%" - } - } - ] - }, - "scopes": [ - "read" - ] -} \ No newline at end of file diff --git a/src/main/webapp/connect/gdriveconnector/spinner.gif b/src/main/webapp/connect/gdriveconnector/spinner.gif deleted file mode 100644 index 054973c9..00000000 Binary files a/src/main/webapp/connect/gdriveconnector/spinner.gif and /dev/null differ diff --git a/src/main/webapp/connect/gdriveconnector/viewer.html b/src/main/webapp/connect/gdriveconnector/viewer.html deleted file mode 100644 index 4efb623f..00000000 --- a/src/main/webapp/connect/gdriveconnector/viewer.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - -GDrive Connector Viewer - - - - - - - - - - - - diff --git a/src/main/webapp/connect/gdriveconnector/viewer.js b/src/main/webapp/connect/gdriveconnector/viewer.js deleted file mode 100644 index 8f9f1c41..00000000 --- a/src/main/webapp/connect/gdriveconnector/viewer.js +++ /dev/null @@ -1,376 +0,0 @@ -(function() -{ - var lightbox = GAC.getUrlParam('lightbox') == '1'; - - if (lightbox) - { - document.body.style.backgroundImage = 'url(/images/drawlogo-text-bottom.svg)'; - document.body.style.backgroundPosition = 'center 30%'; - document.body.style.backgroundSize = '128px'; - } - - var connectUrl = GAC.getBaseUrl() + '/atlassian-connect'; - var head = document.getElementsByTagName("head")[0]; - - var script = document.createElement('script'); - - script.onload = function() - { - GAC.getCurPageId(function(pageId, draftPage) - { - confPageId = pageId; - isDraft = draftPage; - - main(); - }); - }; - - script.src = 'https://connect-cdn.atl-paas.net/all.js'; - script.setAttribute('data-options', 'resize:false;margin:false'); - head.appendChild(script); - - var link = document.createElement('link'); - link.type = 'text/css'; - link.rel = 'stylesheet'; - link.href = connectUrl + '/all.css'; - head.appendChild(link); - - var diagramMimeTypes = 'application/mxe,application/vnd.jgraph.mxfile,' + - 'application/mxr,application/vnd.jgraph.mxfile.realtime,' + - 'application/vnd.jgraph.mxfile.rtlegacy'; - - var formsMimeType = 'application/vnd.google-apps.form'; - var folderMimeType = 'application/vnd.google-apps.folder'; - - var confPageId, isDraft; - - function showError(errMsg) - { - document.body.style.backgroundImage = 'none'; - document.body.innerHTML = ' ' + - GAC.htmlEntities(errMsg); - AP.resize('100%', '20'); - }; - - function getFileInfoErr(err) - { - if (err && (err.status == 403 || err.status == 400)) //400 is returned when a business account file is accessed via a personal account - { - showError('Error: Access Denied. You do not have permission to access this file.'); - } - else - { - showError('Error: Cannot get file information.'); - } - }; - - function showDiagram(fileId, width, height, name, mimeType, autoSize, macroVer, aspect) - { - document.body.innerHTML = ''; - document.body.style.backgroundImage = 'url(/connect/gdriveconnector/spinner.gif)'; - document.body.style.backgroundSize = null; - - GAC.getFileInfo(fileId, function(fileInfo) - { - var isPng = fileInfo.mimeType == 'image/png'; - - function cacheAndRender(fileContent, timestamp, filename) - { - timestamp = String(timestamp); - renderDiagram(fileContent); - - GAC.uploadCachedMxFile(fileContent, timestamp + '_' + filename, GAC.noop, GAC.noop); - - //Delete old cached file - GAC.delOldCachedFiles(confPageId, filename, timestamp); - }; - - function renderDiagram(resp) - { - try - { - if (isPng) - { - resp = 'data:image/png;base64,' + Editor.base64Encode (resp); - resp = GAC.extractGraphModelFromPng(resp); - } - - var pageId, layerIds; - - if (aspect != null) - { - var aspectArray = aspect.split(' '); - - if (aspectArray.length > 1) - { - pageId = aspectArray[0]; - layerIds = aspectArray.slice(1); - } - } - - if (lightbox) - { - AP.resize('100%', '100%'); - - var config = {highlight: '#3572b0', nav: true, lightbox: false, - pageId: pageId, layerIds: layerIds}; - - EditorUi.prototype.lightboxToolbarActions = [{icon: Editor.editLargeImage, tooltip: mxResources.get('edit'), fn: function() - { - window.open('https://' + window.location.hostname + '/#G' + encodeURIComponent(fileId)); - }}]; - - var viewer = new GraphViewer(null, null, config); - viewer.lightboxChrome = false; - viewer.xml = resp; - - // Enables layers via flag to avoid toolbar - viewer.layersEnabled = true; - - var ui = viewer.showLocalLightbox(); - // Destroy lightbox with ui instance - var destroy = ui.destroy; - ui.destroy = function() - { - AP.dialog.close(); - destroy.apply(this, arguments); - }; - - // Workaround for ignored header toolbar height for iframe - ui.editor.graph.container.style.bottom = '51px'; - } - else - { - var refreshImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAhFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8qm6wAAAAK3RSTlMABr4XDQoC07pc+/Yq5dzYtaiSjXlkMx4U8u/NwrKZf1gl8eDKb2lOR0Q6/VKNjQAAAKlJREFUGNOtjlcOwjAQBd1jOwnpvdNh738/kuA4iE/EfI1Gu9JD/4RTyr+bNxDHCS8FKp62CXWAlSYj0n6MNZziLOt90EC2OgXQ5osoF/aagr/GgsBeRUpSsUgeSikHbG4xFpssamCU0lIYZVuMDkFw9oxeTaUOgE74e0T1+Ki1wvOl8iHituojVDJJiAuNhwxlG9+Jhhm3sxGJiaFy7MMuvjFksavRD7wAhtIMKUShI2QAAAAASUVORK5CYII='; - - var btnDefs = { - 'refresh': {title: 'Refresh', - image: refreshImg, handler: function() - { - showDiagram(fileId, width, height, name, mimeType, autoSize, macroVer, aspect); - } - } - }; - var tbHeight = GraphViewer.prototype.toolbarHeight; - var doc = mxUtils.parseXml(resp); - - var container = document.createElement('div'); - - container.style.cssText = 'position:absolute;max-width:100%;border:1px solid transparent;'; - document.body.appendChild(container); - - var config = {highlight: '#3572b0', 'toolbar-position': 'top', - nav: true, border: 8, title: name, lightbox: true, - toolbar: 'pages refresh zoom layers lightbox', 'toolbar-buttons': btnDefs, - pageId: pageId, layerIds: layerIds}; - - if (!autoSize) - { - config['auto-fit'] = true; - config.resize = false; - } - - var viewer = new GraphViewer(container, doc.documentElement, config); - - viewer.showLightbox = function() - { - //Create an aspect reflecting current view - var layerIds = [], pageId = viewer.diagrams[viewer.currentPage].getAttribute('id'); - - var model = viewer.graph.getModel(); - var childCount = model.getChildCount(model.root); - - // Get visible layers - for (var i = 0; i < childCount; i++) - { - var layer = model.getChildAt(model.root, i); - - if (model.isVisible(layer)) - { - layerIds.push(layer.id); - } - } - - var curAspect = pageId + ' ' + layerIds.join(' '); - - AP.dialog.create( - { - header: name, - key: 'GDLightbox', - size: 'fullscreen', - customData: {fileId: fileId, name: name, width: width, height: height, mimeType: mimeType, macroVer: macroVer, aspect: curAspect}, - chrome: true - }); - }; - - // Handles resize of iframe after zoom - var graphDoResizeContainer = viewer.graph.doResizeContainer; - - if (!autoSize) - { - AP.resize(width, height); - viewer.graph.doResizeContainer(width, height); - } - else - { - function updateHeight(height) - { - AP.resize('100%', Math.ceil(height) + tbHeight + 4); - }; - - viewer.graph.doResizeContainer = function(width, height) - { - graphDoResizeContainer.apply(this, arguments); - updateHeight(height); - }; - - // Updates the size of the iframe in responsive cases - viewer.updateContainerHeight = function(container, height) - { - updateHeight(height); - }; - - updateHeight(container.offsetHeight); - } - } - } - catch(e) - { - console.log(e); - showError('File "' + name + '" is corrupted'); - } - - document.body.style.backgroundImage = 'none'; - }; - - function loadFileErr() - { - showError('Failed to load Google Drive file "' + name + '"'); - }; - - var timestamp = new Date(fileInfo.modifiedDate).getTime(); - - AP.request({ - url: '/download/attachments/' + confPageId + '/' + encodeURIComponent(timestamp + '_' + fileInfo.title), - success: renderDiagram, - error : function() //Not found (e.g, file updated), fetch and cache - { - if (/\.v(dx|sdx?)$/i.test(name)) - { - GAC.getBinaryFile(fileInfo, function(blobFile) - { - convertVSDXtoMX(blobFile, name, function(content) - { - cacheAndRender(content, timestamp, name); - }, loadFileErr); - }, loadFileErr); - } - else - { - GAC.doAuthRequestPlain(fileInfo['downloadUrl'], 'GET', null, function(req) - { - cacheAndRender(req.responseText, timestamp, name); - }, loadFileErr, null, isPng); - } - } - }); - }, getFileInfoErr); - }; - - function main() - { - if (lightbox) - { - AP.dialog.getCustomData(function (customData) { - showDiagram(customData.fileId, customData.width, customData.height, customData.name, - customData.mimeType, null, customData.macroVer, customData.aspect); - }); - } - else - { - var fileId = GAC.getUrlParam('fileId'); - var width = GAC.getUrlParam('width'); - var height = GAC.getUrlParam('height'); - var name = GAC.getUrlParam('filename', true); - var mimeType = GAC.getUrlParam('mimeType', true); - var isDrawio = GAC.getUrlParam('isDrawio') == '1'; - var aspect = GAC.getUrlParam('aspect', true); - var autoSize = GAC.getUrlParam('autoSize') == '1'; - var macroVer = GAC.getUrlParam('macroVer'); - - if (fileId == null) - { - showError('Error: Missing File ID'); - } - else if (macroVer == 2) - { - if (isDrawio || /\.v(dx|sdx?)$/i.test(name)) - { - showDiagram(fileId, width, height, name, mimeType, autoSize, macroVer, aspect); - } - else - { - AP.resize(width, height); - GAC.getFileInfo(fileId, function(fileInfo) - { - window.location.href = fileInfo.embedLink; - }, getFileInfoErr); - } - } - else - { - // Forces reload of document to override browser cache - var nocache = 't=' + new Date().getTime(); - var url = null; - - if (mimeType == 'image') - { - document.body.style.backgroundImage = 'none'; - document.body.innerHTML = ''; - } - else if (mimeType == 'thumb') - { - document.body.style.backgroundImage = 'none'; - document.body.innerHTML = ''; - } - else - { - var drawioFile = diagramMimeTypes.indexOf(mimeType) > -1 || (name != null && - (/(\.xml)($|\?)/i.test(name) || /(\.drawio)($|\?)/i.test(name))); - - if (drawioFile || mimeType == 'application/json' || mimeType == 'application/octet-stream' || - (name != null && (/(\.v(dx|sdx?))($|\?)/i.test(name) || /(\.gliffy)($|\?)/i.test(name)))) - { - // Uses public file URL, fallback implemented in editor - var pubUrl = encodeURIComponent('https://drive.google.com/uc?id=' + fileId + '&export=download'); - var editUrl = (drawioFile) ? encodeURIComponent('https://www.draw.io/#G' + fileId) : '_blank'; - - url = 'https://www.draw.io/?lightbox=1&toolbar-config=%7B"refreshBtn"%3Atrue%2C"fullscreenBtn"%3Atrue%2C"closeBtn"%3Atrue%7D&layers=1&' + - 'edit=' + editUrl + ((name != null) ? ('&template-filename=' + encodeURIComponent(name)) : '') + '#U' + pubUrl; - } - else if (mimeType == formsMimeType) - { - url = 'https://docs.google.com/forms/d/' + fileId + '/viewform?' + nocache; - } - else if (mimeType == folderMimeType) - { - // Possible view options are #list and #grid - url = 'https://drive.google.com/embeddedfolderview?id=' + fileId + '&authuser=0&' + nocache + '#list'; - } - else if (mimeType == 'url') - { - url = decodeURIComponent(fileId); - } - else - { - url = 'https://drive.google.com/file/d/' + fileId + '/preview?authuser=0&' + nocache; - } - - window.location.href = url; - } - } - } - }; -})(); \ No newline at end of file diff --git a/src/main/webapp/connect/jira/ac.js b/src/main/webapp/connect/jira/ac.js deleted file mode 100644 index 9a7db614..00000000 --- a/src/main/webapp/connect/jira/ac.js +++ /dev/null @@ -1,372 +0,0 @@ -var AC = {}; - -AC.getUrlParam = function(param, escape, url){ - try{ - var url = url || window.location.search; - var regex = new RegExp(param + '=([^&]+)'), - data = regex.exec(url)[1]; - // decode URI with plus sign fix. - return (escape) ? window.decodeURIComponent(data.replace(/\+/g, '%20')) : data; - } catch (e){ - return ''; - } -}; - -AC.getMetaTag = function(name) { - return document.getElementsByTagName('meta')[name].getAttribute('content'); -}; - -AC.openEditor = function(baseUrl, issueId, diagramName) -{ - var diagramXml = null; - var link = document.createElement('a'); - link.href = location.href; - link.href = link.href; //to have 'host' populated under IE - var hostUrl = link.protocol + '//' + link.hostname; - - var lang = AC.getUrlParam['loc']; - - if (lang != null) - { - var dash = lang.indexOf('-'); - - if (dash >= 0) - { - lang = lang.substring(0, dash); - } - } - - var editor = $(' - - - - \ No newline at end of file diff --git a/src/main/webapp/connect/trello/images/drawio-trello-ss.png b/src/main/webapp/connect/trello/images/drawio-trello-ss.png deleted file mode 100644 index 3a8e18b3..00000000 Binary files a/src/main/webapp/connect/trello/images/drawio-trello-ss.png and /dev/null differ diff --git a/src/main/webapp/connect/trello/index.html b/src/main/webapp/connect/trello/index.html deleted file mode 100644 index 20c96119..00000000 --- a/src/main/webapp/connect/trello/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - -

- draw.io Trello Power-Up -

- - diff --git a/src/main/webapp/connect/trello/js/attSection.js b/src/main/webapp/connect/trello/js/attSection.js deleted file mode 100644 index a8466d81..00000000 --- a/src/main/webapp/connect/trello/js/attSection.js +++ /dev/null @@ -1,201 +0,0 @@ -// Resize sensor not needed -GraphViewer.useResizeSensor = false; - -var t = window.TrelloPowerUp.iframe(); - -t.render(function() -{ - var idSep = encodeURIComponent('|$|'); - var ident = 'attachment-thumbnail-details-options-item dark-hover'; - var data = null; - - // NOTE: Autosave is enabled to avoid possible data loss due - // to no event fired before the modal dialog closes - var getEditFunction = function(att, name) - { - return function() - { - var id = t.getContext().card + idSep + att.id; - - t.modal({ - url: './editor.html', - fullscreen: true, - title: 'draw.io: ' + name, - args: {url: mxTrelloCommon.editorURL + - ((location.hostname != 'www.draw.io') ? - '?dev=1&test=1&embed=1&libraries=1&tr=1&gapi=1&od=1&gh=1&db=1&gl=1&p=tr' : - '?embed=1&libraries=1&tr=1&gapi=1&od=1&gh=1&db=1&gl=1&p=tr') + - '#T' + id} - }); - } - }; - - var getPrevFunction = function(prevURL, name) - { - return function(evt) - { - var source = mxEvent.getSource(evt); - - while (source != null) - { - if (source.className != null && source.className. - toString().substring(0, ident.length) == ident) - { - return; - } - - source = source.parentNode; - } - - // Redirect via editor.html to avoid Trello injecting crap - // after the hash in the URL - t.modal({ - url: './editor.html', - fullscreen: true, - title: 'draw.io: ' + name, - args: {url: prevURL} - }); - } - }; - - t.card('attachments') - .get('attachments') - .filter(mxTrelloCommon.attFilterFn) - .then(function(drawioAtts) - { - var content = document.getElementById('content'); - content.innerHTML = ""; - - for (var i = 0; i < drawioAtts.length; i++) - { - (function(atts) - { - var div = document.createElement('div'); - div.className = "attachment-thumbnail"; - - var attName = atts.name; - - //TODO add preview modal on click - //For PNG and SVG (on supported browsers) show them as images, otherwise, load them inside a lightbox editor [size 300px max for images] - //Click shows a preview - var previews = atts.previews; - - var prevURL = mxTrelloCommon.editorURL + '?lightbox=1&nav=1&layers=1&highlight=3572b0'; - var fileId = '#T' + t.getContext().card + idSep + atts.id; - - if (previews.length > 0) - { - //find the best size (max dim is 300px) - var maxPrev = previews[0]; - - for (var j = 1; j < previews.length; j++) - { - if (previews[j].width <= 350 && previews[j].height <= 260 && maxPrev.width < previews[j].width) - { - maxPrev = previews[j]; - } - } - - var imgLink = document.createElement('a'); - imgLink.className = "attachment-thumbnail-preview"; - imgLink.setAttribute('href', 'javascript:void(0);'); - imgLink.setAttribute('title', attName); - imgLink.style.cssText = "background-image: url('" + maxPrev.url + "');background-color: #fcfcfc;"; - - div.appendChild(imgLink); - } - else - { - var id = t.getContext().card + encodeURIComponent('|$|') + atts.id; - - var container = document.createElement('div'); - container.style.cssText = 'position:absolute;top:0px;left:0px;width:110px;' + - 'height:80px;border:1px solid transparent;cursor:pointer;' + - 'background-position:center;background-repeat:no-repeat;background-image:url(/images/spin.gif);'; - div.appendChild(container); - - // Does not use iframe for quicker loading and avoiding authorize dialog - mxUtils.get('/proxy?url=' + encodeURIComponent(atts.url), function(req) - { - container.style.backgroundImage = 'none'; - - if (req.getStatus() >= 200 && req.getStatus() < 300) - { - var viewer = new GraphViewer(container, req.getDocumentElement(), - {highlight: '#3572b0', border: 4, lightbox: false, - nav: true, 'max-height': 72}); - container.style.width = '110px'; - container.style.height = '80px'; - - if (viewer.graph != null) - { - // Adds transparent background - viewer.graph.view.canvas.ownerSVGElement.style.backgroundColor = 'transparent'; - - // Undo container resize and center - var bounds = viewer.graph.getGraphBounds(); - var dx = (110 - bounds.width) / 2 - bounds.x; - var dy = (80 - bounds.height) / 2 - bounds.y; - viewer.graph.view.canvas.ownerSVGElement.setAttribute('transform', - 'translate(' + dx + ' ' + dy + ')'); - } - } - }); - } - - var prevFn = getPrevFunction(prevURL + fileId, attName); - mxEvent.addListener(div, 'click', prevFn); - - var detailsP = document.createElement('p'); - detailsP.className = "attachment-thumbnail-details"; - - var nameSpan = document.createElement('span'); - nameSpan.className = "attachment-thumbnail-name"; - mxUtils.write(nameSpan, attName); - detailsP.appendChild(nameSpan); - - var detailOpt = document.createElement('span'); - detailOpt.className = "u-block quiet attachment-thumbnail-details-title-options"; - - var addedSpan = document.createElement('span'); - addedSpan.innerHTML = " "; //Add more details about the file here - detailOpt.appendChild(addedSpan); - // - // Added an hour ago - // - // - // Delete - // - detailsP.appendChild(detailOpt); - - var actionsSpan = document.createElement('span'); - actionsSpan.className = "quiet attachment-thumbnail-details-options"; - detailsP.appendChild(actionsSpan); - - var downloadLink = document.createElement('a'); - downloadLink.className = "attachment-thumbnail-details-options-item dark-hover"; - downloadLink.setAttribute('href', atts.url); - downloadLink.setAttribute('target', '_blank'); - downloadLink.setAttribute('download', attName); - downloadLink.innerHTML = ' Download'; - actionsSpan.appendChild(downloadLink); - - var editLink = document.createElement('a'); - editLink.className = "attachment-thumbnail-details-options-item dark-hover"; - editLink.setAttribute('href', 'javascript:void(0);'); - editLink.innerHTML = ' Edit'; - editLink.addEventListener("click", getEditFunction(atts, attName)); - actionsSpan.appendChild(editLink); - - detailsP.appendChild(actionsSpan); - div.appendChild(detailsP); - - content.appendChild(div); - })(drawioAtts[i]); - } - }) - .then(function() - { - return t.sizeTo('#content'); - }); -}); diff --git a/src/main/webapp/connect/trello/js/client.js b/src/main/webapp/connect/trello/js/client.js deleted file mode 100644 index c299f03b..00000000 --- a/src/main/webapp/connect/trello/js/client.js +++ /dev/null @@ -1,69 +0,0 @@ -/* global TrelloPowerUp */ - -var Promise = TrelloPowerUp.Promise; - -TrelloPowerUp - .initialize({ - 'card-buttons' : function(t, options) - { - return [ { - icon : 'https://www.draw.io/images/drawlogo48-gray.png', - text : 'draw.io', - callback : function(t) - { - return t.popup({ - title : 'Create a New Diagram...', - url : './new.html', - height : 190 - }); - } - } ]; - }, - 'attachment-sections' : function(t, options) - { - // Claim all png attachment that is created by draw.io - var claimed = options.entries.filter(mxTrelloCommon.attFilterFn); - - if (claimed && claimed.length > 0) - { - return [ { - claimed : claimed, - icon : 'https://www.draw.io/images/drawlogo48-gray.png', - title : 'draw.io Diagrams', - content : - { - type : 'iframe', - url : t.signUrl('./attSection.html', { - arg: "" - }), - height : 230 - } - } ]; - } - else - { - return []; - } - }, - 'card-badges' : function(t, options) - { - return t.card('attachments') - .get('attachments') - .filter(mxTrelloCommon.attFilterFn) - .then(function(claimed) - { - if (claimed && claimed.length > 0) - { - return [{ - text: claimed.length, - icon: 'https://www.draw.io/images/drawlogo48-gray.png', - color: 'white' - }]; - } - else - { - return []; - } - }); - } - }); diff --git a/src/main/webapp/connect/trello/js/common.js b/src/main/webapp/connect/trello/js/common.js deleted file mode 100644 index 81c9174b..00000000 --- a/src/main/webapp/connect/trello/js/common.js +++ /dev/null @@ -1,8 +0,0 @@ -mxTrelloCommon = { - editorURL: location.protocol + '//' + location.hostname + '/', - attFilterFn: function(attachment) - { - // Returns true for files ending with .drawio and an optional extension - return /.*\.drawio(\.[A-Za-z]*)?$/.test(attachment.name); - } -}; diff --git a/src/main/webapp/connect/trello/js/editor.js b/src/main/webapp/connect/trello/js/editor.js deleted file mode 100644 index 2a295666..00000000 --- a/src/main/webapp/connect/trello/js/editor.js +++ /dev/null @@ -1,29 +0,0 @@ -(function () { - var t = window.TrelloPowerUp.iframe(); - var url = t.arg('url'); - - var iframe = document.getElementById("editorFrame"); - iframe.setAttribute('src', url); - - // Only needed to invoke closeModal via embed button in toolbar - // and to receive messages from iframe (cannot recv from t.modal) - window.addEventListener('message', function(evt) - { - if (evt.data.length > 0) - { - try - { - var msg = JSON.parse(evt.data); - - if (msg != null && msg.event == 'exit') - { - t.closeModal(); - } - } - catch (e) - { - // ignore - } - } - }); -})(); \ No newline at end of file diff --git a/src/main/webapp/connect/trello/js/new.js b/src/main/webapp/connect/trello/js/new.js deleted file mode 100644 index 21590cff..00000000 --- a/src/main/webapp/connect/trello/js/new.js +++ /dev/null @@ -1,104 +0,0 @@ -(function() -{ - var t = window.TrelloPowerUp.iframe(); - var diagName = document.getElementById("diagName"); - var errorMsg = document.getElementById("errorMsg"); - - diagName.focus(); - - function create(fileName, type, templateId) - { - t.closePopup(); - - t.modal({ - url: './editor.html', - fullscreen: true, - title: 'draw.io: ' + fileName, - args: {url: mxTrelloCommon.editorURL + - ((location.hostname != 'www.draw.io') ? - '?dev=1&drawdev=1&embed=1&tr=1&gapi=1&od=1&gh=1&db=1&p=tr' : - '?embed=1&tr=1&gapi=1&od=1&gh=1&db=1&p=tr') + - '&filename=' + encodeURIComponent(fileName + '.drawio' + (type == 'xml' ? '' : '.' + type)) + - '&filetype=' + encodeURIComponent(type) + - '&card=' + encodeURIComponent(t.getContext().card) + - ((templateId != null) ? '&template=' + encodeURIComponent(templateId) : '')} - }); - }; - - //Fill the dialog with other attachments - var select = document.getElementById("otherAtt"); - var importBtn = document.getElementById("importBtn"); - - t.card('attachments') - .get('attachments') - .then(function(atts) - { - var count = 0; - for (var i = 0; i < atts.length; i++) - { - if (!mxTrelloCommon.attFilterFn(atts[i])) - { - var opt = document.createElement("option"); - opt.setAttribute('value', atts[i].id); - mxUtils.write(opt, atts[i].name); - select.appendChild(opt); - count++; - } - } - - if (count == 0) - { - document.getElementById("importLbl").style.display = "none"; - select.style.display = "none"; - importBtn.style.display = "none"; - } - - var newDiagFn = function() - { - var name = diagName.value; - var type = document.getElementById("format").value; - - if (name == null || name.length == 0) - { - errorMsg.style.display = ""; - errorMsg.innerHTML = 'Diagram name cannot be empty'; - return; - } - else - { - for (var i = 0; i < atts.length; i++) - { - if (atts[i].name == name + '.drawio' + (type == 'xml' ? '' : '.' + type)) - { - errorMsg.style.display = ""; - errorMsg.innerHTML = 'Diagram already exists'; - return; - } - } - } - - create(name, type); - }; - - diagName.addEventListener("keypress", function(e) - { - if (e.keyCode == 13) - newDiagFn(); - else - errorMsg.style.display = "none"; - }); - - document.getElementById("createBtn").addEventListener("click", newDiagFn); - document.getElementById("createBtn").removeAttribute('disabled'); - }) - .then(function() - { - return t.sizeTo('#content'); - }); - - importBtn.addEventListener("click", function() - { - create(select.options[select.selectedIndex].text, 'xml', select.value); - }); - -})(); \ No newline at end of file diff --git a/src/main/webapp/connect/trello/manifest.json b/src/main/webapp/connect/trello/manifest.json deleted file mode 100644 index 9bf9113d..00000000 --- a/src/main/webapp/connect/trello/manifest.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "draw.io", - "details":"[draw.io](https://www.draw.io) is a free diagramming Power-up that enables you to draw a wide range of diagrams including flowcharts, BPMN, network diagrams, UML and ER diagrams, and much more. draw.io offers these advantages:\n\n* Fully open source platform.\n* All data stored inside Trello, nothing externally.\n* Import diagrams from other diagramming tools.\n\n### Screenshot\n\n![Screenshot of a draw.io diagram insertion in Trello card.](https://www.draw.io/connect/trello/images/drawio-trello-ss.png)", - "icon": { - "url": "https://www.draw.io/images/drawlogo128.png" - }, - "author": "draw.io", - "capabilities": [ - "callback", - "card-buttons", - "card-badges", - "attachment-sections" - ], - "connectors": { - "iframe": { - "url": "./index.html" - } - } -} diff --git a/src/main/webapp/connect/trello/new.html b/src/main/webapp/connect/trello/new.html deleted file mode 100644 index a0a1355a..00000000 --- a/src/main/webapp/connect/trello/new.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - -
- - - - - - -
- - - -
- - - diff --git a/src/main/webapp/connect/vsdx/importer.js b/src/main/webapp/connect/vsdx/importer.js deleted file mode 100644 index 34c83866..00000000 --- a/src/main/webapp/connect/vsdx/importer.js +++ /dev/null @@ -1,79 +0,0 @@ -function convertVSDXtoMX(file, filename, success, error) -{ - function doImport(vsdxFile) - { - try - { - new com.mxgraph.io.mxVsdxCodec({ - addRemoteServiceSecurityCheck: function() {} - }).decodeVsdx(vsdxFile, success, null, error); - } - catch (e) - { - error(); - } - }; - - var delayed = function() - { - if (typeof mxVsdxCodec === 'undefined') - { - if (/(\.v(sd|dx))($|\?)/i.test(filename)) - { - if (VSD_CONVERT_URL != null) - { - var formData = new FormData(); - formData.append('file1', file, filename); - - var xhr = new XMLHttpRequest(); - xhr.open('POST', VSD_CONVERT_URL); - xhr.responseType = 'blob'; - - xhr.onreadystatechange = function() - { - if (xhr.readyState == 4) - { - if (xhr.status >= 200 && xhr.status <= 299) - { - doImport(xhr.response); - } - else - { - error(); - } - } - }; - - xhr.send(formData); - } - else - { - error(); - } - } - else - { - doImport(file); - } - } - else - { - error(); - } - }; - - //Load extensions.min.js lazily - if (typeof mxVsdxCodec === 'undefined') - { - var script = document.createElement('script'); - script.onload = delayed; - script.src = '/js/extensions.min.js'; - script.setAttribute('type', 'text/javascript'); - var head = document.getElementsByTagName('head')[0]; - head.appendChild(script); - } - else - { - delayed(); - } -}; \ No newline at end of file diff --git a/src/main/webapp/export2.html b/src/main/webapp/export2.html deleted file mode 100644 index 0d4c3932..00000000 --- a/src/main/webapp/export2.html +++ /dev/null @@ -1,415 +0,0 @@ - - - - - - - - - - - - -
- - diff --git a/src/main/webapp/js/diagramly/Devel.js b/src/main/webapp/js/diagramly/Devel.js index b00a3929..88155906 100644 --- a/src/main/webapp/js/diagramly/Devel.js +++ b/src/main/webapp/js/diagramly/Devel.js @@ -21,7 +21,7 @@ if (!mxIsElectron && location.protocol !== 'http:') //----------------------------------------------------------// // Version 14.0.1 '\'sha256-ZMnCMK9Jg5ijd0Viqw4KAFn39HeC1LrVwervb9uC7Mo=\' ' + - // Version 13.11.1 + // Version 14.0.0 '\'sha256-KgVey3Yy0LCtaUZnD77KXAark2kZ3wS5HGa+tyAkR28=\' ' + // Version 13.8.2 '\'sha256-1k6pyjDIKgd1KTCRcmDfV6Yc9vgQexHRTiO4zUBoKg8=\' ' + @@ -70,7 +70,6 @@ if (!mxIsElectron && location.protocol !== 'http:') if (urlParams['print-csp'] == '1') { console.log('Content-Security-Policy') - console.log('Development:', devCsp) console.log('app.diagrams.net:', csp.replace(/%script-src%/g, 'https://www.dropbox.com https://api.trello.com'). replace(/%connect-src%/g, 'https://*.dropboxapi.com https://api.trello.com'). @@ -91,6 +90,7 @@ if (!mxIsElectron && location.protocol !== 'http:') replace(/ /g, ' ')); console.log('import.diagrams.net:', 'default-src \'self\'; worker-src blob:; img-src \'self\' blob: data: https://www.lucidchart.com ' + 'https://app.lucidchart.com; style-src \'self\' \'unsafe-inline\'; frame-src https://www.lucidchart.com https://app.lucidchart.com;'); + console.log('Development:', devCsp) } })(); } diff --git a/src/main/webapp/js/diagramly/mxTableLayout.js b/src/main/webapp/js/diagramly/mxTableLayout.js deleted file mode 100644 index f0dc8870..00000000 --- a/src/main/webapp/js/diagramly/mxTableLayout.js +++ /dev/null @@ -1,900 +0,0 @@ -/** - * Copyright (c) 2006-2018, JGraph Ltd - */ -/** - * Class: mxTableLayout - * - * Extends to create a table of the - * child vertices. The children do not need to be connected for this layout - * to work. - * - * Example: - * - * (code) - * var layout = new mxTableLayout(graph, 2, 2); //2x2 table layout - * layout.execute(graph.getDefaultParent()); - * (end) - * - * Constructor: mxTableLayout - * - * Constructs a new table layout for the specified graph - */ -function mxTableLayout(graph, rows, columns, border) -{ - mxGraphLayout.call(this, graph); - this.rows = (rows != null && rows > 0) ? rows : 2; - this.columns = (columns != null && columns > 0) ? columns : 2; - this.border = (border != null) ? border : 0; -}; - -/** - * Extends mxStackLayout. - */ -mxTableLayout.prototype = new mxStackLayout(); -mxTableLayout.prototype.constructor = mxTableLayout; - -/** - * Variable: rows - * - * Specifies the number of rows of the layout. Default is 2. - */ -mxTableLayout.prototype.rows = 2; - -/** - * Variable: columns - * - * Specifies the number of columns of the layout. Default is 2. - */ -mxTableLayout.prototype.columns = 2; - -/** - * Variable: border - * - * Border between cells and around the table. Default is 0. - */ -mxTableLayout.prototype.border = 0; - -/** - * Variable: marginTop - * - * Top margin for the child area. Default is 0. - */ -mxTableLayout.prototype.marginTop = 0; - -/** - * Variable: marginLeft - * - * Top margin for the child area. Default is 0. - */ -mxTableLayout.prototype.marginLeft = 0; - -/** - * Variable: marginRight - * - * Top margin for the child area. Default is 0. - */ -mxTableLayout.prototype.marginRight = 0; - -/** - * Variable: marginBottom - * - * Top margin for the child area. Default is 0. - */ -mxTableLayout.prototype.marginBottom = 0; - -/** - * Variable: equalColumns - * - * Boolean indicating if columns are distributed equally. Default is true - */ -mxTableLayout.prototype.equalColumns = true; - -/** - * Variable: colWidths - * - * Required only if resizeParent is true and autoAddCol is true. It should be one value if equalColumns is true. Default is 100 - */ -mxTableLayout.prototype.colWidths = "100"; - -/** - * Variable: equalRows - * - * Boolean indicating if rows are distributed equally. Default is true - */ -mxTableLayout.prototype.equalRows = true; - -/** - * Variable: rowHeights - * - * Required only if resizeParent is true and autoAddRow is true. It should be one value if equalRows is true. Default is 50 - */ -mxTableLayout.prototype.rowHeights = "50"; - -/** - * Variable: colPercentages - * - * The percentages of each column from the parent width. This value is ignored if equalColumns is true. Default is null. - */ -mxTableLayout.prototype.colPercentages = null; - -/** - * Variable: rowPercentages - * - * The percentages of each row from the parent width. This value is ignored if equalRows is true. Default is null. - */ -mxTableLayout.prototype.rowPercentages = null; - -/** - * Variable: resizeParent - * - * If the parent should be resized when adding new rows/columns. Default is false. - */ -mxTableLayout.prototype.resizeParent = false; - -/** - * Variable: autoAddRow - * - * Weather a new row should be created. Default is true. - */ -mxTableLayout.prototype.autoAddRow = true; - -/** - * Variable: autoAddCol - * - * Weather a new column should be created. This value is ignored if autoAddRow is true. Default is false. - */ -mxTableLayout.prototype.autoAddCol = false; - -/** - * Variable: fill - * - * Boolean indicating if dimension should be changed to fill out the parent - * cell. Default is true. - */ -mxTableLayout.prototype.fill = true; - -/** - * Function: moveCell - * - * Implements . - */ -mxTableLayout.prototype.moveCell = function(cell, x, y) -{ - var model = this.graph.getModel(); - var parent = model.getParent(cell); - var pstate = this.graph.getView().getState(parent); - - if (pstate != null) - { - x -= pstate.x; - y -= pstate.y; - } - - if (cell != null && parent != null) - { - var i = 0; - var childCount = model.getChildCount(parent); - - for (i = 0; i < childCount; i++) - { - var child = model.getChildAt(parent, i); - - if (child != cell) - { - var bounds = model.getGeometry(child); - - if (bounds != null) - { - if (x >= bounds.x && x <= bounds.x + bounds.width - && y >= bounds.y && y <= bounds.y + bounds.height) - { - break; - } - } - } - } - - model.add(parent, cell, i); - } -}; - -/** - * Function: calcDims - * - * Calculate cells positions and dimensions - * - */ -mxTableLayout.prototype.calcDims = function(parent) -{ - if (parent != null) - { - var pgeo = this.getParentSize(parent); - var model = this.graph.getModel(); - var fillWidth = null, fillHeight = null; - var x = this.marginLeft + this.border; - var y = this.marginTop + this.border; - - if (pgeo == null) - { - return null; //We cannot do anything without knowing the parent geometry - } - - fillHeight = pgeo.height - this.marginTop - this.marginBottom - 2 * this.border; - fillWidth = pgeo.width - this.marginLeft - this.marginRight - 2 * this.border; - - // Handles swimlane start size - if (this.graph.isSwimlane(parent)) - { - // Uses computed style to get latest - var style = this.graph.getCellStyle(parent); - var start = mxUtils.getNumber(style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE); - var horz = mxUtils.getValue(style, mxConstants.STYLE_HORIZONTAL, true) == 1; - - if (pgeo != null) - { - if (horz) - { - start = Math.min(start, pgeo.height); - } - else - { - start = Math.min(start, pgeo.width); - } - } - - if (horz) - { - fillHeight -= start; - y += start; - } - else - { - fillWidth -= start; - x += start; - } - } - - var childCount = model.getChildCount(parent); - var rows = this.rows; - var cols = this.columns; - var cellCount = rows * cols; - - //if auto-add without parent-resize, then each cell size in the table depends on how many columns/rows - if (!this.resizeParent && (this.autoAddCol || this.autoAddRow) && childCount > cellCount) - { - var actualChildCount = 0; - //get actual child count (movable and not ignored) - for (var i = 0; i < childCount; i++) - { - var child = model.getChildAt(parent, i); - - if (!this.isVertexIgnored(child) && this.isVertexMovable(child)) - { - actualChildCount++; - } - } - - if (actualChildCount > cellCount) - { - if (this.autoAddRow) - { - rows = Math.ceil(actualChildCount / cols); - } - else - { - cols = Math.ceil(actualChildCount / rows); - } - } - } - - var cellWidth = [], cellHeight = []; - fillWidth -= this.border * (cols - 1); - fillHeight -= this.border * (rows - 1); - - //Calc each cell width/height in the table - if (this.resizeParent && this.autoAddCol && !this.autoAddRow) - { - cellWidth = this.colWidths && this.colWidths.split? this.colWidths.split(',') : [(this.colWidths || 100)]; - - var w = parseFloat(cellWidth[0]) || 100; - - for (var i = 0; i < cols; i++) - { - cellWidth[i] = this.equalColumns? w : (parseFloat(cellWidth[i]) || w); - } - } - else - { - if (this.equalColumns || this.colPercentages == null) - { - var w = fillWidth / cols; - - for (var i = 0; i < cols; i++) - { - cellWidth.push(w); - } - } - else - { - //TODO handle incorrect configurations - var ratios = this.colPercentages.split(','); - - for (var i = 0; i < cols; i++) - { - cellWidth.push((fillWidth * parseInt(ratios[i]) / 100) || 100); - } - } - } - - if (this.resizeParent && (this.autoAddRow || !this.autoAddCol)) - { - cellHeight = this.rowHeights && this.rowHeights.split? this.rowHeights.split(',') : [(this.rowHeights || 50)]; - - var h = parseFloat(cellHeight[0]) || 50; - - for (var i = 0; i < rows; i++) - { - cellHeight[i] = this.equalRows? h : (parseFloat(cellHeight[i]) || h); - } - } - else - { - if (this.equalRows || this.rowPercentages == null) - { - var h = fillHeight / rows; - - for (var i = 0; i < rows; i++) - { - cellHeight.push(h); - } - } - else - { - //TODO handle incorrect configurations - var ratios = this.rowPercentages.split(','); - - for (var i = 0; i < rows; i++) - { - cellHeight.push((fillHeight * parseInt(ratios[i]) / 100) || 50); - } - } - } - - return {cellHeight: cellHeight, cellWidth: cellWidth, - cols: cols, rows: rows, x: x, y: y, - fillHeight: fillHeight, fillWidth: fillWidth}; - } - - return null; -}; - -/** - * Function: execute - * - * Implements . - * - * Only children where returns false are taken into - * account. - */ -mxTableLayout.prototype.execute = function(parent) -{ - var dims = this.calcDims(parent); - - if (parent != null && dims != null) - { - var pgeo = this.getParentSize(parent); - var model = this.graph.getModel(); - var childCount = model.getChildCount(parent); - var x = dims.x, y = dims.y; - - model.beginUpdate(); - try - { - var rowIndex = 0, colIndex = 0; - var tableWidth = 0, tableHeight = 0; - //save the initial value of x - var x0 = x, y0 = y; - - //children are filled row by row - for (var i = 0; i < childCount; i++) - { - var child = model.getChildAt(parent, i); - - if (!this.isVertexIgnored(child) && this.isVertexMovable(child)) - { - var geo = model.getGeometry(child); - - if (geo != null) - { - geo = geo.clone(); - - geo.x = x; - geo.y = y; - - if (this.fill) - { - geo.height = dims.cellHeight[rowIndex]; - geo.width = dims.cellWidth[colIndex]; - } - - this.setChildGeometry(child, geo); - - if (this.autoAddRow || !this.autoAddCol) - { - if (colIndex + 1 == dims.cols) - { - tableWidth = x + dims.cellWidth[colIndex]; - x = x0; - y += dims.cellHeight[rowIndex] + this.border; - colIndex = 0; - rowIndex = (rowIndex + 1) % dims.rows; - } - else - { - x += dims.cellWidth[colIndex] + this.border; - colIndex++; - } - } - else - { - if (rowIndex + 1 == dims.rows) - { - tableHeight = y + dims.cellHeight[rowIndex]; - y = y0; - x += dims.cellWidth[colIndex] + this.border; - rowIndex = 0; - colIndex = (colIndex + 1) % dims.cols; - } - else - { - y += dims.cellHeight[rowIndex] + this.border; - rowIndex++; - } - } - } - } - } - - if (this.resizeParent && !this.graph.isCellCollapsed(parent)) - { - var pgeo2 = pgeo.clone(); - - pgeo2.width = (tableWidth? tableWidth + this.border : (rowIndex > 0? x + dims.cellWidth[colIndex] + this.border : x)) + this.marginRight; - pgeo2.height = (tableHeight? tableHeight + this.border: (colIndex > 0? y + dims.cellHeight[rowIndex] + this.border : y)) + this.marginBottom; - - if (pgeo.x != pgeo2.x || pgeo.y != pgeo2.y || - pgeo.width != pgeo2.width || pgeo.height != pgeo2.height) - { - model.setGeometry(parent, pgeo2); - } - } - } - finally - { - model.endUpdate(); - } - } -}; - -function mxTableLayoutHandle(index, isCol, state, layoutDims) -{ - this.index = index; - this.isCol = isCol; - this.bounds = new mxRectangle(0, 0, isCol? 2 : state.width, isCol? state.height : 2); - this.dims = layoutDims; - var cursor = isCol? 'col-resize' : 'row-resize'; - - mxHandle.call(this, state, cursor); -}; - -mxUtils.extend(mxTableLayoutHandle, mxHandle); - -mxTableLayoutHandle.prototype.color = '#00FF00'; -mxTableLayoutHandle.prototype.MIN_COL_W = 10; -mxTableLayoutHandle.prototype.MIN_ROW_H = 10; - -mxTableLayoutHandle.prototype.createShape = function(html) -{ - return new mxRectangleShape(this.bounds, this.color, this.color); -}; - -/** - * Function: redraw - * - * Renders the shape for this handle. - */ -mxTableLayoutHandle.prototype.redraw = function() -{ - if (this.shape != null && this.state.shape != null) - { - var pt = this.getPosition(this.state.getPaintBounds()); - - if (pt != null) - { - var alpha = mxUtils.toRadians(this.getTotalRotation()); - pt = this.rotatePoint(this.flipPoint(pt), alpha); - - var scale = this.graph.view.scale; - var tr = this.graph.view.translate; - this.shape.bounds.x = Math.floor((pt.x + tr.x) * scale - this.shape.bounds.width / 2); - this.shape.bounds.y = Math.floor((pt.y + tr.y) * scale - this.shape.bounds.height / 2); - this.shape.bounds.width = this.isCol? 2 : this.state.width; - this.shape.bounds.height = this.isCol? this.state.height : 2; - this.shape.rotation = this.getTotalRotation(); - - // Needed to force update of text bounds - this.shape.redraw(); - } - } -}; - -mxTableLayoutHandle.prototype.getPosition = function(bounds) -{ - var sizes = this.isCol? this.dims.cellWidth : this.dims.cellHeight; - var pos = this.isCol? this.dims.x : this.dims.y; - - for (var i = 0; i <= this.index; i++) - { - pos += sizes[i]; - } - - this.x = this.isCol? bounds.x + pos : bounds.getCenterX(); - this.y = this.isCol? bounds.getCenterY() : bounds.y + pos; - - return new mxPoint(this.x, this.y); -}; - -mxTableLayoutHandle.prototype.setPosition = function(bounds, pt) -{ - this.state.style['resizeParent'] = '0'; - var anotherRedraw = []; - - if (this.isCol) - { - if (this.origCellWidth == null) - { - this.origCellWidth = this.dims.cellWidth.slice(); - } - - this.state.style['equalColumns'] = '0'; - var oldColW = this.dims.cellWidth[this.index]; - var newColW = oldColW + pt.x - this.x; - - if (newColW < this.MIN_COL_W) - { - this.dims.cellWidth[this.index] = this.MIN_COL_W; - var addedW = oldColW - this.MIN_COL_W; - newColW = Math.abs(newColW - this.MIN_COL_W); - var i = this.index - 1; - - while (i >= 0 && newColW > 0) - { - if (newColW < this.dims.cellWidth[i] - this.MIN_COL_W) - { - this.dims.cellWidth[i] -= newColW; - addedW += newColW; - newColW = 0; - } - else - { - var diff = this.dims.cellWidth[i] - this.MIN_COL_W; - newColW -= diff; - addedW += diff; - this.dims.cellWidth[i] = this.MIN_COL_W; - } - - anotherRedraw.push(i); - i--; - } - - this.dims.cellWidth[this.index + 1] += addedW; - } - else if (this.dims.cellWidth[this.index + 1] < (newColW - oldColW + this.MIN_COL_W)) - { - var addedW = this.dims.cellWidth[this.index + 1] - this.MIN_COL_W; - this.dims.cellWidth[this.index + 1] = this.MIN_COL_W; - var neededW = newColW - oldColW; - var i = this.index + 2; - - while (i < this.dims.cols && neededW > 0) - { - if (neededW < this.dims.cellWidth[i] - this.MIN_COL_W) - { - this.dims.cellWidth[i] -= neededW; - addedW += neededW; - neededW = 0; - } - else - { - var diff = this.dims.cellWidth[i] - this.MIN_COL_W; - neededW -= diff; - addedW += diff; - this.dims.cellWidth[i] = this.MIN_COL_W; - } - - anotherRedraw.push(i - 1); - i++; - } - - this.dims.cellWidth[this.index] += addedW; - } - else - { - if (newColW > oldColW) - { - var diff = newColW - oldColW; - var addAll = false; - var i; - - //check other cols if we already resized them - for (i = 0; i < this.index && diff > 0; i++) - { - var cDiff = this.origCellWidth[i] - this.dims.cellWidth[i]; - - if (cDiff != 0) - { - cDiff = Math.min(diff, cDiff); - diff -= cDiff; - this.dims.cellWidth[i] += cDiff; - anotherRedraw.push(i); - addAll = true; - } - } - - for (; i < this.index && addAll; i++) - { - anotherRedraw.push(i); - } - - this.dims.cellWidth[this.index] += diff; - this.dims.cellWidth[this.index + 1] -= (newColW - oldColW); - } - else - { - var diff = oldColW - newColW; - var addAll = false; - var i; - - //check other cols if we already resized them - for (i = this.dims.cols - 2; i >= this.index && diff > 0; i--) - { - var cDiff = this.origCellWidth[i + 1] - this.dims.cellWidth[i + 1]; - - if (cDiff != 0) - { - cDiff = Math.min(diff, cDiff); - diff -= cDiff; - this.dims.cellWidth[i + 1] += cDiff; - anotherRedraw.push(i); // FIXME this.index can be redrawn twice - addAll = true; - } - } - - for (; i > this.index && addAll; i--) - { - anotherRedraw.push(i); - } - - this.dims.cellWidth[this.index] = newColW; - this.dims.cellWidth[this.index + 1] += diff; - } - } - console.log(this.dims.cellWidth) - var perc = []; - - for (var i = 0; i < this.dims.cols; i++) - { - perc.push((this.dims.cellWidth[i] / this.dims.fillWidth) * 100); - } - - this.state.style['colPercentages'] = perc.join(','); - } - else - { - if (this.origCellHeight == null) - { - this.origCellHeight = this.dims.cellHeight.slice(); - } - - this.state.style['equalRows'] = '0'; - var oldRowH = this.dims.cellHeight[this.index]; - var newRowH = oldRowH + pt.y - this.y; - - if (newRowH < this.MIN_ROW_H) - { - this.dims.cellHeight[this.index] = this.MIN_ROW_H; - var addedH = oldRowH - this.MIN_ROW_H; - newRowH = Math.abs(newRowH - this.MIN_ROW_H); - var i = this.index - 1; - - while (i >= 0 && newRowH > 0) - { - if (newRowH < this.dims.cellHeight[i] - this.MIN_ROW_H) - { - this.dims.cellHeight[i] -= newRowH; - addedH += newRowH; - newRowH = 0; - } - else - { - var diff = this.dims.cellHeight[i] - this.MIN_ROW_H; - newRowH -= diff; - addedH += diff; - this.dims.cellHeight[i] = this.MIN_ROW_H; - } - - anotherRedraw.push(i); - i--; - } - - this.dims.cellHeight[this.index + 1] += addedH; - } - else if (this.dims.cellHeight[this.index + 1] < (newRowH - oldRowH + this.MIN_ROW_H)) - { - var addedH = this.dims.cellHeight[this.index + 1] - this.MIN_ROW_H; - this.dims.cellHeight[this.index + 1] = this.MIN_ROW_H; - var neededH = newRowH - oldRowH; - var i = this.index + 2; - - while (i < this.dims.rows && neededH > 0) - { - if (neededH < this.dims.cellHeight[i] - this.MIN_ROW_H) - { - this.dims.cellHeight[i] -= neededH; - addedH += neededH; - neededH = 0; - } - else - { - var diff = this.dims.cellHeight[i] - this.MIN_ROW_H; - neededH -= diff; - addedH += diff; - this.dims.cellHeight[i] = this.MIN_ROW_H; - } - - anotherRedraw.push(i - 1); - i++; - } - - this.dims.cellHeight[this.index] += addedH; - } - else - { - if (newRowH > oldRowH) - { - var diff = newRowH - oldRowH; - var addAll = false; - var i; - - //check other cols if we already resized them - for (i = 0; i < this.index && diff > 0; i++) - { - var cDiff = this.origCellHeight[i] - this.dims.cellHeight[i]; - - if (cDiff != 0) - { - cDiff = Math.min(diff, cDiff); - diff -= cDiff; - this.dims.cellHeight[i] += cDiff; - anotherRedraw.push(i); - addAll = true; - } - } - - for (; i < this.index && addAll; i++) - { - anotherRedraw.push(i); - } - - this.dims.cellHeight[this.index] += diff; - this.dims.cellHeight[this.index + 1] -= (newRowH - oldRowH); - } - else - { - var diff = oldRowH - newRowH; - var addAll = false; - var i; - - //check other cols if we already resized them - for (i = this.dims.rows - 2; i >= this.index && diff > 0; i--) - { - var cDiff = this.origCellHeight[i + 1] - this.dims.cellHeight[i + 1]; - - if (cDiff != 0) - { - cDiff = Math.min(diff, cDiff); - diff -= cDiff; - this.dims.cellHeight[i + 1] += cDiff; - anotherRedraw.push(i); // FIXME this.index can be redrawn twice - addAll = true; - } - } - - for (; i > this.index && addAll; i--) - { - anotherRedraw.push(i); - } - - this.dims.cellHeight[this.index] = newRowH; - this.dims.cellHeight[this.index + 1] += diff; - } - } - - var perc = []; - - for (var i = 0; i < this.dims.rows; i++) - { - perc.push((this.dims.cellHeight[i] / this.dims.fillHeight) * 100); - } - - this.state.style['rowPercentages'] = perc.join(','); - } - - var handlers = this.isCol? this.dims.colHandlers : this.dims.rowHandlers; - - for (var i = 0; i < anotherRedraw.length; i++) - { - handlers[anotherRedraw[i]].redraw(); - } -}; - -mxTableLayoutHandle.prototype.execute = function() -{ - this.copyStyle('resizeParent'); - - if (this.isCol) - { - this.origCellWidth = null; - this.copyStyle('equalColumns'); - this.copyStyle('colPercentages'); - } - else - { - this.origCellHeight = null; - this.copyStyle('equalRows'); - this.copyStyle('rowPercentages'); - } -} - -mxTableLayoutHandle.prototype.ignoreGrid = true; - -//Based on its index, create two handlers per col/row which resize it and set the layout parameters - -mxTableLayout.prototype.origCreateCustomHandles = mxVertexHandler.prototype.createCustomHandles; - -mxVertexHandler.prototype.createCustomHandles = function() -{ - var rowHandlers = [], colHandlers = []; - var origHandlers = mxTableLayout.prototype.origCreateCustomHandles.apply(this, arguments); - - var cell = this.state.cell; - var layout = this.graph.layoutManager.getLayout(cell); - - if (layout instanceof mxTableLayout) - { - if (origHandlers == null) - { - origHandlers = []; - } - - var dims = layout.calcDims(this.state.cell); - dims.rowHandlers = rowHandlers; - dims.colHandlers = colHandlers; - - for (var i = 0; i < dims.rows - 1; i++) - { - var rowH = new mxTableLayoutHandle(i, false, this.state, dims); - origHandlers.push(rowH); - rowHandlers.push(rowH); - } - - for (var i = 0; i < dims.cols - 1; i++) - { - var colH = new mxTableLayoutHandle(i, true, this.state, dims); - origHandlers.push(colH); - colHandlers.push(colH); - } - } - - return origHandlers; -}; \ No newline at end of file diff --git a/src/main/webapp/js/diagramly/ruler/mxRuler.js b/src/main/webapp/js/diagramly/ruler/mxRuler.js deleted file mode 100644 index 26959bdd..00000000 --- a/src/main/webapp/js/diagramly/ruler/mxRuler.js +++ /dev/null @@ -1,359 +0,0 @@ -/** - * Copyright (c) 2017, CTI LOGIC - * Copyright (c) 2006-2017, JGraph Ltd - * Copyright (c) 2006-2017, Gaudenz Alder - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -var mxRuler = function(graph, container, isVertical) -{ - var ruler = this; - var canvas = document.createElement("canvas"); - //initial sizing which is corrected by the graph size event - canvas.width = container.offsetWidth; - canvas.height = container.offsetHeight; - container.style.overflow = 'hidden'; - canvas.style.position = "relative"; - container.appendChild(canvas); - //Disable alpha to improve performance as we don't need it - var ctx = canvas.getContext("2d"/*, {alpha: false}*/); - this.graph = graph; - this.container = container; - this.canvas = canvas; - - var drawLine = function (x1, y1, x2, y2, text) - { - //remove all fractions - x1 = Math.round(x1); y1 = Math.round(y1); x2 = Math.round(x2); y2 = Math.round(y2); - //adding the 0.5 is necessary to prevent anti-aliasing from making lines thicker! - ctx.moveTo(x1 + 0.5, y1 + 0.5); - ctx.lineTo(x2 + 0.5, y2 + 0.5); - ctx.stroke(); - - if (text) - { - if (isVertical) - { - var x = x1; - var y = y1 - 3; - var metric = ctx.measureText(text); - - ctx.save(); - - // We want to find the center of the text (or whatever point you want) and rotate about it - var tx = x + (metric.width / 2) + 8; - var ty = y + 5; - - // Translate to near the center to rotate about the center - ctx.translate(tx, ty); - // Then rotate... - ctx.rotate(-Math.PI / 2); - // Then translate back to draw in the right place! - ctx.translate(-tx, -ty); - ctx.fillText(text, x, y); - ctx.restore(); - } - else - { - ctx.fillText(text, isVertical? x1 : x1 + 3, isVertical? y1 - 3 : y1 + 9); - } - } - }; - - var drawRuler = function(forceErase) - { - //The area is automatically cleared when the canvas size is changed - if (forceErase) ctx.clearRect(0, 0, canvas.width, canvas.height); - - ctx.beginPath(); - ctx.lineWidth = 0.1; - ctx.strokeStyle = "#BBBBBB"; - ctx.font = "9px Arial"; - ctx.fillStyle = '#BBBBBB'; - - var scale = graph.view.scale; - var bgPages = graph.view.getBackgroundPageBounds(); - var t = graph.view.translate; - var bounds = graph.view.getGraphBounds(); - - var rStart = (isVertical? bgPages.y : bgPages.x); - - //handle negative pages - if (isVertical) - { - var y = ((bounds.y) / scale - t.y); - - if (y <= -1) - { - rStart += Math.ceil(Math.abs(y) / graph.pageFormat.height) * graph.pageFormat.height * scale; - } - } - else - { - var x = ((bounds.x) / scale - t.x); - - if (x <= -1) - { - rStart += Math.ceil(Math.abs(x) / graph.pageFormat.width) * graph.pageFormat.width * scale; - } - } - - rStart += isVertical? (graph.container.offsetTop - ruler.container.offsetTop) : (graph.container.offsetLeft - ruler.container.offsetLeft); - - var tickStep, tickSize, len; - - switch(ruler.unit) - { - case ruler.PIXELS: - len = 10; - tickStep = 10; - tickSize = [25,5,5,5,5,10,5,5,5,5]; - break; - case ruler.CENTIMETER: - len = 10; - tickStep = ruler.pPerCM/len; - tickSize = [25,5,5,5,5,10,5,5,5,5]; - break; - case ruler.INCHES: - if (scale <=0.5 || scale >=4) - len = 8; - else - len = 16; - - tickStep = ruler.pPerInch/len; - tickSize = [25,5,8,5,12,5,8,5,15,5,8,5,12,5,8,5]; - break; - } - - var step = tickStep; - - if (ruler.unit != ruler.INCHES || (scale > 2 || scale < 0.25)) - step = scale>= 1 ? (tickStep / Math.floor(scale)) : Math.floor(10 / scale / 10) * 10; - - for (var i = rStart % (step * scale); i <= (isVertical? canvas.height : canvas.width); i += step * scale) - { - var current = Math.round((i - rStart) / scale / step); - var text = null; - - if (current % len == 0) - { - text = ruler.formatText(Math.round(current * step)) + ""; - } - - if (isVertical) - { - drawLine(30 - tickSize[Math.abs(current) % len], i, 30, i, text); - } - else - { - drawLine(i, 30 - tickSize[Math.abs(current) % len], i, 30, text); - } - } - }; - - var sizeListener = function() - { - var div = graph.container; - var newW = isVertical? container.offsetWidth : div.scrollWidth; - var newH = isVertical? div.scrollHeight : container.offsetHeight; - - if (newW != canvas.width || newH != canvas.height) - { - canvas.width = newW; - canvas.height = newH; - drawRuler(); - } - }; - - this.drawRuler = drawRuler; - - var efficientSizeListener = debounce(sizeListener, 10); - this.sizeListener = efficientSizeListener; - - //Size event is called upon scaling so we may not need it - //graph.view.addListener(mxEvent.SCALE, efficientSizeListener); - graph.addListener(mxEvent.SIZE, efficientSizeListener); - graph.container.addEventListener("scroll", function() { - if (isVertical) - { - canvas.style.top = -graph.container.scrollTop + "px"; - } - else - { - canvas.style.left = -graph.container.scrollLeft + "px"; - } - }); - - function debounce(func, wait, immediate) - { - var timeout; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - if (!immediate) func.apply(context, args); - }; - var callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) func.apply(context, args); - }; - }; - - function createHint() - { - var hint = document.createElement('div'); - hint.className = 'geHint'; - hint.style.whiteSpace = 'nowrap'; - hint.style.position = 'absolute'; - - return hint; - }; - - graph.graphHandler.updateHint = function(me) - { - if (this.shape != null) - { - if (this.hint == null) - { - this.hint = createHint(); - this.graph.container.appendChild(this.hint); - } - - var t = this.graph.view.translate; - var s = this.graph.view.scale; - var x = this.roundLength((this.bounds.x + this.currentDx) / s - t.x); - var y = this.roundLength((this.bounds.y + this.currentDy) / s - t.y); - - this.hint.innerHTML = ruler.formatText(x) + ', ' + ruler.formatText(y); //Math.round(current * step) - - this.hint.style.left = (this.shape.bounds.x + Math.round((this.shape.bounds.width - this.hint.clientWidth) / 2)) + 'px'; - this.hint.style.top = (this.shape.bounds.y + this.shape.bounds.height + 12) + 'px'; - } - }; - - mxVertexHandler.prototype.updateHint = function(me) - { - if (this.index != mxEvent.LABEL_HANDLE) - { - if (this.hint == null) - { - this.hint = createHint(); - this.state.view.graph.container.appendChild(this.hint); - } - - if (this.index == mxEvent.ROTATION_HANDLE) - { - this.hint.innerHTML = this.currentAlpha + '°'; - } - else - { - var s = this.state.view.scale; - this.hint.innerHTML = ruler.formatText(this.roundLength(this.bounds.width / s)) + ' x ' + ruler.formatText(this.roundLength(this.bounds.height / s)); - } - - var rot = (this.currentAlpha != null) ? this.currentAlpha : this.state.style[mxConstants.STYLE_ROTATION] || '0'; - var bb = mxUtils.getBoundingBox(this.bounds, rot); - - if (bb == null) - { - bb = this.bounds; - } - - this.hint.style.left = bb.x + Math.round((bb.width - this.hint.clientWidth) / 2) + 'px'; - this.hint.style.top = (bb.y + bb.height + 12) + 'px'; - } - }; - - mxEdgeHandler.prototype.updateHint = function(me, point) - { - if (this.hint == null) - { - this.hint = createHint(); - this.state.view.graph.container.appendChild(this.hint); - } - - var t = this.graph.view.translate; - var s = this.graph.view.scale; - var x = this.roundLength(point.x / s - t.x); - var y = this.roundLength(point.y / s - t.y); - - this.hint.innerHTML = ruler.formatText(x) + ', ' + ruler.formatText(y); - this.hint.style.visibility = 'visible'; - - if (this.isSource || this.isTarget) - { - if (this.constraintHandler.currentConstraint != null && - this.constraintHandler.currentFocus != null) - { - var pt = this.constraintHandler.currentConstraint.point; - this.hint.innerHTML = '[' + Math.round(pt.x * 100) + '%, '+ Math.round(pt.y * 100) + '%]'; - } - else if (this.marker.hasValidState()) - { - this.hint.style.visibility = 'hidden'; - } - } - - this.hint.style.left = Math.round(me.getGraphX() - this.hint.clientWidth / 2) + 'px'; - this.hint.style.top = (Math.max(me.getGraphY(), point.y) + this.state.view.graph.gridSize) + 'px'; - - if (this.hideEdgeHintThread != null) - { - window.clearTimeout(this.hideEdgeHintThread); - } - - this.hideEdgeHintThread = window.setTimeout(mxUtils.bind(this, function() - { - if (this.hint != null) - { - this.hint.style.visibility = 'hidden'; - } - }), 500); - }; -}; - -mxRuler.prototype.PIXELS = 1; -mxRuler.prototype.CENTIMETER = 2; -mxRuler.prototype.INCHES = 3; - -mxRuler.prototype.pPerCM = 39.37; -mxRuler.prototype.pPerInch = 100; - -mxRuler.prototype.unit = mxRuler.prototype.PIXELS; - -mxRuler.prototype.setUnit = function(unit) { - this.unit = unit; -}; - -mxRuler.prototype.formatText = function(pixels) { - switch(this.unit) { - case this.PIXELS: - return pixels; - case this.CENTIMETER: - return (pixels / this.pPerCM).toFixed(2); - case this.INCHES: - return (pixels / this.pPerInch).toFixed(2); - } -}; - -//TODO fix this (put correct listeners) -mxRuler.prototype.destroy = function() { - this.graph.view.removeListener(this.drawRuler); - this.graph.removeListener(this.sizeListener); - this.graph.container.removeEventListener("scroll", this.drawRuler); - this.graph.view.removeListener(mxEvent.SCALE, this.drawRuler); - if (this.container != null && this.canvas != null) this.container.removeChild(this.canvas); -}; \ No newline at end of file diff --git a/src/main/webapp/js/mxgraph/Actions.js b/src/main/webapp/js/mxgraph/Actions.js deleted file mode 100644 index 9edfdb3f..00000000 --- a/src/main/webapp/js/mxgraph/Actions.js +++ /dev/null @@ -1,1597 +0,0 @@ -/** - * Copyright (c) 2006-2020, JGraph Ltd - * Copyright (c) 2006-2020, draw.io AG - * - * Constructs the actions object for the given UI. - */ -function Actions(editorUi) -{ - this.editorUi = editorUi; - this.actions = new Object(); - this.init(); -}; - -/** - * Adds the default actions. - */ -Actions.prototype.init = function() -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - var isGraphEnabled = function() - { - return Action.prototype.isEnabled.apply(this, arguments) && graph.isEnabled(); - }; - - // File actions - this.addAction('new...', function() { graph.openLink(ui.getUrl()); }); - this.addAction('open...', function() - { - window.openNew = true; - window.openKey = 'open'; - - ui.openFile(); - }); - this.addAction('import...', function() - { - window.openNew = false; - window.openKey = 'import'; - - // Closes dialog after open - window.openFile = new OpenFile(mxUtils.bind(this, function() - { - ui.hideDialog(); - })); - - window.openFile.setConsumer(mxUtils.bind(this, function(xml, filename) - { - try - { - var doc = mxUtils.parseXml(xml); - editor.graph.setSelectionCells(editor.graph.importGraphModel(doc.documentElement)); - } - catch (e) - { - mxUtils.alert(mxResources.get('invalidOrMissingFile') + ': ' + e.message); - } - })); - - // Removes openFile if dialog is closed - ui.showDialog(new OpenDialog(this).container, 320, 220, true, true, function() - { - window.openFile = null; - }); - }).isEnabled = isGraphEnabled; - this.addAction('save', function() { ui.saveFile(false); }, null, null, Editor.ctrlKey + '+S').isEnabled = isGraphEnabled; - this.addAction('saveAs...', function() { ui.saveFile(true); }, null, null, Editor.ctrlKey + '+Shift+S').isEnabled = isGraphEnabled; - this.addAction('export...', function() { ui.showDialog(new ExportDialog(ui).container, 300, 296, true, true); }); - this.addAction('editDiagram...', function() - { - var dlg = new EditDiagramDialog(ui); - ui.showDialog(dlg.container, 620, 420, true, false); - dlg.init(); - }); - this.addAction('pageSetup...', function() { ui.showDialog(new PageSetupDialog(ui).container, 320, 220, true, true); }).isEnabled = isGraphEnabled; - this.addAction('print...', function() { ui.showDialog(new PrintDialog(ui).container, 300, 180, true, true); }, null, 'sprite-print', Editor.ctrlKey + '+P'); - this.addAction('preview', function() { mxUtils.show(graph, null, 10, 10); }); - - // Edit actions - this.addAction('undo', function() { ui.undo(); }, null, 'sprite-undo', Editor.ctrlKey + '+Z'); - this.addAction('redo', function() { ui.redo(); }, null, 'sprite-redo', (!mxClient.IS_WIN) ? Editor.ctrlKey + '+Shift+Z' : Editor.ctrlKey + '+Y'); - this.addAction('cut', function() { mxClipboard.cut(graph); }, null, 'sprite-cut', Editor.ctrlKey + '+X'); - this.addAction('copy', function() - { - try - { - mxClipboard.copy(graph); - } - catch (e) - { - ui.handleError(e); - } - }, null, 'sprite-copy', Editor.ctrlKey + '+C'); - this.addAction('paste', function() - { - if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent())) - { - mxClipboard.paste(graph); - } - }, false, 'sprite-paste', Editor.ctrlKey + '+V'); - this.addAction('pasteHere', function(evt) - { - if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent())) - { - graph.getModel().beginUpdate(); - try - { - var cells = mxClipboard.paste(graph); - - if (cells != null) - { - var includeEdges = true; - - for (var i = 0; i < cells.length && includeEdges; i++) - { - includeEdges = includeEdges && graph.model.isEdge(cells[i]); - } - - var t = graph.view.translate; - var s = graph.view.scale; - var dx = t.x; - var dy = t.y; - var bb = null; - - if (cells.length == 1 && includeEdges) - { - var geo = graph.getCellGeometry(cells[0]); - - if (geo != null) - { - bb = geo.getTerminalPoint(true); - } - } - - bb = (bb != null) ? bb : graph.getBoundingBoxFromGeometry(cells, includeEdges); - - if (bb != null) - { - var x = Math.round(graph.snap(graph.popupMenuHandler.triggerX / s - dx)); - var y = Math.round(graph.snap(graph.popupMenuHandler.triggerY / s - dy)); - - graph.cellsMoved(cells, x - bb.x, y - bb.y); - } - } - } - finally - { - graph.getModel().endUpdate(); - } - } - }); - - this.addAction('copySize', function(evt) - { - var cell = graph.getSelectionCell(); - - if (graph.isEnabled() && cell != null && graph.getModel().isVertex(cell)) - { - var geo = graph.getCellGeometry(cell); - - if (geo != null) - { - ui.copiedSize = new mxRectangle(geo.x, geo.y, geo.width, geo.height); - } - } - }, null, null, 'Alt+Shift+X'); - - this.addAction('pasteSize', function(evt) - { - if (graph.isEnabled() && !graph.isSelectionEmpty() && ui.copiedSize != null) - { - graph.getModel().beginUpdate(); - - try - { - var cells = graph.getSelectionCells(); - - for (var i = 0; i < cells.length; i++) - { - if (graph.getModel().isVertex(cells[i])) - { - var geo = graph.getCellGeometry(cells[i]); - - if (geo != null) - { - geo = geo.clone(); - geo.width = ui.copiedSize.width; - geo.height = ui.copiedSize.height; - - graph.getModel().setGeometry(cells[i], geo); - } - } - } - } - finally - { - graph.getModel().endUpdate(); - } - } - }, null, null, 'Alt+Shift+V'); - - function deleteCells(includeEdges) - { - // Cancels interactive operations - graph.escape(); - var select = graph.deleteCells(graph.getDeletableCells(graph.getSelectionCells()), includeEdges); - - if (select != null) - { - graph.setSelectionCells(select); - } - }; - - this.addAction('delete', function(evt) - { - deleteCells(evt != null && mxEvent.isControlDown(evt)); - }, null, null, 'Delete'); - this.addAction('deleteAll', function() - { - if (!graph.isSelectionEmpty()) - { - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - - for (var i = 0; i < cells.length; i++) - { - graph.cellLabelChanged(cells[i], ''); - } - } - finally - { - graph.getModel().endUpdate(); - } - } - }); - this.addAction('deleteLabels', function() - { - if (!graph.isSelectionEmpty()) - { - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - - for (var i = 0; i < cells.length; i++) - { - graph.cellLabelChanged(cells[i], ''); - } - } - finally - { - graph.getModel().endUpdate(); - } - } - }, null, null, Editor.ctrlKey + '+Delete'); - this.addAction('duplicate', function() - { - try - { - graph.setSelectionCells(graph.duplicateCells()); - graph.scrollCellToVisible(graph.getSelectionCell()); - } - catch (e) - { - ui.handleError(e); - } - }, null, null, Editor.ctrlKey + '+D'); - this.put('turn', new Action(mxResources.get('turn') + ' / ' + mxResources.get('reverse'), function(evt) - { - graph.turnShapes(graph.getSelectionCells(), (evt != null) ? mxEvent.isShiftDown(evt) : false); - }, null, null, Editor.ctrlKey + '+R')); - this.addAction('selectVertices', function() { graph.selectVertices(null, true); }, null, null, Editor.ctrlKey + '+Shift+I'); - this.addAction('selectEdges', function() { graph.selectEdges(); }, null, null, Editor.ctrlKey + '+Shift+E'); - this.addAction('selectAll', function() { graph.selectAll(null, true); }, null, null, Editor.ctrlKey + '+A'); - this.addAction('selectNone', function() { graph.clearSelection(); }, null, null, Editor.ctrlKey + '+Shift+A'); - this.addAction('lockUnlock', function() - { - if (!graph.isSelectionEmpty()) - { - graph.getModel().beginUpdate(); - try - { - var defaultValue = graph.isCellMovable(graph.getSelectionCell()) ? 1 : 0; - graph.toggleCellStyles(mxConstants.STYLE_MOVABLE, defaultValue); - graph.toggleCellStyles(mxConstants.STYLE_RESIZABLE, defaultValue); - graph.toggleCellStyles(mxConstants.STYLE_ROTATABLE, defaultValue); - graph.toggleCellStyles(mxConstants.STYLE_DELETABLE, defaultValue); - graph.toggleCellStyles(mxConstants.STYLE_EDITABLE, defaultValue); - graph.toggleCellStyles('connectable', defaultValue); - } - finally - { - graph.getModel().endUpdate(); - } - } - }, null, null, Editor.ctrlKey + '+L'); - - // Navigation actions - this.addAction('home', function() { graph.home(); }, null, null, 'Shift+Home'); - this.addAction('exitGroup', function() { graph.exitGroup(); }, null, null, Editor.ctrlKey + '+Shift+Home'); - this.addAction('enterGroup', function() { graph.enterGroup(); }, null, null, Editor.ctrlKey + '+Shift+End'); - this.addAction('collapse', function() { graph.foldCells(true); }, null, null, Editor.ctrlKey + '+Home'); - this.addAction('expand', function() { graph.foldCells(false); }, null, null, Editor.ctrlKey + '+End'); - - // Arrange actions - this.addAction('toFront', function() { graph.orderCells(false); }, null, null, Editor.ctrlKey + '+Shift+F'); - this.addAction('toBack', function() { graph.orderCells(true); }, null, null, Editor.ctrlKey + '+Shift+B'); - this.addAction('group', function() - { - if (graph.isEnabled()) - { - var cells = mxUtils.sortCells(graph.getSelectionCells(), true); - - if (cells.length == 1 && !graph.isTable(cells[0]) && !graph.isTableRow(cells[0])) - { - graph.setCellStyles('container', '1'); - } - else - { - cells = graph.getCellsForGroup(cells); - - if (cells.length > 1) - { - graph.setSelectionCell(graph.groupCells(null, 0, cells)); - } - } - } - }, null, null, Editor.ctrlKey + '+G'); - this.addAction('ungroup', function() - { - if (graph.isEnabled()) - { - var cells = graph.getSelectionCells(); - - graph.model.beginUpdate(); - try - { - var temp = graph.ungroupCells(); - - // Clears container flag for remaining cells - if (cells != null) - { - for (var i = 0; i < cells.length; i++) - { - if (graph.model.contains(cells[i])) - { - if (graph.model.getChildCount(cells[i]) == 0 && - graph.model.isVertex(cells[i])) - { - graph.setCellStyles('container', '0', [cells[i]]); - } - - temp.push(cells[i]); - } - } - } - } - finally - { - graph.model.endUpdate(); - } - - graph.setSelectionCells(temp); - } - }, null, null, Editor.ctrlKey + '+Shift+U'); - this.addAction('removeFromGroup', function() - { - if (graph.isEnabled()) - { - var cells = graph.getSelectionCells(); - - // Removes table rows and cells - if (cells != null) - { - var temp = []; - - for (var i = 0; i < cells.length; i++) - { - if (!graph.isTableRow(cells[i]) && - !graph.isTableCell(cells[i])) - { - temp.push(cells[i]); - } - } - - graph.removeCellsFromParent(temp); - } - } - }); - // Adds action - this.addAction('edit', function() - { - if (graph.isEnabled()) - { - graph.startEditingAtCell(); - } - }, null, null, 'F2/Enter'); - this.addAction('editData...', function() - { - var cell = graph.getSelectionCell() || graph.getModel().getRoot(); - ui.showDataDialog(cell); - }, null, null, Editor.ctrlKey + '+M'); - this.addAction('editTooltip...', function() - { - if (graph.isEnabled() && !graph.isSelectionEmpty()) - { - var cell = graph.getSelectionCell(); - var tooltip = ''; - - if (mxUtils.isNode(cell.value)) - { - var tmp = null; - - if (Graph.translateDiagram && Graph.diagramLanguage != null && - cell.value.hasAttribute('tooltip_' + Graph.diagramLanguage)) - { - tmp = cell.value.getAttribute('tooltip_' + Graph.diagramLanguage); - } - - if (tmp == null) - { - tmp = cell.value.getAttribute('tooltip'); - } - - if (tmp != null) - { - tooltip = tmp; - } - } - - var dlg = new TextareaDialog(ui, mxResources.get('editTooltip') + ':', tooltip, function(newValue) - { - graph.setTooltipForCell(cell, newValue); - }); - ui.showDialog(dlg.container, 320, 200, true, true); - dlg.init(); - } - }, null, null, 'Alt+Shift+T'); - this.addAction('openLink', function() - { - var link = graph.getLinkForCell(graph.getSelectionCell()); - - if (link != null) - { - graph.openLink(link); - } - }); - this.addAction('editLink...', function() - { - if (graph.isEnabled() && !graph.isSelectionEmpty()) - { - var cell = graph.getSelectionCell(); - var value = graph.getLinkForCell(cell) || ''; - - ui.showLinkDialog(value, mxResources.get('apply'), function(link) - { - link = mxUtils.trim(link); - graph.setLinkForCell(cell, (link.length > 0) ? link : null); - }); - } - }, null, null, 'Alt+Shift+L'); - this.put('insertImage', new Action(mxResources.get('image') + '...', function() - { - if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent())) - { - graph.clearSelection(); - ui.actions.get('image').funct(); - } - })).isEnabled = isGraphEnabled; - this.put('insertLink', new Action(mxResources.get('link') + '...', function() - { - if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent())) - { - ui.showLinkDialog('', mxResources.get('insert'), function(link, docs) - { - link = mxUtils.trim(link); - - if (link.length > 0) - { - var icon = null; - var title = graph.getLinkTitle(link); - - if (docs != null && docs.length > 0) - { - icon = docs[0].iconUrl; - title = docs[0].name || docs[0].type; - title = title.charAt(0).toUpperCase() + title.substring(1); - - if (title.length > 30) - { - title = title.substring(0, 30) + '...'; - } - } - - var linkCell = new mxCell(title, new mxGeometry(0, 0, 100, 40), - 'fontColor=#0000EE;fontStyle=4;rounded=1;overflow=hidden;' + ((icon != null) ? - 'shape=label;imageWidth=16;imageHeight=16;spacingLeft=26;align=left;image=' + icon : - 'spacing=10;')); - linkCell.vertex = true; - - var pt = graph.getCenterInsertPoint(graph.getBoundingBoxFromGeometry([linkCell], true)); - linkCell.geometry.x = pt.x; - linkCell.geometry.y = pt.y; - - graph.setLinkForCell(linkCell, link); - graph.cellSizeUpdated(linkCell, true); - - graph.getModel().beginUpdate(); - try - { - linkCell = graph.addCell(linkCell); - graph.fireEvent(new mxEventObject('cellsInserted', 'cells', [linkCell])); - } - finally - { - graph.getModel().endUpdate(); - } - - graph.setSelectionCell(linkCell); - graph.scrollCellToVisible(graph.getSelectionCell()); - } - }); - } - })).isEnabled = isGraphEnabled; - this.addAction('link...', mxUtils.bind(this, function() - { - if (graph.isEnabled()) - { - if (graph.cellEditor.isContentEditing()) - { - var elt = graph.getSelectedElement(); - var link = graph.getParentByName(elt, 'A', graph.cellEditor.textarea); - var oldValue = ''; - - // Workaround for FF returning the outermost selected element after double - // click on a DOM hierarchy with a link inside (but not as topmost element) - if (link == null && elt != null && elt.getElementsByTagName != null) - { - // Finds all links in the selected DOM and uses the link - // where the selection text matches its text content - var links = elt.getElementsByTagName('a'); - - for (var i = 0; i < links.length && link == null; i++) - { - if (links[i].textContent == elt.textContent) - { - link = links[i]; - } - } - } - - if (link != null && link.nodeName == 'A') - { - oldValue = link.getAttribute('href') || ''; - graph.selectNode(link); - } - - var selState = graph.cellEditor.saveSelection(); - - ui.showLinkDialog(oldValue, mxResources.get('apply'), mxUtils.bind(this, function(value) - { - graph.cellEditor.restoreSelection(selState); - - if (value != null) - { - graph.insertLink(value); - } - })); - } - else if (graph.isSelectionEmpty()) - { - this.get('insertLink').funct(); - } - else - { - this.get('editLink').funct(); - } - } - })).isEnabled = isGraphEnabled; - this.addAction('autosize', function() - { - var cells = graph.getSelectionCells(); - - if (cells != null) - { - graph.getModel().beginUpdate(); - try - { - for (var i = 0; i < cells.length; i++) - { - var cell = cells[i]; - - if (graph.getModel().getChildCount(cell)) - { - graph.updateGroupBounds([cell], 20); - } - else - { - var state = graph.view.getState(cell); - var geo = graph.getCellGeometry(cell); - - if (graph.getModel().isVertex(cell) && state != null && state.text != null && - geo != null && graph.isWrapping(cell)) - { - geo = geo.clone(); - geo.height = state.text.boundingBox.height / graph.view.scale; - graph.getModel().setGeometry(cell, geo); - } - else - { - graph.updateCellSize(cell); - } - } - } - } - finally - { - graph.getModel().endUpdate(); - } - } - }, null, null, Editor.ctrlKey + '+Shift+Y'); - this.addAction('formattedText', function() - { - var refState = graph.getView().getState(graph.getSelectionCell()); - - if (refState != null) - { - graph.stopEditing(); - var value = (refState.style['html'] == '1') ? null : '1'; - - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - - for (var i = 0; i < cells.length; i++) - { - state = graph.getView().getState(cells[i]); - - if (state != null) - { - var html = mxUtils.getValue(state.style, 'html', '0'); - - if (html == '1' && value == null) - { - var label = graph.convertValueToString(state.cell); - - if (mxUtils.getValue(state.style, 'nl2Br', '1') != '0') - { - // Removes newlines from HTML and converts breaks to newlines - // to match the HTML output in plain text - label = label.replace(/\n/g, '').replace(//g, '\n'); - } - - // Removes HTML tags - var temp = document.createElement('div'); - temp.innerHTML = graph.sanitizeHtml(label); - label = mxUtils.extractTextWithWhitespace(temp.childNodes); - - graph.cellLabelChanged(state.cell, label); - graph.setCellStyles('html', value, [cells[i]]); - } - else if (html == '0' && value == '1') - { - // Converts HTML tags to text - var label = mxUtils.htmlEntities(graph.convertValueToString(state.cell), false); - - if (mxUtils.getValue(state.style, 'nl2Br', '1') != '0') - { - // Converts newlines in plain text to breaks in HTML - // to match the plain text output - label = label.replace(/\n/g, '
'); - } - - graph.cellLabelChanged(state.cell, graph.sanitizeHtml(label)); - graph.setCellStyles('html', value, [cells[i]]); - } - } - } - - ui.fireEvent(new mxEventObject('styleChanged', 'keys', ['html'], - 'values', [(value != null) ? value : '0'], 'cells', cells)); - } - finally - { - graph.getModel().endUpdate(); - } - } - }); - this.addAction('wordWrap', function() - { - var state = graph.getView().getState(graph.getSelectionCell()); - var value = 'wrap'; - - graph.stopEditing(); - - if (state != null && state.style[mxConstants.STYLE_WHITE_SPACE] == 'wrap') - { - value = null; - } - - graph.setCellStyles(mxConstants.STYLE_WHITE_SPACE, value); - }); - this.addAction('rotation', function() - { - var value = '0'; - var state = graph.getView().getState(graph.getSelectionCell()); - - if (state != null) - { - value = state.style[mxConstants.STYLE_ROTATION] || value; - } - - var dlg = new FilenameDialog(ui, value, mxResources.get('apply'), function(newValue) - { - if (newValue != null && newValue.length > 0) - { - graph.setCellStyles(mxConstants.STYLE_ROTATION, newValue); - } - }, mxResources.get('enterValue') + ' (' + mxResources.get('rotation') + ' 0-360)'); - - ui.showDialog(dlg.container, 375, 80, true, true); - dlg.init(); - }); - // View actions - this.addAction('resetView', function() - { - graph.zoomTo(1); - ui.resetScrollbars(); - }, null, null, 'Home'); - this.addAction('zoomIn', function(evt) - { - if (graph.isFastZoomEnabled()) - { - graph.lazyZoom(true, true, ui.buttonZoomDelay); - } - else - { - graph.zoomIn(); - } - }, null, null, Editor.ctrlKey + ' + (Numpad) / Alt+Mousewheel'); - this.addAction('zoomOut', function(evt) - { - if (graph.isFastZoomEnabled()) - { - graph.lazyZoom(false, true, ui.buttonZoomDelay); - } - else - { - graph.zoomOut(); - } - }, null, null, Editor.ctrlKey + ' - (Numpad) / Alt+Mousewheel'); - this.addAction('fitWindow', function() - { - var bounds = (graph.isSelectionEmpty()) ? graph.getGraphBounds() : - graph.getBoundingBox(graph.getSelectionCells()) - var t = graph.view.translate; - var s = graph.view.scale; - - bounds.x = bounds.x / s - t.x; - bounds.y = bounds.y / s - t.y; - bounds.width /= s; - bounds.height /= s; - - if (graph.backgroundImage != null) - { - bounds.add(new mxRectangle(0, 0, graph.backgroundImage.width, graph.backgroundImage.height)); - } - - if (bounds.width == 0 || bounds.height == 0) - { - graph.zoomTo(1); - ui.resetScrollbars(); - } - else - { - graph.fitWindow(bounds); - } - }, null, null, Editor.ctrlKey + '+Shift+H'); - this.addAction('fitPage', mxUtils.bind(this, function() - { - if (!graph.pageVisible) - { - this.get('pageView').funct(); - } - - var fmt = graph.pageFormat; - var ps = graph.pageScale; - var cw = graph.container.clientWidth - 10; - var ch = graph.container.clientHeight - 10; - var scale = Math.floor(20 * Math.min(cw / fmt.width / ps, ch / fmt.height / ps)) / 20; - graph.zoomTo(scale); - - if (mxUtils.hasScrollbars(graph.container)) - { - var pad = graph.getPagePadding(); - graph.container.scrollTop = pad.y * graph.view.scale - 1; - graph.container.scrollLeft = Math.min(pad.x * graph.view.scale, (graph.container.scrollWidth - graph.container.clientWidth) / 2) - 1; - } - }), null, null, Editor.ctrlKey + '+J'); - this.addAction('fitTwoPages', mxUtils.bind(this, function() - { - if (!graph.pageVisible) - { - this.get('pageView').funct(); - } - - var fmt = graph.pageFormat; - var ps = graph.pageScale; - var cw = graph.container.clientWidth - 10; - var ch = graph.container.clientHeight - 10; - - var scale = Math.floor(20 * Math.min(cw / (2 * fmt.width) / ps, ch / fmt.height / ps)) / 20; - graph.zoomTo(scale); - - if (mxUtils.hasScrollbars(graph.container)) - { - var pad = graph.getPagePadding(); - graph.container.scrollTop = Math.min(pad.y, (graph.container.scrollHeight - graph.container.clientHeight) / 2); - graph.container.scrollLeft = Math.min(pad.x, (graph.container.scrollWidth - graph.container.clientWidth) / 2); - } - }), null, null, Editor.ctrlKey + '+Shift+J'); - this.addAction('fitPageWidth', mxUtils.bind(this, function() - { - if (!graph.pageVisible) - { - this.get('pageView').funct(); - } - - var fmt = graph.pageFormat; - var ps = graph.pageScale; - var cw = graph.container.clientWidth - 10; - - var scale = Math.floor(20 * cw / fmt.width / ps) / 20; - graph.zoomTo(scale); - - if (mxUtils.hasScrollbars(graph.container)) - { - var pad = graph.getPagePadding(); - graph.container.scrollLeft = Math.min(pad.x * graph.view.scale, - (graph.container.scrollWidth - graph.container.clientWidth) / 2); - } - })); - this.put('customZoom', new Action(mxResources.get('custom') + '...', mxUtils.bind(this, function() - { - var dlg = new FilenameDialog(this.editorUi, parseInt(graph.getView().getScale() * 100), mxResources.get('apply'), mxUtils.bind(this, function(newValue) - { - var val = parseInt(newValue); - - if (!isNaN(val) && val > 0) - { - graph.zoomTo(val / 100); - } - }), mxResources.get('zoom') + ' (%)'); - this.editorUi.showDialog(dlg.container, 300, 80, true, true); - dlg.init(); - }), null, null, Editor.ctrlKey + '+0')); - this.addAction('pageScale...', mxUtils.bind(this, function() - { - var dlg = new FilenameDialog(this.editorUi, parseInt(graph.pageScale * 100), mxResources.get('apply'), mxUtils.bind(this, function(newValue) - { - var val = parseInt(newValue); - - if (!isNaN(val) && val > 0) - { - var change = new ChangePageSetup(ui, null, null, null, val / 100); - change.ignoreColor = true; - change.ignoreImage = true; - - graph.model.execute(change); - } - }), mxResources.get('pageScale') + ' (%)'); - this.editorUi.showDialog(dlg.container, 300, 80, true, true); - dlg.init(); - })); - - // Option actions - var action = null; - action = this.addAction('grid', function() - { - graph.setGridEnabled(!graph.isGridEnabled()); - ui.fireEvent(new mxEventObject('gridEnabledChanged')); - }, null, null, Editor.ctrlKey + '+Shift+G'); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.isGridEnabled(); }); - action.setEnabled(false); - - action = this.addAction('guides', function() - { - graph.graphHandler.guidesEnabled = !graph.graphHandler.guidesEnabled; - ui.fireEvent(new mxEventObject('guidesEnabledChanged')); - }); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.graphHandler.guidesEnabled; }); - action.setEnabled(false); - - action = this.addAction('tooltips', function() - { - graph.tooltipHandler.setEnabled(!graph.tooltipHandler.isEnabled()); - ui.fireEvent(new mxEventObject('tooltipsEnabledChanged')); - }); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.tooltipHandler.isEnabled(); }); - - action = this.addAction('collapseExpand', function() - { - var change = new ChangePageSetup(ui); - change.ignoreColor = true; - change.ignoreImage = true; - change.foldingEnabled = !graph.foldingEnabled; - - graph.model.execute(change); - }); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.foldingEnabled; }); - action.isEnabled = isGraphEnabled; - action = this.addAction('scrollbars', function() - { - ui.setScrollbars(!ui.hasScrollbars()); - }); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.scrollbars; }); - action = this.addAction('pageView', mxUtils.bind(this, function() - { - ui.setPageVisible(!graph.pageVisible); - })); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.pageVisible; }); - action = this.addAction('connectionArrows', function() - { - graph.connectionArrowsEnabled = !graph.connectionArrowsEnabled; - ui.fireEvent(new mxEventObject('connectionArrowsChanged')); - }, null, null, 'Alt+Shift+A'); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.connectionArrowsEnabled; }); - action = this.addAction('connectionPoints', function() - { - graph.setConnectable(!graph.connectionHandler.isEnabled()); - ui.fireEvent(new mxEventObject('connectionPointsChanged')); - }, null, null, 'Alt+Shift+P'); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.connectionHandler.isEnabled(); }); - action = this.addAction('copyConnect', function() - { - graph.connectionHandler.setCreateTarget(!graph.connectionHandler.isCreateTarget()); - ui.fireEvent(new mxEventObject('copyConnectChanged')); - }); - action.setToggleAction(true); - action.setSelectedCallback(function() { return graph.connectionHandler.isCreateTarget(); }); - action.isEnabled = isGraphEnabled; - action = this.addAction('autosave', function() - { - ui.editor.setAutosave(!ui.editor.autosave); - }); - action.setToggleAction(true); - action.setSelectedCallback(function() { return ui.editor.autosave; }); - action.isEnabled = isGraphEnabled; - action.visible = false; - - // Help actions - this.addAction('help', function() - { - var ext = ''; - - if (mxResources.isLanguageSupported(mxClient.language)) - { - ext = '_' + mxClient.language; - } - - graph.openLink(RESOURCES_PATH + '/help' + ext + '.html'); - }); - - var showingAbout = false; - - this.put('about', new Action(mxResources.get('about') + ' Graph Editor...', function() - { - if (!showingAbout) - { - ui.showDialog(new AboutDialog(ui).container, 320, 280, true, true, function() - { - showingAbout = false; - }); - - showingAbout = true; - } - })); - - // Font style actions - var toggleFontStyle = mxUtils.bind(this, function(key, style, fn, shortcut) - { - return this.addAction(key, function() - { - if (fn != null && graph.cellEditor.isContentEditing()) - { - fn(); - } - else - { - graph.stopEditing(false); - - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - graph.toggleCellStyleFlags(mxConstants.STYLE_FONTSTYLE, style, cells); - - // Removes bold and italic tags and CSS styles inside labels - if ((style & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD) - { - graph.updateLabelElements(graph.getSelectionCells(), function(elt) - { - elt.style.fontWeight = null; - - if (elt.nodeName == 'B') - { - graph.replaceElement(elt); - } - }); - } - else if ((style & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC) - { - graph.updateLabelElements(graph.getSelectionCells(), function(elt) - { - elt.style.fontStyle = null; - - if (elt.nodeName == 'I') - { - graph.replaceElement(elt); - } - }); - } - else if ((style & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE) - { - graph.updateLabelElements(graph.getSelectionCells(), function(elt) - { - elt.style.textDecoration = null; - - if (elt.nodeName == 'U') - { - graph.replaceElement(elt); - } - }); - } - - for (var i = 0; i < cells.length; i++) - { - if (graph.model.getChildCount(cells[i]) == 0) - { - graph.autoSizeCell(cells[i], false); - } - } - } - finally - { - graph.getModel().endUpdate(); - } - } - }, null, null, shortcut); - }); - - toggleFontStyle('bold', mxConstants.FONT_BOLD, function() { document.execCommand('bold', false, null); }, Editor.ctrlKey + '+B'); - toggleFontStyle('italic', mxConstants.FONT_ITALIC, function() { document.execCommand('italic', false, null); }, Editor.ctrlKey + '+I'); - toggleFontStyle('underline', mxConstants.FONT_UNDERLINE, function() { document.execCommand('underline', false, null); }, Editor.ctrlKey + '+U'); - - // Color actions - this.addAction('fontColor...', function() { ui.menus.pickColor(mxConstants.STYLE_FONTCOLOR, 'forecolor', '000000'); }); - this.addAction('strokeColor...', function() { ui.menus.pickColor(mxConstants.STYLE_STROKECOLOR); }); - this.addAction('fillColor...', function() { ui.menus.pickColor(mxConstants.STYLE_FILLCOLOR); }); - this.addAction('gradientColor...', function() { ui.menus.pickColor(mxConstants.STYLE_GRADIENTCOLOR); }); - this.addAction('backgroundColor...', function() { ui.menus.pickColor(mxConstants.STYLE_LABEL_BACKGROUNDCOLOR, 'backcolor'); }); - this.addAction('borderColor...', function() { ui.menus.pickColor(mxConstants.STYLE_LABEL_BORDERCOLOR); }); - - // Format actions - this.addAction('vertical', function() { ui.menus.toggleStyle(mxConstants.STYLE_HORIZONTAL, true); }); - this.addAction('shadow', function() { ui.menus.toggleStyle(mxConstants.STYLE_SHADOW); }); - this.addAction('solid', function() - { - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles(mxConstants.STYLE_DASHED, null); - graph.setCellStyles(mxConstants.STYLE_DASH_PATTERN, null); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], - 'values', [null, null], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - }); - this.addAction('dashed', function() - { - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles(mxConstants.STYLE_DASHED, '1'); - graph.setCellStyles(mxConstants.STYLE_DASH_PATTERN, null); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], - 'values', ['1', null], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - }); - this.addAction('dotted', function() - { - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles(mxConstants.STYLE_DASHED, '1'); - graph.setCellStyles(mxConstants.STYLE_DASH_PATTERN, '1 4'); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], - 'values', ['1', '1 4'], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - }); - this.addAction('sharp', function() - { - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles(mxConstants.STYLE_ROUNDED, '0'); - graph.setCellStyles(mxConstants.STYLE_CURVED, '0'); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_ROUNDED, mxConstants.STYLE_CURVED], - 'values', ['0', '0'], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - }); - this.addAction('rounded', function() - { - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles(mxConstants.STYLE_ROUNDED, '1'); - graph.setCellStyles(mxConstants.STYLE_CURVED, '0'); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_ROUNDED, mxConstants.STYLE_CURVED], - 'values', ['1', '0'], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - }); - this.addAction('toggleRounded', function() - { - if (!graph.isSelectionEmpty() && graph.isEnabled()) - { - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - var style = graph.getCurrentCellStyle(cells[0]); - var value = (mxUtils.getValue(style, mxConstants.STYLE_ROUNDED, '0') == '1') ? '0' : '1'; - - graph.setCellStyles(mxConstants.STYLE_ROUNDED, value); - graph.setCellStyles(mxConstants.STYLE_CURVED, null); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_ROUNDED, mxConstants.STYLE_CURVED], - 'values', [value, '0'], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - } - }); - this.addAction('curved', function() - { - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles(mxConstants.STYLE_ROUNDED, '0'); - graph.setCellStyles(mxConstants.STYLE_CURVED, '1'); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_ROUNDED, mxConstants.STYLE_CURVED], - 'values', ['0', '1'], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - }); - this.addAction('collapsible', function() - { - var state = graph.view.getState(graph.getSelectionCell()); - var value = '1'; - - if (state != null && graph.getFoldingImage(state) != null) - { - value = '0'; - } - - graph.setCellStyles('collapsible', value); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', ['collapsible'], - 'values', [value], 'cells', graph.getSelectionCells())); - }); - this.addAction('editStyle...', mxUtils.bind(this, function() - { - var cells = graph.getSelectionCells(); - - if (cells != null && cells.length > 0) - { - var model = graph.getModel(); - - var dlg = new TextareaDialog(this.editorUi, mxResources.get('editStyle') + ':', - model.getStyle(cells[0]) || '', function(newValue) - { - if (newValue != null) - { - graph.setCellStyle(mxUtils.trim(newValue), cells); - } - }, null, null, 400, 220); - this.editorUi.showDialog(dlg.container, 420, 300, true, true); - dlg.init(); - } - }), null, null, Editor.ctrlKey + '+E'); - this.addAction('setAsDefaultStyle', function() - { - if (graph.isEnabled() && !graph.isSelectionEmpty()) - { - ui.setDefaultStyle(graph.getSelectionCell()); - } - }, null, null, Editor.ctrlKey + '+Shift+D'); - this.addAction('clearDefaultStyle', function() - { - if (graph.isEnabled()) - { - ui.clearDefaultStyle(); - } - }, null, null, Editor.ctrlKey + '+Shift+R'); - this.addAction('addWaypoint', function() - { - var cell = graph.getSelectionCell(); - - if (cell != null && graph.getModel().isEdge(cell)) - { - var handler = editor.graph.selectionCellsHandler.getHandler(cell); - - if (handler instanceof mxEdgeHandler) - { - var t = graph.view.translate; - var s = graph.view.scale; - var dx = t.x; - var dy = t.y; - - var parent = graph.getModel().getParent(cell); - var pgeo = graph.getCellGeometry(parent); - - while (graph.getModel().isVertex(parent) && pgeo != null) - { - dx += pgeo.x; - dy += pgeo.y; - - parent = graph.getModel().getParent(parent); - pgeo = graph.getCellGeometry(parent); - } - - var x = Math.round(graph.snap(graph.popupMenuHandler.triggerX / s - dx)); - var y = Math.round(graph.snap(graph.popupMenuHandler.triggerY / s - dy)); - - handler.addPointAt(handler.state, x, y); - } - } - }); - this.addAction('removeWaypoint', function() - { - // TODO: Action should run with "this" set to action - var rmWaypointAction = ui.actions.get('removeWaypoint'); - - if (rmWaypointAction.handler != null) - { - // NOTE: Popupevent handled and action updated in Menus.createPopupMenu - rmWaypointAction.handler.removePoint(rmWaypointAction.handler.state, rmWaypointAction.index); - } - }); - this.addAction('clearWaypoints', function() - { - var cells = graph.getSelectionCells(); - - if (cells != null) - { - cells = graph.addAllEdges(cells); - - graph.getModel().beginUpdate(); - try - { - for (var i = 0; i < cells.length; i++) - { - var cell = cells[i]; - - if (graph.getModel().isEdge(cell)) - { - var geo = graph.getCellGeometry(cell); - - if (geo != null) - { - geo = geo.clone(); - geo.points = null; - graph.getModel().setGeometry(cell, geo); - } - } - } - } - finally - { - graph.getModel().endUpdate(); - } - } - }, null, null, 'Alt+Shift+C'); - action = this.addAction('subscript', mxUtils.bind(this, function() - { - if (graph.cellEditor.isContentEditing()) - { - document.execCommand('subscript', false, null); - } - }), null, null, Editor.ctrlKey + '+,'); - action = this.addAction('superscript', mxUtils.bind(this, function() - { - if (graph.cellEditor.isContentEditing()) - { - document.execCommand('superscript', false, null); - } - }), null, null, Editor.ctrlKey + '+.'); - action = this.addAction('indent', mxUtils.bind(this, function() - { - // NOTE: Alt+Tab for outdent implemented via special code in - // keyHandler.getFunction in EditorUi.js. Ctrl+Tab is reserved. - if (graph.cellEditor.isContentEditing()) - { - document.execCommand('indent', false, null); - } - }), null, null, 'Shift+Tab'); - this.addAction('image...', function() - { - if (graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent())) - { - var title = mxResources.get('image') + ' (' + mxResources.get('url') + '):'; - var state = graph.getView().getState(graph.getSelectionCell()); - var value = ''; - - if (state != null) - { - value = state.style[mxConstants.STYLE_IMAGE] || value; - } - - var selectionState = graph.cellEditor.saveSelection(); - - ui.showImageDialog(title, value, function(newValue, w, h) - { - // Inserts image into HTML text - if (graph.cellEditor.isContentEditing()) - { - graph.cellEditor.restoreSelection(selectionState); - graph.insertImage(newValue, w, h); - } - else - { - var cells = graph.getSelectionCells(); - - if (newValue != null && (newValue.length > 0 || cells.length > 0)) - { - var select = null; - - graph.getModel().beginUpdate(); - try - { - // Inserts new cell if no cell is selected - if (cells.length == 0) - { - cells = [graph.insertVertex(graph.getDefaultParent(), null, '', 0, 0, w, h, - 'shape=image;imageAspect=0;aspect=fixed;verticalLabelPosition=bottom;verticalAlign=top;')]; - var pt = graph.getCenterInsertPoint(graph.getBoundingBoxFromGeometry(cells, true)); - cells[0].geometry.x = pt.x; - cells[0].geometry.y = pt.y; - - select = cells; - graph.fireEvent(new mxEventObject('cellsInserted', 'cells', select)); - } - - graph.setCellStyles(mxConstants.STYLE_IMAGE, (newValue.length > 0) ? newValue : null, cells); - - // Sets shape only if not already shape with image (label or image) - var style = graph.getCurrentCellStyle(cells[0]); - - if (style[mxConstants.STYLE_SHAPE] != 'image' && style[mxConstants.STYLE_SHAPE] != 'label') - { - graph.setCellStyles(mxConstants.STYLE_SHAPE, 'image', cells); - } - else if (newValue.length == 0) - { - graph.setCellStyles(mxConstants.STYLE_SHAPE, null, cells); - } - - if (graph.getSelectionCount() == 1) - { - if (w != null && h != null) - { - var cell = cells[0]; - var geo = graph.getModel().getGeometry(cell); - - if (geo != null) - { - geo = geo.clone(); - geo.width = w; - geo.height = h; - graph.getModel().setGeometry(cell, geo); - } - } - } - } - finally - { - graph.getModel().endUpdate(); - } - - if (select != null) - { - graph.setSelectionCells(select); - graph.scrollCellToVisible(select[0]); - } - } - } - }, graph.cellEditor.isContentEditing(), !graph.cellEditor.isContentEditing()); - } - }).isEnabled = isGraphEnabled; - action = this.addAction('layers', mxUtils.bind(this, function() - { - if (this.layersWindow == null) - { - // LATER: Check outline window for initial placement - this.layersWindow = new LayersWindow(ui, document.body.offsetWidth - 280, 120, 220, 196); - this.layersWindow.window.addListener('show', function() - { - ui.fireEvent(new mxEventObject('layers')); - }); - this.layersWindow.window.addListener('hide', function() - { - ui.fireEvent(new mxEventObject('layers')); - }); - this.layersWindow.window.setVisible(true); - ui.fireEvent(new mxEventObject('layers')); - - this.layersWindow.init(); - } - else - { - this.layersWindow.window.setVisible(!this.layersWindow.window.isVisible()); - } - }), null, null, Editor.ctrlKey + '+Shift+L'); - action.setToggleAction(true); - action.setSelectedCallback(mxUtils.bind(this, function() { return this.layersWindow != null && this.layersWindow.window.isVisible(); })); - action = this.addAction('formatPanel', mxUtils.bind(this, function() - { - ui.toggleFormatPanel(); - }), null, null, Editor.ctrlKey + '+Shift+P'); - action.setToggleAction(true); - action.setSelectedCallback(mxUtils.bind(this, function() { return ui.formatWidth > 0; })); - action = this.addAction('outline', mxUtils.bind(this, function() - { - if (this.outlineWindow == null) - { - // LATER: Check layers window for initial placement - this.outlineWindow = new OutlineWindow(ui, document.body.offsetWidth - 260, 100, 180, 180); - this.outlineWindow.window.addListener('show', function() - { - ui.fireEvent(new mxEventObject('outline')); - }); - this.outlineWindow.window.addListener('hide', function() - { - ui.fireEvent(new mxEventObject('outline')); - }); - this.outlineWindow.window.setVisible(true); - ui.fireEvent(new mxEventObject('outline')); - } - else - { - this.outlineWindow.window.setVisible(!this.outlineWindow.window.isVisible()); - } - }), null, null, Editor.ctrlKey + '+Shift+O'); - - action.setToggleAction(true); - action.setSelectedCallback(mxUtils.bind(this, function() { return this.outlineWindow != null && this.outlineWindow.window.isVisible(); })); -}; - -/** - * Registers the given action under the given name. - */ -Actions.prototype.addAction = function(key, funct, enabled, iconCls, shortcut) -{ - var title; - - if (key.substring(key.length - 3) == '...') - { - key = key.substring(0, key.length - 3); - title = mxResources.get(key) + '...'; - } - else - { - title = mxResources.get(key); - } - - return this.put(key, new Action(title, funct, enabled, iconCls, shortcut)); -}; - -/** - * Registers the given action under the given name. - */ -Actions.prototype.put = function(name, action) -{ - this.actions[name] = action; - - return action; -}; - -/** - * Returns the action for the given name or null if no such action exists. - */ -Actions.prototype.get = function(name) -{ - return this.actions[name]; -}; - -/** - * Constructs a new action for the given parameters. - */ -function Action(label, funct, enabled, iconCls, shortcut) -{ - mxEventSource.call(this); - this.label = label; - this.funct = this.createFunction(funct); - this.enabled = (enabled != null) ? enabled : true; - this.iconCls = iconCls; - this.shortcut = shortcut; - this.visible = true; -}; - -// Action inherits from mxEventSource -mxUtils.extend(Action, mxEventSource); - -/** - * Sets the enabled state of the action and fires a stateChanged event. - */ -Action.prototype.createFunction = function(funct) -{ - return funct; -}; - -/** - * Sets the enabled state of the action and fires a stateChanged event. - */ -Action.prototype.setEnabled = function(value) -{ - if (this.enabled != value) - { - this.enabled = value; - this.fireEvent(new mxEventObject('stateChanged')); - } -}; - -/** - * Sets the enabled state of the action and fires a stateChanged event. - */ -Action.prototype.isEnabled = function() -{ - return this.enabled; -}; - -/** - * Sets the enabled state of the action and fires a stateChanged event. - */ -Action.prototype.setToggleAction = function(value) -{ - this.toggleAction = value; -}; - -/** - * Sets the enabled state of the action and fires a stateChanged event. - */ -Action.prototype.setSelectedCallback = function(funct) -{ - this.selectedCallback = funct; -}; - -/** - * Sets the enabled state of the action and fires a stateChanged event. - */ -Action.prototype.isSelected = function() -{ - return this.selectedCallback(); -}; diff --git a/src/main/webapp/js/mxgraph/Dialogs.js b/src/main/webapp/js/mxgraph/Dialogs.js deleted file mode 100644 index 86a75542..00000000 --- a/src/main/webapp/js/mxgraph/Dialogs.js +++ /dev/null @@ -1,2558 +0,0 @@ -/** - * Copyright (c) 2006-2012, JGraph Ltd - */ -/** - * Constructs a new open dialog. - */ -var OpenDialog = function() -{ - var iframe = document.createElement('iframe'); - iframe.style.backgroundColor = 'transparent'; - iframe.allowTransparency = 'true'; - iframe.style.borderStyle = 'none'; - iframe.style.borderWidth = '0px'; - iframe.style.overflow = 'hidden'; - iframe.frameBorder = '0'; - - // Adds padding as a workaround for box model in older IE versions - var dx = (mxClient.IS_VML && (document.documentMode == null || document.documentMode < 8)) ? 20 : 0; - - iframe.setAttribute('width', (((Editor.useLocalStorage) ? 640 : 320) + dx) + 'px'); - iframe.setAttribute('height', (((Editor.useLocalStorage) ? 480 : 220) + dx) + 'px'); - iframe.setAttribute('src', OPEN_FORM); - - this.container = iframe; -}; - -/** - * Constructs a new color dialog. - */ -var ColorDialog = function(editorUi, color, apply, cancelFn) -{ - this.editorUi = editorUi; - - var input = document.createElement('input'); - input.style.marginBottom = '10px'; - input.style.width = '216px'; - - // Required for picker to render in IE - if (mxClient.IS_IE) - { - input.style.marginTop = '10px'; - document.body.appendChild(input); - } - - var applyFunction = (apply != null) ? apply : this.createApplyFunction(); - - function doApply() - { - var color = input.value; - - // Blocks any non-alphabetic chars in colors - if (/(^#?[a-zA-Z0-9]*$)/.test(color)) - { - if (color != 'none' && color.charAt(0) != '#') - { - color = '#' + color; - } - - ColorDialog.addRecentColor((color != 'none') ? color.substring(1) : color, 12); - applyFunction(color); - editorUi.hideDialog(); - } - else - { - editorUi.handleError({message: mxResources.get('invalidInput')}); - } - }; - - this.init = function() - { - if (!mxClient.IS_TOUCH) - { - input.focus(); - } - }; - - var picker = new mxJSColor.color(input); - picker.pickerOnfocus = false; - picker.showPicker(); - - var div = document.createElement('div'); - mxJSColor.picker.box.style.position = 'relative'; - mxJSColor.picker.box.style.width = '230px'; - mxJSColor.picker.box.style.height = '100px'; - mxJSColor.picker.box.style.paddingBottom = '10px'; - div.appendChild(mxJSColor.picker.box); - - var center = document.createElement('center'); - - function createRecentColorTable() - { - var table = addPresets((ColorDialog.recentColors.length == 0) ? ['FFFFFF'] : - ColorDialog.recentColors, 11, 'FFFFFF', true); - table.style.marginBottom = '8px'; - - return table; - }; - - function addPresets(presets, rowLength, defaultColor, addResetOption) - { - rowLength = (rowLength != null) ? rowLength : 12; - var table = document.createElement('table'); - table.style.borderCollapse = 'collapse'; - table.setAttribute('cellspacing', '0'); - table.style.marginBottom = '20px'; - table.style.cellSpacing = '0px'; - var tbody = document.createElement('tbody'); - table.appendChild(tbody); - - var rows = presets.length / rowLength; - - for (var row = 0; row < rows; row++) - { - var tr = document.createElement('tr'); - - for (var i = 0; i < rowLength; i++) - { - (function(clr) - { - var td = document.createElement('td'); - td.style.border = '1px solid black'; - td.style.padding = '0px'; - td.style.width = '16px'; - td.style.height = '16px'; - - if (clr == null) - { - clr = defaultColor; - } - - if (clr == 'none') - { - td.style.background = 'url(\'' + Dialog.prototype.noColorImage + '\')'; - } - else - { - td.style.backgroundColor = '#' + clr; - } - - tr.appendChild(td); - - if (clr != null) - { - td.style.cursor = 'pointer'; - - mxEvent.addListener(td, 'click', function() - { - if (clr == 'none') - { - picker.fromString('ffffff'); - input.value = 'none'; - } - else - { - picker.fromString(clr); - } - }); - - mxEvent.addListener(td, 'dblclick', doApply); - } - })(presets[row * rowLength + i]); - } - - tbody.appendChild(tr); - } - - if (addResetOption) - { - var td = document.createElement('td'); - td.setAttribute('title', mxResources.get('reset')); - td.style.border = '1px solid black'; - td.style.padding = '0px'; - td.style.width = '16px'; - td.style.height = '16px'; - td.style.backgroundImage = 'url(\'' + Dialog.prototype.closeImage + '\')'; - td.style.backgroundPosition = 'center center'; - td.style.backgroundRepeat = 'no-repeat'; - td.style.cursor = 'pointer'; - - tr.appendChild(td); - - mxEvent.addListener(td, 'click', function() - { - ColorDialog.resetRecentColors(); - table.parentNode.replaceChild(createRecentColorTable(), table); - }); - } - - center.appendChild(table); - - return table; - }; - - div.appendChild(input); - mxUtils.br(div); - - // Adds recent colors - createRecentColorTable(); - - // Adds presets - var table = addPresets(this.presetColors); - table.style.marginBottom = '8px'; - table = addPresets(this.defaultColors); - table.style.marginBottom = '16px'; - - div.appendChild(center); - - var buttons = document.createElement('div'); - buttons.style.textAlign = 'right'; - buttons.style.whiteSpace = 'nowrap'; - - var cancelBtn = mxUtils.button(mxResources.get('cancel'), function() - { - editorUi.hideDialog(); - - if (cancelFn != null) - { - cancelFn(); - } - }); - cancelBtn.className = 'geBtn'; - - if (editorUi.editor.cancelFirst) - { - buttons.appendChild(cancelBtn); - } - - var applyBtn = mxUtils.button(mxResources.get('apply'), doApply); - applyBtn.className = 'geBtn gePrimaryBtn'; - buttons.appendChild(applyBtn); - - if (!editorUi.editor.cancelFirst) - { - buttons.appendChild(cancelBtn); - } - - if (color != null) - { - if (color == 'none') - { - picker.fromString('ffffff'); - input.value = 'none'; - } - else - { - picker.fromString(color); - } - } - - div.appendChild(buttons); - this.picker = picker; - this.colorInput = input; - - // LATER: Only fires if input if focused, should always - // fire if this dialog is showing. - mxEvent.addListener(div, 'keydown', function(e) - { - if (e.keyCode == 27) - { - editorUi.hideDialog(); - - if (cancelFn != null) - { - cancelFn(); - } - - mxEvent.consume(e); - } - }); - - this.container = div; -}; - -/** - * Creates function to apply value - */ -ColorDialog.prototype.presetColors = ['E6D0DE', 'CDA2BE', 'B5739D', 'E1D5E7', 'C3ABD0', 'A680B8', 'D4E1F5', 'A9C4EB', '7EA6E0', 'D5E8D4', '9AC7BF', '67AB9F', 'D5E8D4', 'B9E0A5', '97D077', 'FFF2CC', 'FFE599', 'FFD966', 'FFF4C3', 'FFCE9F', 'FFB570', 'F8CECC', 'F19C99', 'EA6B66']; - -/** - * Creates function to apply value - */ -ColorDialog.prototype.defaultColors = ['none', 'FFFFFF', 'E6E6E6', 'CCCCCC', 'B3B3B3', '999999', '808080', '666666', '4D4D4D', '333333', '1A1A1A', '000000', 'FFCCCC', 'FFE6CC', 'FFFFCC', 'E6FFCC', 'CCFFCC', 'CCFFE6', 'CCFFFF', 'CCE5FF', 'CCCCFF', 'E5CCFF', 'FFCCFF', 'FFCCE6', - 'FF9999', 'FFCC99', 'FFFF99', 'CCFF99', '99FF99', '99FFCC', '99FFFF', '99CCFF', '9999FF', 'CC99FF', 'FF99FF', 'FF99CC', 'FF6666', 'FFB366', 'FFFF66', 'B3FF66', '66FF66', '66FFB3', '66FFFF', '66B2FF', '6666FF', 'B266FF', 'FF66FF', 'FF66B3', 'FF3333', 'FF9933', 'FFFF33', - '99FF33', '33FF33', '33FF99', '33FFFF', '3399FF', '3333FF', '9933FF', 'FF33FF', 'FF3399', 'FF0000', 'FF8000', 'FFFF00', '80FF00', '00FF00', '00FF80', '00FFFF', '007FFF', '0000FF', '7F00FF', 'FF00FF', 'FF0080', 'CC0000', 'CC6600', 'CCCC00', '66CC00', '00CC00', '00CC66', - '00CCCC', '0066CC', '0000CC', '6600CC', 'CC00CC', 'CC0066', '990000', '994C00', '999900', '4D9900', '009900', '00994D', '009999', '004C99', '000099', '4C0099', '990099', '99004D', '660000', '663300', '666600', '336600', '006600', '006633', '006666', '003366', '000066', - '330066', '660066', '660033', '330000', '331A00', '333300', '1A3300', '003300', '00331A', '003333', '001933', '000033', '190033', '330033', '33001A']; - -/** - * Creates function to apply value - */ -ColorDialog.prototype.createApplyFunction = function() -{ - return mxUtils.bind(this, function(color) - { - var graph = this.editorUi.editor.graph; - - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles(this.currentColorKey, color); - this.editorUi.fireEvent(new mxEventObject('styleChanged', 'keys', [this.currentColorKey], - 'values', [color], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - }); -}; - -/** - * - */ -ColorDialog.recentColors = []; - -/** - * Adds recent color for later use. - */ -ColorDialog.addRecentColor = function(color, max) -{ - if (color != null) - { - mxUtils.remove(color, ColorDialog.recentColors); - ColorDialog.recentColors.splice(0, 0, color); - - if (ColorDialog.recentColors.length >= max) - { - ColorDialog.recentColors.pop(); - } - } -}; - -/** - * Adds recent color for later use. - */ -ColorDialog.resetRecentColors = function() -{ - ColorDialog.recentColors = []; -}; - -/** - * Constructs a new about dialog. - */ -var AboutDialog = function(editorUi) -{ - var div = document.createElement('div'); - div.setAttribute('align', 'center'); - var h3 = document.createElement('h3'); - mxUtils.write(h3, mxResources.get('about') + ' GraphEditor'); - div.appendChild(h3); - var img = document.createElement('img'); - img.style.border = '0px'; - img.setAttribute('width', '176'); - img.setAttribute('width', '151'); - img.setAttribute('src', IMAGE_PATH + '/logo.png'); - div.appendChild(img); - mxUtils.br(div); - mxUtils.write(div, 'Powered by mxGraph ' + mxClient.VERSION); - mxUtils.br(div); - var link = document.createElement('a'); - link.setAttribute('href', 'http://www.jgraph.com/'); - link.setAttribute('target', '_blank'); - mxUtils.write(link, 'www.jgraph.com'); - div.appendChild(link); - mxUtils.br(div); - mxUtils.br(div); - var closeBtn = mxUtils.button(mxResources.get('close'), function() - { - editorUi.hideDialog(); - }); - closeBtn.className = 'geBtn gePrimaryBtn'; - div.appendChild(closeBtn); - - this.container = div; -}; - -/** - * Constructs a new textarea dialog. - */ -var TextareaDialog = function(editorUi, title, url, fn, cancelFn, cancelTitle, w, h, - addButtons, noHide, noWrap, applyTitle, helpLink, customButtons) -{ - w = (w != null) ? w : 300; - h = (h != null) ? h : 120; - noHide = (noHide != null) ? noHide : false; - var row, td; - - var table = document.createElement('table'); - var tbody = document.createElement('tbody'); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - td.style.width = '100px'; - mxUtils.write(td, title); - - row.appendChild(td); - tbody.appendChild(row); - - row = document.createElement('tr'); - td = document.createElement('td'); - - var nameInput = document.createElement('textarea'); - - if (noWrap) - { - nameInput.setAttribute('wrap', 'off'); - } - - nameInput.setAttribute('spellcheck', 'false'); - nameInput.setAttribute('autocorrect', 'off'); - nameInput.setAttribute('autocomplete', 'off'); - nameInput.setAttribute('autocapitalize', 'off'); - - mxUtils.write(nameInput, url || ''); - nameInput.style.resize = 'none'; - nameInput.style.width = w + 'px'; - nameInput.style.height = h + 'px'; - - this.textarea = nameInput; - - this.init = function() - { - nameInput.focus(); - nameInput.scrollTop = 0; - }; - - td.appendChild(nameInput); - row.appendChild(td); - - tbody.appendChild(row); - - row = document.createElement('tr'); - td = document.createElement('td'); - td.style.paddingTop = '14px'; - td.style.whiteSpace = 'nowrap'; - td.setAttribute('align', 'right'); - - if (helpLink != null) - { - var helpBtn = mxUtils.button(mxResources.get('help'), function() - { - editorUi.editor.graph.openLink(helpLink); - }); - helpBtn.className = 'geBtn'; - - td.appendChild(helpBtn); - } - - if (customButtons != null) - { - for (var i = 0; i < customButtons.length; i++) - { - (function(label, fn) - { - var customBtn = mxUtils.button(label, function(e) - { - fn(e, nameInput); - }); - customBtn.className = 'geBtn'; - - td.appendChild(customBtn); - })(customButtons[i][0], customButtons[i][1]); - } - } - - var cancelBtn = mxUtils.button(cancelTitle || mxResources.get('cancel'), function() - { - editorUi.hideDialog(); - - if (cancelFn != null) - { - cancelFn(); - } - }); - cancelBtn.className = 'geBtn'; - - if (editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - } - - if (addButtons != null) - { - addButtons(td, nameInput); - } - - if (fn != null) - { - var genericBtn = mxUtils.button(applyTitle || mxResources.get('apply'), function() - { - if (!noHide) - { - editorUi.hideDialog(); - } - - fn(nameInput.value); - }); - - genericBtn.className = 'geBtn gePrimaryBtn'; - td.appendChild(genericBtn); - } - - if (!editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - } - - row.appendChild(td); - tbody.appendChild(row); - table.appendChild(tbody); - this.container = table; -}; - -/** - * Constructs a new edit file dialog. - */ -var EditDiagramDialog = function(editorUi) -{ - var div = document.createElement('div'); - div.style.textAlign = 'right'; - var textarea = document.createElement('textarea'); - textarea.setAttribute('wrap', 'off'); - textarea.setAttribute('spellcheck', 'false'); - textarea.setAttribute('autocorrect', 'off'); - textarea.setAttribute('autocomplete', 'off'); - textarea.setAttribute('autocapitalize', 'off'); - textarea.style.overflow = 'auto'; - textarea.style.resize = 'none'; - textarea.style.width = '600px'; - textarea.style.height = '360px'; - textarea.style.marginBottom = '16px'; - - textarea.value = mxUtils.getPrettyXml(editorUi.editor.getGraphXml()); - div.appendChild(textarea); - - this.init = function() - { - textarea.focus(); - }; - - // Enables dropping files - if (Graph.fileSupport) - { - function handleDrop(evt) - { - evt.stopPropagation(); - evt.preventDefault(); - - if (evt.dataTransfer.files.length > 0) - { - var file = evt.dataTransfer.files[0]; - var reader = new FileReader(); - - reader.onload = function(e) - { - textarea.value = e.target.result; - }; - - reader.readAsText(file); - } - else - { - textarea.value = editorUi.extractGraphModelFromEvent(evt); - } - }; - - function handleDragOver(evt) - { - evt.stopPropagation(); - evt.preventDefault(); - }; - - // Setup the dnd listeners. - textarea.addEventListener('dragover', handleDragOver, false); - textarea.addEventListener('drop', handleDrop, false); - } - - var cancelBtn = mxUtils.button(mxResources.get('cancel'), function() - { - editorUi.hideDialog(); - }); - cancelBtn.className = 'geBtn'; - - if (editorUi.editor.cancelFirst) - { - div.appendChild(cancelBtn); - } - - var select = document.createElement('select'); - select.style.width = '180px'; - select.className = 'geBtn'; - - if (editorUi.editor.graph.isEnabled()) - { - var replaceOption = document.createElement('option'); - replaceOption.setAttribute('value', 'replace'); - mxUtils.write(replaceOption, mxResources.get('replaceExistingDrawing')); - select.appendChild(replaceOption); - } - - var newOption = document.createElement('option'); - newOption.setAttribute('value', 'new'); - mxUtils.write(newOption, mxResources.get('openInNewWindow')); - - if (EditDiagramDialog.showNewWindowOption) - { - select.appendChild(newOption); - } - - if (editorUi.editor.graph.isEnabled()) - { - var importOption = document.createElement('option'); - importOption.setAttribute('value', 'import'); - mxUtils.write(importOption, mxResources.get('addToExistingDrawing')); - select.appendChild(importOption); - } - - div.appendChild(select); - - var okBtn = mxUtils.button(mxResources.get('ok'), function() - { - // Removes all illegal control characters before parsing - var data = Graph.zapGremlins(mxUtils.trim(textarea.value)); - var error = null; - - if (select.value == 'new') - { - editorUi.hideDialog(); - editorUi.editor.editAsNew(data); - } - else if (select.value == 'replace') - { - editorUi.editor.graph.model.beginUpdate(); - try - { - editorUi.editor.setGraphXml(mxUtils.parseXml(data).documentElement); - // LATER: Why is hideDialog between begin-/endUpdate faster? - editorUi.hideDialog(); - } - catch (e) - { - error = e; - } - finally - { - editorUi.editor.graph.model.endUpdate(); - } - } - else if (select.value == 'import') - { - editorUi.editor.graph.model.beginUpdate(); - try - { - var doc = mxUtils.parseXml(data); - var model = new mxGraphModel(); - var codec = new mxCodec(doc); - codec.decode(doc.documentElement, model); - - var children = model.getChildren(model.getChildAt(model.getRoot(), 0)); - editorUi.editor.graph.setSelectionCells(editorUi.editor.graph.importCells(children)); - - // LATER: Why is hideDialog between begin-/endUpdate faster? - editorUi.hideDialog(); - } - catch (e) - { - error = e; - } - finally - { - editorUi.editor.graph.model.endUpdate(); - } - } - - if (error != null) - { - mxUtils.alert(error.message); - } - }); - okBtn.className = 'geBtn gePrimaryBtn'; - div.appendChild(okBtn); - - if (!editorUi.editor.cancelFirst) - { - div.appendChild(cancelBtn); - } - - this.container = div; -}; - -/** - * - */ -EditDiagramDialog.showNewWindowOption = true; - -/** - * Constructs a new export dialog. - */ -var ExportDialog = function(editorUi) -{ - var graph = editorUi.editor.graph; - var bounds = graph.getGraphBounds(); - var scale = graph.view.scale; - - var width = Math.ceil(bounds.width / scale); - var height = Math.ceil(bounds.height / scale); - - var row, td; - - var table = document.createElement('table'); - var tbody = document.createElement('tbody'); - table.setAttribute('cellpadding', (mxClient.IS_SF) ? '0' : '2'); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - td.style.width = '100px'; - mxUtils.write(td, mxResources.get('filename') + ':'); - - row.appendChild(td); - - var nameInput = document.createElement('input'); - nameInput.setAttribute('value', editorUi.editor.getOrCreateFilename()); - nameInput.style.width = '180px'; - - td = document.createElement('td'); - td.appendChild(nameInput); - row.appendChild(td); - - tbody.appendChild(row); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - mxUtils.write(td, mxResources.get('format') + ':'); - - row.appendChild(td); - - var imageFormatSelect = document.createElement('select'); - imageFormatSelect.style.width = '180px'; - - var pngOption = document.createElement('option'); - pngOption.setAttribute('value', 'png'); - mxUtils.write(pngOption, mxResources.get('formatPng')); - imageFormatSelect.appendChild(pngOption); - - var gifOption = document.createElement('option'); - - if (ExportDialog.showGifOption) - { - gifOption.setAttribute('value', 'gif'); - mxUtils.write(gifOption, mxResources.get('formatGif')); - imageFormatSelect.appendChild(gifOption); - } - - var jpgOption = document.createElement('option'); - jpgOption.setAttribute('value', 'jpg'); - mxUtils.write(jpgOption, mxResources.get('formatJpg')); - imageFormatSelect.appendChild(jpgOption); - - var pdfOption = document.createElement('option'); - pdfOption.setAttribute('value', 'pdf'); - mxUtils.write(pdfOption, mxResources.get('formatPdf')); - imageFormatSelect.appendChild(pdfOption); - - var svgOption = document.createElement('option'); - svgOption.setAttribute('value', 'svg'); - mxUtils.write(svgOption, mxResources.get('formatSvg')); - imageFormatSelect.appendChild(svgOption); - - if (ExportDialog.showXmlOption) - { - var xmlOption = document.createElement('option'); - xmlOption.setAttribute('value', 'xml'); - mxUtils.write(xmlOption, mxResources.get('formatXml')); - imageFormatSelect.appendChild(xmlOption); - } - - td = document.createElement('td'); - td.appendChild(imageFormatSelect); - row.appendChild(td); - - tbody.appendChild(row); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - mxUtils.write(td, mxResources.get('zoom') + ' (%):'); - - row.appendChild(td); - - var zoomInput = document.createElement('input'); - zoomInput.setAttribute('type', 'number'); - zoomInput.setAttribute('value', '100'); - zoomInput.style.width = '180px'; - - td = document.createElement('td'); - td.appendChild(zoomInput); - row.appendChild(td); - - tbody.appendChild(row); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - mxUtils.write(td, mxResources.get('width') + ':'); - - row.appendChild(td); - - var widthInput = document.createElement('input'); - widthInput.setAttribute('value', width); - widthInput.style.width = '180px'; - - td = document.createElement('td'); - td.appendChild(widthInput); - row.appendChild(td); - - tbody.appendChild(row); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - mxUtils.write(td, mxResources.get('height') + ':'); - - row.appendChild(td); - - var heightInput = document.createElement('input'); - heightInput.setAttribute('value', height); - heightInput.style.width = '180px'; - - td = document.createElement('td'); - td.appendChild(heightInput); - row.appendChild(td); - - tbody.appendChild(row); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - mxUtils.write(td, mxResources.get('dpi') + ':'); - - row.appendChild(td); - - var dpiSelect = document.createElement('select'); - dpiSelect.style.width = '180px'; - - var dpi100Option = document.createElement('option'); - dpi100Option.setAttribute('value', '100'); - mxUtils.write(dpi100Option, '100dpi'); - dpiSelect.appendChild(dpi100Option); - - var dpi200Option = document.createElement('option'); - dpi200Option.setAttribute('value', '200'); - mxUtils.write(dpi200Option, '200dpi'); - dpiSelect.appendChild(dpi200Option); - - var dpi300Option = document.createElement('option'); - dpi300Option.setAttribute('value', '300'); - mxUtils.write(dpi300Option, '300dpi'); - dpiSelect.appendChild(dpi300Option); - - var dpi400Option = document.createElement('option'); - dpi400Option.setAttribute('value', '400'); - mxUtils.write(dpi400Option, '400dpi'); - dpiSelect.appendChild(dpi400Option); - - var dpiCustOption = document.createElement('option'); - dpiCustOption.setAttribute('value', 'custom'); - mxUtils.write(dpiCustOption, mxResources.get('custom')); - dpiSelect.appendChild(dpiCustOption); - - var customDpi = document.createElement('input'); - customDpi.style.width = '180px'; - customDpi.style.display = 'none'; - customDpi.setAttribute('value', '100'); - customDpi.setAttribute('type', 'number'); - customDpi.setAttribute('min', '50'); - customDpi.setAttribute('step', '50'); - - var zoomUserChanged = false; - - mxEvent.addListener(dpiSelect, 'change', function() - { - if (this.value == 'custom') - { - this.style.display = 'none'; - customDpi.style.display = ''; - customDpi.focus(); - } - else - { - customDpi.value = this.value; - - if (!zoomUserChanged) - { - zoomInput.value = this.value; - } - } - }); - - mxEvent.addListener(customDpi, 'change', function() - { - var dpi = parseInt(customDpi.value); - - if (isNaN(dpi) || dpi <= 0) - { - customDpi.style.backgroundColor = 'red'; - } - else - { - customDpi.style.backgroundColor = ''; - - if (!zoomUserChanged) - { - zoomInput.value = dpi; - } - } - }); - - td = document.createElement('td'); - td.appendChild(dpiSelect); - td.appendChild(customDpi); - row.appendChild(td); - - tbody.appendChild(row); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - mxUtils.write(td, mxResources.get('background') + ':'); - - row.appendChild(td); - - var transparentCheckbox = document.createElement('input'); - transparentCheckbox.setAttribute('type', 'checkbox'); - transparentCheckbox.checked = graph.background == null || graph.background == mxConstants.NONE; - - td = document.createElement('td'); - td.appendChild(transparentCheckbox); - mxUtils.write(td, mxResources.get('transparent')); - - row.appendChild(td); - - tbody.appendChild(row); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - mxUtils.write(td, mxResources.get('borderWidth') + ':'); - - row.appendChild(td); - - var borderInput = document.createElement('input'); - borderInput.setAttribute('type', 'number'); - borderInput.setAttribute('value', ExportDialog.lastBorderValue); - borderInput.style.width = '180px'; - - td = document.createElement('td'); - td.appendChild(borderInput); - row.appendChild(td); - - tbody.appendChild(row); - table.appendChild(tbody); - - // Handles changes in the export format - function formatChanged() - { - var name = nameInput.value; - var dot = name.lastIndexOf('.'); - - if (dot > 0) - { - nameInput.value = name.substring(0, dot + 1) + imageFormatSelect.value; - } - else - { - nameInput.value = name + '.' + imageFormatSelect.value; - } - - if (imageFormatSelect.value === 'xml') - { - zoomInput.setAttribute('disabled', 'true'); - widthInput.setAttribute('disabled', 'true'); - heightInput.setAttribute('disabled', 'true'); - borderInput.setAttribute('disabled', 'true'); - } - else - { - zoomInput.removeAttribute('disabled'); - widthInput.removeAttribute('disabled'); - heightInput.removeAttribute('disabled'); - borderInput.removeAttribute('disabled'); - } - - if (imageFormatSelect.value === 'png' || imageFormatSelect.value === 'svg' || imageFormatSelect.value === 'pdf') - { - transparentCheckbox.removeAttribute('disabled'); - } - else - { - transparentCheckbox.setAttribute('disabled', 'disabled'); - } - - if (imageFormatSelect.value === 'png') - { - dpiSelect.removeAttribute('disabled'); - customDpi.removeAttribute('disabled'); - } - else - { - dpiSelect.setAttribute('disabled', 'disabled'); - customDpi.setAttribute('disabled', 'disabled'); - } - }; - - mxEvent.addListener(imageFormatSelect, 'change', formatChanged); - formatChanged(); - - function checkValues() - { - if (widthInput.value * heightInput.value > MAX_AREA || widthInput.value <= 0) - { - widthInput.style.backgroundColor = 'red'; - } - else - { - widthInput.style.backgroundColor = ''; - } - - if (widthInput.value * heightInput.value > MAX_AREA || heightInput.value <= 0) - { - heightInput.style.backgroundColor = 'red'; - } - else - { - heightInput.style.backgroundColor = ''; - } - }; - - mxEvent.addListener(zoomInput, 'change', function() - { - zoomUserChanged = true; - var s = Math.max(0, parseFloat(zoomInput.value) || 100) / 100; - zoomInput.value = parseFloat((s * 100).toFixed(2)); - - if (width > 0) - { - widthInput.value = Math.floor(width * s); - heightInput.value = Math.floor(height * s); - } - else - { - zoomInput.value = '100'; - widthInput.value = width; - heightInput.value = height; - } - - checkValues(); - }); - - mxEvent.addListener(widthInput, 'change', function() - { - var s = parseInt(widthInput.value) / width; - - if (s > 0) - { - zoomInput.value = parseFloat((s * 100).toFixed(2)); - heightInput.value = Math.floor(height * s); - } - else - { - zoomInput.value = '100'; - widthInput.value = width; - heightInput.value = height; - } - - checkValues(); - }); - - mxEvent.addListener(heightInput, 'change', function() - { - var s = parseInt(heightInput.value) / height; - - if (s > 0) - { - zoomInput.value = parseFloat((s * 100).toFixed(2)); - widthInput.value = Math.floor(width * s); - } - else - { - zoomInput.value = '100'; - widthInput.value = width; - heightInput.value = height; - } - - checkValues(); - }); - - row = document.createElement('tr'); - td = document.createElement('td'); - td.setAttribute('align', 'right'); - td.style.paddingTop = '22px'; - td.colSpan = 2; - - var saveBtn = mxUtils.button(mxResources.get('export'), mxUtils.bind(this, function() - { - if (parseInt(zoomInput.value) <= 0) - { - mxUtils.alert(mxResources.get('drawingEmpty')); - } - else - { - var name = nameInput.value; - var format = imageFormatSelect.value; - var s = Math.max(0, parseFloat(zoomInput.value) || 100) / 100; - var b = Math.max(0, parseInt(borderInput.value)); - var bg = graph.background; - var dpi = Math.max(1, parseInt(customDpi.value)); - - if ((format == 'svg' || format == 'png' || format == 'pdf') && transparentCheckbox.checked) - { - bg = null; - } - else if (bg == null || bg == mxConstants.NONE) - { - bg = '#ffffff'; - } - - ExportDialog.lastBorderValue = b; - ExportDialog.exportFile(editorUi, name, format, bg, s, b, dpi); - } - })); - saveBtn.className = 'geBtn gePrimaryBtn'; - - var cancelBtn = mxUtils.button(mxResources.get('cancel'), function() - { - editorUi.hideDialog(); - }); - cancelBtn.className = 'geBtn'; - - if (editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - td.appendChild(saveBtn); - } - else - { - td.appendChild(saveBtn); - td.appendChild(cancelBtn); - } - - row.appendChild(td); - tbody.appendChild(row); - table.appendChild(tbody); - this.container = table; -}; - -/** - * Remembers last value for border. - */ -ExportDialog.lastBorderValue = 0; - -/** - * Global switches for the export dialog. - */ -ExportDialog.showGifOption = true; - -/** - * Global switches for the export dialog. - */ -ExportDialog.showXmlOption = true; - -/** - * Hook for getting the export format. Returns null for the default - * intermediate XML export format or a function that returns the - * parameter and value to be used in the request in the form - * key=value, where value should be URL encoded. - */ -ExportDialog.exportFile = function(editorUi, name, format, bg, s, b, dpi) -{ - var graph = editorUi.editor.graph; - - if (format == 'xml') - { - ExportDialog.saveLocalFile(editorUi, mxUtils.getXml(editorUi.editor.getGraphXml()), name, format); - } - else if (format == 'svg') - { - ExportDialog.saveLocalFile(editorUi, mxUtils.getXml(graph.getSvg(bg, s, b)), name, format); - } - else - { - var bounds = graph.getGraphBounds(); - - // New image export - var xmlDoc = mxUtils.createXmlDocument(); - var root = xmlDoc.createElement('output'); - xmlDoc.appendChild(root); - - // Renders graph. Offset will be multiplied with state's scale when painting state. - var xmlCanvas = new mxXmlCanvas2D(root); - xmlCanvas.translate(Math.floor((b / s - bounds.x) / graph.view.scale), - Math.floor((b / s - bounds.y) / graph.view.scale)); - xmlCanvas.scale(s / graph.view.scale); - - var imgExport = new mxImageExport() - imgExport.drawState(graph.getView().getState(graph.model.root), xmlCanvas); - - // Puts request data together - var param = 'xml=' + encodeURIComponent(mxUtils.getXml(root)); - var w = Math.ceil(bounds.width * s / graph.view.scale + 2 * b); - var h = Math.ceil(bounds.height * s / graph.view.scale + 2 * b); - - // Requests image if request is valid - if (param.length <= MAX_REQUEST_SIZE && w * h < MAX_AREA) - { - editorUi.hideDialog(); - var req = new mxXmlRequest(EXPORT_URL, 'format=' + format + - '&filename=' + encodeURIComponent(name) + - '&bg=' + ((bg != null) ? bg : 'none') + - '&w=' + w + '&h=' + h + '&' + param + - '&dpi=' + dpi); - req.simulate(document, '_blank'); - } - else - { - mxUtils.alert(mxResources.get('drawingTooLarge')); - } - } -}; - -/** - * Hook for getting the export format. Returns null for the default - * intermediate XML export format or a function that returns the - * parameter and value to be used in the request in the form - * key=value, where value should be URL encoded. - */ -ExportDialog.saveLocalFile = function(editorUi, data, filename, format) -{ - if (data.length < MAX_REQUEST_SIZE) - { - editorUi.hideDialog(); - var req = new mxXmlRequest(SAVE_URL, 'xml=' + encodeURIComponent(data) + '&filename=' + - encodeURIComponent(filename) + '&format=' + format); - req.simulate(document, '_blank'); - } - else - { - mxUtils.alert(mxResources.get('drawingTooLarge')); - mxUtils.popup(xml); - } -}; - -/** - * Constructs a new metadata dialog. - */ -var EditDataDialog = function(ui, cell) -{ - var div = document.createElement('div'); - var graph = ui.editor.graph; - - var value = graph.getModel().getValue(cell); - - // Converts the value to an XML node - if (!mxUtils.isNode(value)) - { - var doc = mxUtils.createXmlDocument(); - var obj = doc.createElement('object'); - obj.setAttribute('label', value || ''); - value = obj; - } - - var meta = {}; - - try - { - var temp = mxUtils.getValue(ui.editor.graph.getCurrentCellStyle(cell), 'metaData', null); - - if (temp != null) - { - meta = JSON.parse(temp); - } - } - catch (e) - { - // ignore - } - - // Creates the dialog contents - var form = new mxForm('properties'); - form.table.style.width = '100%'; - - var attrs = value.attributes; - var names = []; - var texts = []; - var count = 0; - - var id = (EditDataDialog.getDisplayIdForCell != null) ? - EditDataDialog.getDisplayIdForCell(ui, cell) : null; - - var addRemoveButton = function(text, name) - { - var wrapper = document.createElement('div'); - wrapper.style.position = 'relative'; - wrapper.style.paddingRight = '20px'; - wrapper.style.boxSizing = 'border-box'; - wrapper.style.width = '100%'; - - var removeAttr = document.createElement('a'); - var img = mxUtils.createImage(Dialog.prototype.closeImage); - img.style.height = '9px'; - img.style.fontSize = '9px'; - img.style.marginBottom = (mxClient.IS_IE11) ? '-1px' : '5px'; - - removeAttr.className = 'geButton'; - removeAttr.setAttribute('title', mxResources.get('delete')); - removeAttr.style.position = 'absolute'; - removeAttr.style.top = '4px'; - removeAttr.style.right = '0px'; - removeAttr.style.margin = '0px'; - removeAttr.style.width = '9px'; - removeAttr.style.height = '9px'; - removeAttr.style.cursor = 'pointer'; - removeAttr.appendChild(img); - - var removeAttrFn = (function(name) - { - return function() - { - var count = 0; - - for (var j = 0; j < names.length; j++) - { - if (names[j] == name) - { - texts[j] = null; - form.table.deleteRow(count + ((id != null) ? 1 : 0)); - - break; - } - - if (texts[j] != null) - { - count++; - } - } - }; - })(name); - - mxEvent.addListener(removeAttr, 'click', removeAttrFn); - - var parent = text.parentNode; - wrapper.appendChild(text); - wrapper.appendChild(removeAttr); - parent.appendChild(wrapper); - }; - - var addTextArea = function(index, name, value) - { - names[index] = name; - texts[index] = form.addTextarea(names[count] + ':', value, 2); - texts[index].style.width = '100%'; - - if (value.indexOf('\n') > 0) - { - texts[index].setAttribute('rows', '2'); - } - - addRemoveButton(texts[index], name); - - if (meta[name] != null && meta[name].editable == false) - { - texts[index].setAttribute('disabled', 'disabled'); - } - }; - - var temp = []; - var isLayer = graph.getModel().getParent(cell) == graph.getModel().getRoot(); - - for (var i = 0; i < attrs.length; i++) - { - if ((isLayer || attrs[i].nodeName != 'label') && attrs[i].nodeName != 'placeholders') - { - temp.push({name: attrs[i].nodeName, value: attrs[i].nodeValue}); - } - } - - // Sorts by name - temp.sort(function(a, b) - { - if (a.name < b.name) - { - return -1; - } - else if (a.name > b.name) - { - return 1; - } - else - { - return 0; - } - }); - - if (id != null) - { - var text = document.createElement('div'); - text.style.width = '100%'; - text.style.fontSize = '11px'; - text.style.textAlign = 'center'; - mxUtils.write(text, id); - - form.addField(mxResources.get('id') + ':', text); - } - - for (var i = 0; i < temp.length; i++) - { - addTextArea(count, temp[i].name, temp[i].value); - count++; - } - - var top = document.createElement('div'); - top.style.cssText = 'position:absolute;left:30px;right:30px;overflow-y:auto;top:30px;bottom:80px;'; - top.appendChild(form.table); - - var newProp = document.createElement('div'); - newProp.style.boxSizing = 'border-box'; - newProp.style.paddingRight = '160px'; - newProp.style.whiteSpace = 'nowrap'; - newProp.style.marginTop = '6px'; - newProp.style.width = '100%'; - - var nameInput = document.createElement('input'); - nameInput.setAttribute('placeholder', mxResources.get('enterPropertyName')); - nameInput.setAttribute('type', 'text'); - nameInput.setAttribute('size', (mxClient.IS_IE || mxClient.IS_IE11) ? '36' : '40'); - nameInput.style.boxSizing = 'border-box'; - nameInput.style.marginLeft = '2px'; - nameInput.style.width = '100%'; - - newProp.appendChild(nameInput); - top.appendChild(newProp); - div.appendChild(top); - - var addBtn = mxUtils.button(mxResources.get('addProperty'), function() - { - var name = nameInput.value; - - // Avoid ':' in attribute names which seems to be valid in Chrome - if (name.length > 0 && name != 'label' && name != 'placeholders' && name.indexOf(':') < 0) - { - try - { - var idx = mxUtils.indexOf(names, name); - - if (idx >= 0 && texts[idx] != null) - { - texts[idx].focus(); - } - else - { - // Checks if the name is valid - var clone = value.cloneNode(false); - clone.setAttribute(name, ''); - - if (idx >= 0) - { - names.splice(idx, 1); - texts.splice(idx, 1); - } - - names.push(name); - var text = form.addTextarea(name + ':', '', 2); - text.style.width = '100%'; - texts.push(text); - addRemoveButton(text, name); - - text.focus(); - } - - addBtn.setAttribute('disabled', 'disabled'); - nameInput.value = ''; - } - catch (e) - { - mxUtils.alert(e); - } - } - else - { - mxUtils.alert(mxResources.get('invalidName')); - } - }); - - this.init = function() - { - if (texts.length > 0) - { - texts[0].focus(); - } - else - { - nameInput.focus(); - } - }; - - addBtn.setAttribute('title', mxResources.get('addProperty')); - addBtn.setAttribute('disabled', 'disabled'); - addBtn.style.textOverflow = 'ellipsis'; - addBtn.style.position = 'absolute'; - addBtn.style.overflow = 'hidden'; - addBtn.style.width = '144px'; - addBtn.style.right = '0px'; - addBtn.className = 'geBtn'; - newProp.appendChild(addBtn); - - var cancelBtn = mxUtils.button(mxResources.get('cancel'), function() - { - ui.hideDialog.apply(ui, arguments); - }); - - cancelBtn.className = 'geBtn'; - - var applyBtn = mxUtils.button(mxResources.get('apply'), function() - { - try - { - ui.hideDialog.apply(ui, arguments); - - // Clones and updates the value - value = value.cloneNode(true); - var removeLabel = false; - - for (var i = 0; i < names.length; i++) - { - if (texts[i] == null) - { - value.removeAttribute(names[i]); - } - else - { - value.setAttribute(names[i], texts[i].value); - removeLabel = removeLabel || (names[i] == 'placeholder' && - value.getAttribute('placeholders') == '1'); - } - } - - // Removes label if placeholder is assigned - if (removeLabel) - { - value.removeAttribute('label'); - } - - // Updates the value of the cell (undoable) - graph.getModel().setValue(cell, value); - } - catch (e) - { - mxUtils.alert(e); - } - }); - applyBtn.className = 'geBtn gePrimaryBtn'; - - function updateAddBtn() - { - if (nameInput.value.length > 0) - { - addBtn.removeAttribute('disabled'); - } - else - { - addBtn.setAttribute('disabled', 'disabled'); - } - }; - - mxEvent.addListener(nameInput, 'keyup', updateAddBtn); - - // Catches all changes that don't fire a keyup (such as paste via mouse) - mxEvent.addListener(nameInput, 'change', updateAddBtn); - - var buttons = document.createElement('div'); - buttons.style.cssText = 'position:absolute;left:30px;right:30px;text-align:right;bottom:30px;height:40px;' - - if (ui.editor.graph.getModel().isVertex(cell) || ui.editor.graph.getModel().isEdge(cell)) - { - var replace = document.createElement('span'); - replace.style.marginRight = '10px'; - var input = document.createElement('input'); - input.setAttribute('type', 'checkbox'); - input.style.marginRight = '6px'; - - if (value.getAttribute('placeholders') == '1') - { - input.setAttribute('checked', 'checked'); - input.defaultChecked = true; - } - - mxEvent.addListener(input, 'click', function() - { - if (value.getAttribute('placeholders') == '1') - { - value.removeAttribute('placeholders'); - } - else - { - value.setAttribute('placeholders', '1'); - } - }); - - replace.appendChild(input); - mxUtils.write(replace, mxResources.get('placeholders')); - - if (EditDataDialog.placeholderHelpLink != null) - { - var link = document.createElement('a'); - link.setAttribute('href', EditDataDialog.placeholderHelpLink); - link.setAttribute('title', mxResources.get('help')); - link.setAttribute('target', '_blank'); - link.style.marginLeft = '8px'; - link.style.cursor = 'help'; - - var icon = document.createElement('img'); - mxUtils.setOpacity(icon, 50); - icon.style.height = '16px'; - icon.style.width = '16px'; - icon.setAttribute('border', '0'); - icon.setAttribute('valign', 'middle'); - icon.style.marginTop = (mxClient.IS_IE11) ? '0px' : '-4px'; - icon.setAttribute('src', Editor.helpImage); - link.appendChild(icon); - - replace.appendChild(link); - } - - buttons.appendChild(replace); - } - - if (ui.editor.cancelFirst) - { - buttons.appendChild(cancelBtn); - buttons.appendChild(applyBtn); - } - else - { - buttons.appendChild(applyBtn); - buttons.appendChild(cancelBtn); - } - - div.appendChild(buttons); - this.container = div; -}; - -/** - * Optional help link. - */ -EditDataDialog.getDisplayIdForCell = function(ui, cell) -{ - var id = null; - - if (ui.editor.graph.getModel().getParent(cell) != null) - { - id = cell.getId(); - } - - return id; -}; - -/** - * Optional help link. - */ -EditDataDialog.placeholderHelpLink = null; - -/** - * Constructs a new link dialog. - */ -var LinkDialog = function(editorUi, initialValue, btnLabel, fn) -{ - var div = document.createElement('div'); - mxUtils.write(div, mxResources.get('editLink') + ':'); - - var inner = document.createElement('div'); - inner.className = 'geTitle'; - inner.style.backgroundColor = 'transparent'; - inner.style.borderColor = 'transparent'; - inner.style.whiteSpace = 'nowrap'; - inner.style.textOverflow = 'clip'; - inner.style.cursor = 'default'; - - if (!mxClient.IS_VML) - { - inner.style.paddingRight = '20px'; - } - - var linkInput = document.createElement('input'); - linkInput.setAttribute('value', initialValue); - linkInput.setAttribute('placeholder', 'http://www.example.com/'); - linkInput.setAttribute('type', 'text'); - linkInput.style.marginTop = '6px'; - linkInput.style.width = '400px'; - linkInput.style.backgroundImage = 'url(\'' + Dialog.prototype.clearImage + '\')'; - linkInput.style.backgroundRepeat = 'no-repeat'; - linkInput.style.backgroundPosition = '100% 50%'; - linkInput.style.paddingRight = '14px'; - - var cross = document.createElement('div'); - cross.setAttribute('title', mxResources.get('reset')); - cross.style.position = 'relative'; - cross.style.left = '-16px'; - cross.style.width = '12px'; - cross.style.height = '14px'; - cross.style.cursor = 'pointer'; - - // Workaround for inline-block not supported in IE - cross.style.display = (mxClient.IS_VML) ? 'inline' : 'inline-block'; - cross.style.top = ((mxClient.IS_VML) ? 0 : 3) + 'px'; - - // Needed to block event transparency in IE - cross.style.background = 'url(' + IMAGE_PATH + '/transparent.gif)'; - - mxEvent.addListener(cross, 'click', function() - { - linkInput.value = ''; - linkInput.focus(); - }); - - inner.appendChild(linkInput); - inner.appendChild(cross); - div.appendChild(inner); - - this.init = function() - { - linkInput.focus(); - - if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS) - { - linkInput.select(); - } - else - { - document.execCommand('selectAll', false, null); - } - }; - - var btns = document.createElement('div'); - btns.style.marginTop = '18px'; - btns.style.textAlign = 'right'; - - mxEvent.addListener(linkInput, 'keypress', function(e) - { - if (e.keyCode == 13) - { - editorUi.hideDialog(); - fn(linkInput.value); - } - }); - - var cancelBtn = mxUtils.button(mxResources.get('cancel'), function() - { - editorUi.hideDialog(); - }); - cancelBtn.className = 'geBtn'; - - if (editorUi.editor.cancelFirst) - { - btns.appendChild(cancelBtn); - } - - var mainBtn = mxUtils.button(btnLabel, function() - { - editorUi.hideDialog(); - fn(linkInput.value); - }); - mainBtn.className = 'geBtn gePrimaryBtn'; - btns.appendChild(mainBtn); - - if (!editorUi.editor.cancelFirst) - { - btns.appendChild(cancelBtn); - } - - div.appendChild(btns); - - this.container = div; -}; - -/** - * - */ -var OutlineWindow = function(editorUi, x, y, w, h) -{ - var graph = editorUi.editor.graph; - - var div = document.createElement('div'); - div.style.position = 'absolute'; - div.style.width = '100%'; - div.style.height = '100%'; - div.style.border = '1px solid whiteSmoke'; - div.style.overflow = 'hidden'; - - this.window = new mxWindow(mxResources.get('outline'), div, x, y, w, h, true, true); - this.window.minimumSize = new mxRectangle(0, 0, 80, 80); - this.window.destroyOnClose = false; - this.window.setMaximizable(false); - this.window.setResizable(true); - this.window.setClosable(true); - this.window.setVisible(true); - - this.window.setLocation = function(x, y) - { - var iw = window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth; - var ih = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight; - - x = Math.max(0, Math.min(x, iw - this.table.clientWidth)); - y = Math.max(0, Math.min(y, ih - this.table.clientHeight - 48)); - - if (this.getX() != x || this.getY() != y) - { - mxWindow.prototype.setLocation.apply(this, arguments); - } - }; - - var resizeListener = mxUtils.bind(this, function() - { - var x = this.window.getX(); - var y = this.window.getY(); - - this.window.setLocation(x, y); - }); - - mxEvent.addListener(window, 'resize', resizeListener); - - var outline = editorUi.createOutline(this.window); - - this.destroy = function() - { - mxEvent.removeListener(window, 'resize', resizeListener); - this.window.destroy(); - outline.destroy(); - } - - this.window.addListener(mxEvent.RESIZE, mxUtils.bind(this, function() - { - outline.update(false); - outline.outline.sizeDidChange(); - })); - - this.window.addListener(mxEvent.SHOW, mxUtils.bind(this, function() - { - this.window.fit(); - outline.suspended = false; - outline.outline.refresh(); - outline.update(); - })); - - this.window.addListener(mxEvent.HIDE, mxUtils.bind(this, function() - { - outline.suspended = true; - })); - - this.window.addListener(mxEvent.NORMALIZE, mxUtils.bind(this, function() - { - outline.suspended = false; - outline.update(); - })); - - this.window.addListener(mxEvent.MINIMIZE, mxUtils.bind(this, function() - { - outline.suspended = true; - })); - - var outlineCreateGraph = outline.createGraph; - outline.createGraph = function(container) - { - var g = outlineCreateGraph.apply(this, arguments); - g.gridEnabled = false; - g.pageScale = graph.pageScale; - g.pageFormat = graph.pageFormat; - g.background = (graph.background == null || graph.background == mxConstants.NONE) ? graph.defaultPageBackgroundColor : graph.background; - g.pageVisible = graph.pageVisible; - - var current = mxUtils.getCurrentStyle(graph.container); - div.style.backgroundColor = current.backgroundColor; - - return g; - }; - - function update() - { - outline.outline.pageScale = graph.pageScale; - outline.outline.pageFormat = graph.pageFormat; - outline.outline.pageVisible = graph.pageVisible; - outline.outline.background = (graph.background == null || graph.background == mxConstants.NONE) ? graph.defaultPageBackgroundColor : graph.background;; - - var current = mxUtils.getCurrentStyle(graph.container); - div.style.backgroundColor = current.backgroundColor; - - if (graph.view.backgroundPageShape != null && outline.outline.view.backgroundPageShape != null) - { - outline.outline.view.backgroundPageShape.fill = graph.view.backgroundPageShape.fill; - } - - outline.outline.refresh(); - }; - - outline.init(div); - - editorUi.editor.addListener('resetGraphView', update); - editorUi.addListener('pageFormatChanged', update); - editorUi.addListener('backgroundColorChanged', update); - editorUi.addListener('backgroundImageChanged', update); - editorUi.addListener('pageViewChanged', function() - { - update(); - outline.update(true); - }); - - if (outline.outline.dialect == mxConstants.DIALECT_SVG) - { - var zoomInAction = editorUi.actions.get('zoomIn'); - var zoomOutAction = editorUi.actions.get('zoomOut'); - - mxEvent.addMouseWheelListener(function(evt, up) - { - var outlineWheel = false; - var source = mxEvent.getSource(evt); - - while (source != null) - { - if (source == outline.outline.view.canvas.ownerSVGElement) - { - outlineWheel = true; - break; - } - - source = source.parentNode; - } - - if (outlineWheel) - { - if (up) - { - zoomInAction.funct(); - } - else - { - zoomOutAction.funct(); - } - } - }); - } -}; - -/** - * - */ -var LayersWindow = function(editorUi, x, y, w, h) -{ - var graph = editorUi.editor.graph; - - var div = document.createElement('div'); - div.style.userSelect = 'none'; - div.style.background = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor; - div.style.border = '1px solid whiteSmoke'; - div.style.height = '100%'; - div.style.marginBottom = '10px'; - div.style.overflow = 'auto'; - - var tbarHeight = (!EditorUi.compactUi) ? '30px' : '26px'; - - var listDiv = document.createElement('div') - listDiv.style.backgroundColor = (Dialog.backdropColor == 'white') ? '#dcdcdc' : Dialog.backdropColor; - listDiv.style.position = 'absolute'; - listDiv.style.overflow = 'auto'; - listDiv.style.left = '0px'; - listDiv.style.right = '0px'; - listDiv.style.top = '0px'; - listDiv.style.bottom = (parseInt(tbarHeight) + 7) + 'px'; - div.appendChild(listDiv); - - var dragSource = null; - var dropIndex = null; - - mxEvent.addListener(div, 'dragover', function(evt) - { - evt.dataTransfer.dropEffect = 'move'; - dropIndex = 0; - evt.stopPropagation(); - evt.preventDefault(); - }); - - // Workaround for "no element found" error in FF - mxEvent.addListener(div, 'drop', function(evt) - { - evt.stopPropagation(); - evt.preventDefault(); - }); - - var layerCount = null; - var selectionLayer = null; - var ldiv = document.createElement('div'); - - ldiv.className = 'geToolbarContainer'; - ldiv.style.position = 'absolute'; - ldiv.style.bottom = '0px'; - ldiv.style.left = '0px'; - ldiv.style.right = '0px'; - ldiv.style.height = tbarHeight; - ldiv.style.overflow = 'hidden'; - ldiv.style.padding = (!EditorUi.compactUi) ? '1px' : '4px 0px 3px 0px'; - ldiv.style.backgroundColor = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor; - ldiv.style.borderWidth = '1px 0px 0px 0px'; - ldiv.style.borderColor = '#c3c3c3'; - ldiv.style.borderStyle = 'solid'; - ldiv.style.display = 'block'; - ldiv.style.whiteSpace = 'nowrap'; - - if (mxClient.IS_QUIRKS) - { - ldiv.style.filter = 'none'; - } - - var link = document.createElement('a'); - link.className = 'geButton'; - - if (mxClient.IS_QUIRKS) - { - link.style.filter = 'none'; - } - - var removeLink = link.cloneNode(); - removeLink.innerHTML = '
'; - - mxEvent.addListener(removeLink, 'click', function(evt) - { - if (graph.isEnabled()) - { - graph.model.beginUpdate(); - try - { - var index = graph.model.root.getIndex(selectionLayer); - graph.removeCells([selectionLayer], false); - - // Creates default layer if no layer exists - if (graph.model.getChildCount(graph.model.root) == 0) - { - graph.model.add(graph.model.root, new mxCell()); - graph.setDefaultParent(null); - } - else if (index > 0 && index <= graph.model.getChildCount(graph.model.root)) - { - graph.setDefaultParent(graph.model.getChildAt(graph.model.root, index - 1)); - } - else - { - graph.setDefaultParent(null); - } - } - finally - { - graph.model.endUpdate(); - } - } - - mxEvent.consume(evt); - }); - - if (!graph.isEnabled()) - { - removeLink.className = 'geButton mxDisabled'; - } - - ldiv.appendChild(removeLink); - - var insertLink = link.cloneNode(); - insertLink.setAttribute('title', mxUtils.trim(mxResources.get('moveSelectionTo', ['...']))); - insertLink.innerHTML = '
'; - - mxEvent.addListener(insertLink, 'click', function(evt) - { - if (graph.isEnabled() && !graph.isSelectionEmpty()) - { - var offset = mxUtils.getOffset(insertLink); - - editorUi.showPopupMenu(mxUtils.bind(this, function(menu, parent) - { - for (var i = layerCount - 1; i >= 0; i--) - { - (mxUtils.bind(this, function(child) - { - var item = menu.addItem(graph.convertValueToString(child) || - mxResources.get('background'), null, mxUtils.bind(this, function() - { - graph.moveCells(graph.getSelectionCells(), 0, 0, false, child); - }), parent); - - if (graph.getSelectionCount() == 1 && graph.model.isAncestor(child, graph.getSelectionCell())) - { - menu.addCheckmark(item, Editor.checkmarkImage); - } - - }))(graph.model.getChildAt(graph.model.root, i)); - } - }), offset.x, offset.y + insertLink.offsetHeight, evt); - } - }); - - ldiv.appendChild(insertLink); - - var dataLink = link.cloneNode(); - dataLink.innerHTML = '
'; - dataLink.setAttribute('title', mxResources.get('rename')); - - mxEvent.addListener(dataLink, 'click', function(evt) - { - if (graph.isEnabled()) - { - editorUi.showDataDialog(selectionLayer); - } - - mxEvent.consume(evt); - }); - - if (!graph.isEnabled()) - { - dataLink.className = 'geButton mxDisabled'; - } - - ldiv.appendChild(dataLink); - - function renameLayer(layer) - { - if (graph.isEnabled() && layer != null) - { - var label = graph.convertValueToString(layer); - var dlg = new FilenameDialog(editorUi, label || mxResources.get('background'), mxResources.get('rename'), mxUtils.bind(this, function(newValue) - { - if (newValue != null) - { - graph.cellLabelChanged(layer, newValue); - } - }), mxResources.get('enterName')); - editorUi.showDialog(dlg.container, 300, 100, true, true); - dlg.init(); - } - }; - - var duplicateLink = link.cloneNode(); - duplicateLink.innerHTML = '
'; - - mxEvent.addListener(duplicateLink, 'click', function(evt) - { - if (graph.isEnabled()) - { - var newCell = null; - graph.model.beginUpdate(); - try - { - newCell = graph.cloneCell(selectionLayer); - graph.cellLabelChanged(newCell, mxResources.get('untitledLayer')); - newCell.setVisible(true); - newCell = graph.addCell(newCell, graph.model.root); - graph.setDefaultParent(newCell); - } - finally - { - graph.model.endUpdate(); - } - - if (newCell != null && !graph.isCellLocked(newCell)) - { - graph.selectAll(newCell); - } - } - }); - - if (!graph.isEnabled()) - { - duplicateLink.className = 'geButton mxDisabled'; - } - - ldiv.appendChild(duplicateLink); - - var addLink = link.cloneNode(); - addLink.innerHTML = '
'; - addLink.setAttribute('title', mxResources.get('addLayer')); - - mxEvent.addListener(addLink, 'click', function(evt) - { - if (graph.isEnabled()) - { - graph.model.beginUpdate(); - - try - { - var cell = graph.addCell(new mxCell(mxResources.get('untitledLayer')), graph.model.root); - graph.setDefaultParent(cell); - } - finally - { - graph.model.endUpdate(); - } - } - - mxEvent.consume(evt); - }); - - if (!graph.isEnabled()) - { - addLink.className = 'geButton mxDisabled'; - } - - ldiv.appendChild(addLink); - div.appendChild(ldiv); - - function refresh() - { - layerCount = graph.model.getChildCount(graph.model.root) - listDiv.innerHTML = ''; - - function addLayer(index, label, child, defaultParent) - { - var ldiv = document.createElement('div'); - ldiv.className = 'geToolbarContainer'; - - ldiv.style.overflow = 'hidden'; - ldiv.style.position = 'relative'; - ldiv.style.padding = '4px'; - ldiv.style.height = '22px'; - ldiv.style.display = 'block'; - ldiv.style.backgroundColor = (Dialog.backdropColor == 'white') ? 'whiteSmoke' : Dialog.backdropColor; - ldiv.style.borderWidth = '0px 0px 1px 0px'; - ldiv.style.borderColor = '#c3c3c3'; - ldiv.style.borderStyle = 'solid'; - ldiv.style.whiteSpace = 'nowrap'; - ldiv.setAttribute('title', label); - - var left = document.createElement('div'); - left.style.display = 'inline-block'; - left.style.width = '100%'; - left.style.textOverflow = 'ellipsis'; - left.style.overflow = 'hidden'; - - mxEvent.addListener(ldiv, 'dragover', function(evt) - { - evt.dataTransfer.dropEffect = 'move'; - dropIndex = index; - evt.stopPropagation(); - evt.preventDefault(); - }); - - mxEvent.addListener(ldiv, 'dragstart', function(evt) - { - dragSource = ldiv; - - // Workaround for no DnD on DIV in FF - if (mxClient.IS_FF) - { - // LATER: Check what triggers a parse as XML on this in FF after drop - evt.dataTransfer.setData('Text', ''); - } - }); - - mxEvent.addListener(ldiv, 'dragend', function(evt) - { - if (dragSource != null && dropIndex != null) - { - graph.addCell(child, graph.model.root, dropIndex); - } - - dragSource = null; - dropIndex = null; - evt.stopPropagation(); - evt.preventDefault(); - }); - - var btn = document.createElement('img'); - btn.setAttribute('draggable', 'false'); - btn.setAttribute('align', 'top'); - btn.setAttribute('border', '0'); - btn.style.padding = '4px'; - btn.setAttribute('title', mxResources.get('lockUnlock')); - - var style = graph.getCurrentCellStyle(child); - - if (mxUtils.getValue(style, 'locked', '0') == '1') - { - btn.setAttribute('src', Dialog.prototype.lockedImage); - } - else - { - btn.setAttribute('src', Dialog.prototype.unlockedImage); - } - - if (graph.isEnabled()) - { - btn.style.cursor = 'pointer'; - } - - mxEvent.addListener(btn, 'click', function(evt) - { - if (graph.isEnabled()) - { - var value = null; - - graph.getModel().beginUpdate(); - try - { - value = (mxUtils.getValue(style, 'locked', '0') == '1') ? null : '1'; - graph.setCellStyles('locked', value, [child]); - } - finally - { - graph.getModel().endUpdate(); - } - - if (value == '1') - { - graph.removeSelectionCells(graph.getModel().getDescendants(child)); - } - - mxEvent.consume(evt); - } - }); - - left.appendChild(btn); - - var inp = document.createElement('input'); - inp.setAttribute('type', 'checkbox'); - inp.setAttribute('title', mxResources.get('hideIt', [child.value || mxResources.get('background')])); - inp.style.marginLeft = '4px'; - inp.style.marginRight = '6px'; - inp.style.marginTop = '4px'; - left.appendChild(inp); - - if (graph.model.isVisible(child)) - { - inp.setAttribute('checked', 'checked'); - inp.defaultChecked = true; - } - - mxEvent.addListener(inp, 'click', function(evt) - { - graph.model.setVisible(child, !graph.model.isVisible(child)); - mxEvent.consume(evt); - }); - - mxUtils.write(left, label); - ldiv.appendChild(left); - - if (graph.isEnabled()) - { - // Fallback if no drag and drop is available - if (mxClient.IS_TOUCH || mxClient.IS_POINTER || mxClient.IS_VML || - (mxClient.IS_IE && document.documentMode < 10)) - { - var right = document.createElement('div'); - right.style.display = 'block'; - right.style.textAlign = 'right'; - right.style.whiteSpace = 'nowrap'; - right.style.position = 'absolute'; - right.style.right = '6px'; - right.style.top = '6px'; - - // Poor man's change layer order - if (index > 0) - { - var img2 = document.createElement('a'); - - img2.setAttribute('title', mxResources.get('toBack')); - - img2.className = 'geButton'; - img2.style.cssFloat = 'none'; - img2.innerHTML = '▼'; - img2.style.width = '14px'; - img2.style.height = '14px'; - img2.style.fontSize = '14px'; - img2.style.margin = '0px'; - img2.style.marginTop = '-1px'; - right.appendChild(img2); - - mxEvent.addListener(img2, 'click', function(evt) - { - if (graph.isEnabled()) - { - graph.addCell(child, graph.model.root, index - 1); - } - - mxEvent.consume(evt); - }); - } - - if (index >= 0 && index < layerCount - 1) - { - var img1 = document.createElement('a'); - - img1.setAttribute('title', mxResources.get('toFront')); - - img1.className = 'geButton'; - img1.style.cssFloat = 'none'; - img1.innerHTML = '▲'; - img1.style.width = '14px'; - img1.style.height = '14px'; - img1.style.fontSize = '14px'; - img1.style.margin = '0px'; - img1.style.marginTop = '-1px'; - right.appendChild(img1); - - mxEvent.addListener(img1, 'click', function(evt) - { - if (graph.isEnabled()) - { - graph.addCell(child, graph.model.root, index + 1); - } - - mxEvent.consume(evt); - }); - } - - ldiv.appendChild(right); - } - - if (mxClient.IS_SVG && (!mxClient.IS_IE || document.documentMode >= 10)) - { - ldiv.setAttribute('draggable', 'true'); - ldiv.style.cursor = 'move'; - } - } - - mxEvent.addListener(ldiv, 'dblclick', function(evt) - { - var nodeName = mxEvent.getSource(evt).nodeName; - - if (nodeName != 'INPUT' && nodeName != 'IMG') - { - renameLayer(child); - mxEvent.consume(evt); - } - }); - - if (graph.getDefaultParent() == child) - { - ldiv.style.background = (Dialog.backdropColor == 'white') ? '#e6eff8' : '#505759'; - ldiv.style.fontWeight = (graph.isEnabled()) ? 'bold' : ''; - selectionLayer = child; - } - else - { - mxEvent.addListener(ldiv, 'click', function(evt) - { - if (graph.isEnabled()) - { - graph.setDefaultParent(defaultParent); - graph.view.setCurrentRoot(null); - } - }); - } - - listDiv.appendChild(ldiv); - }; - - // Cannot be moved or deleted - for (var i = layerCount - 1; i >= 0; i--) - { - (mxUtils.bind(this, function(child) - { - addLayer(i, graph.convertValueToString(child) || - mxResources.get('background'), child, child); - }))(graph.model.getChildAt(graph.model.root, i)); - } - - var label = graph.convertValueToString(selectionLayer) || mxResources.get('background'); - removeLink.setAttribute('title', mxResources.get('removeIt', [label])); - duplicateLink.setAttribute('title', mxResources.get('duplicateIt', [label])); - dataLink.setAttribute('title', mxResources.get('editData')); - - if (graph.isSelectionEmpty()) - { - insertLink.className = 'geButton mxDisabled'; - } - }; - - refresh(); - graph.model.addListener(mxEvent.CHANGE, refresh); - graph.addListener('defaultParentChanged', refresh); - - graph.selectionModel.addListener(mxEvent.CHANGE, function() - { - if (graph.isSelectionEmpty()) - { - insertLink.className = 'geButton mxDisabled'; - } - else - { - insertLink.className = 'geButton'; - } - }); - - this.window = new mxWindow(mxResources.get('layers'), div, x, y, w, h, true, true); - this.window.minimumSize = new mxRectangle(0, 0, 120, 120); - this.window.destroyOnClose = false; - this.window.setMaximizable(false); - this.window.setResizable(true); - this.window.setClosable(true); - this.window.setVisible(true); - - this.init = function() - { - listDiv.scrollTop = listDiv.scrollHeight - listDiv.clientHeight; - }; - - this.window.addListener(mxEvent.SHOW, mxUtils.bind(this, function() - { - this.window.fit(); - })); - - // Make refresh available via instance - this.refreshLayers = refresh; - - this.window.setLocation = function(x, y) - { - var iw = window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth; - var ih = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight; - - x = Math.max(0, Math.min(x, iw - this.table.clientWidth)); - y = Math.max(0, Math.min(y, ih - this.table.clientHeight - 48)); - - if (this.getX() != x || this.getY() != y) - { - mxWindow.prototype.setLocation.apply(this, arguments); - } - }; - - var resizeListener = mxUtils.bind(this, function() - { - var x = this.window.getX(); - var y = this.window.getY(); - - this.window.setLocation(x, y); - }); - - mxEvent.addListener(window, 'resize', resizeListener); - - this.destroy = function() - { - mxEvent.removeListener(window, 'resize', resizeListener); - this.window.destroy(); - } -}; diff --git a/src/main/webapp/js/mxgraph/Editor.js b/src/main/webapp/js/mxgraph/Editor.js deleted file mode 100644 index 4ac80f32..00000000 --- a/src/main/webapp/js/mxgraph/Editor.js +++ /dev/null @@ -1,2778 +0,0 @@ -/** - * Copyright (c) 2006-2012, JGraph Ltd - */ -/** - * Editor constructor executed on page load. - */ -Editor = function(chromeless, themes, model, graph, editable) -{ - mxEventSource.call(this); - this.chromeless = (chromeless != null) ? chromeless : this.chromeless; - this.initStencilRegistry(); - this.graph = graph || this.createGraph(themes, model); - this.editable = (editable != null) ? editable : !chromeless; - this.undoManager = this.createUndoManager(); - this.status = ''; - - this.getOrCreateFilename = function() - { - return this.filename || mxResources.get('drawing', [Editor.pageCounter]) + '.xml'; - }; - - this.getFilename = function() - { - return this.filename; - }; - - // Sets the status and fires a statusChanged event - this.setStatus = function(value) - { - this.status = value; - this.fireEvent(new mxEventObject('statusChanged')); - }; - - // Returns the current status - this.getStatus = function() - { - return this.status; - }; - - // Updates modified state if graph changes - this.graphChangeListener = function(sender, eventObject) - { - var edit = (eventObject != null) ? eventObject.getProperty('edit') : null; - - if (edit == null || !edit.ignoreEdit) - { - this.setModified(true); - } - }; - - this.graph.getModel().addListener(mxEvent.CHANGE, mxUtils.bind(this, function() - { - this.graphChangeListener.apply(this, arguments); - })); - - // Sets persistent graph state defaults - this.graph.resetViewOnRootChange = false; - this.init(); -}; - -/** - * Counts open editor tabs (must be global for cross-window access) - */ -Editor.pageCounter = 0; - -// Cross-domain window access is not allowed in FF, so if we -// were opened from another domain then this will fail. -(function() -{ - try - { - var op = window; - - while (op.opener != null && typeof op.opener.Editor !== 'undefined' && - !isNaN(op.opener.Editor.pageCounter) && - // Workaround for possible infinite loop in FF https://drawio.atlassian.net/browse/DS-795 - op.opener != op) - { - op = op.opener; - } - - // Increments the counter in the first opener in the chain - if (op != null) - { - op.Editor.pageCounter++; - Editor.pageCounter = op.Editor.pageCounter; - } - } - catch (e) - { - // ignore - } -})(); - -/** - * Specifies if local storage should be used (eg. on the iPad which has no filesystem) - */ -Editor.useLocalStorage = typeof(Storage) != 'undefined' && mxClient.IS_IOS; - -/** - * - */ -Editor.moveImage = (mxClient.IS_SVG) ? 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI4cHgiIGhlaWdodD0iMjhweCI+PGc+PC9nPjxnPjxnPjxnPjxwYXRoIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIuNCwyLjQpc2NhbGUoMC44KXJvdGF0ZSg0NSwxMiwxMikiIHN0cm9rZT0iIzI5YjZmMiIgZmlsbD0iIzI5YjZmMiIgZD0iTTE1LDNsMi4zLDIuM2wtMi44OSwyLjg3bDEuNDIsMS40MkwxOC43LDYuN0wyMSw5VjNIMTV6IE0zLDlsMi4zLTIuM2wyLjg3LDIuODlsMS40Mi0xLjQyTDYuNyw1LjNMOSwzSDNWOXogTTksMjEgbC0yLjMtMi4zbDIuODktMi44N2wtMS40Mi0xLjQyTDUuMywxNy4zTDMsMTV2Nkg5eiBNMjEsMTVsLTIuMywyLjNsLTIuODctMi44OWwtMS40MiwxLjQybDIuODksMi44N0wxNSwyMWg2VjE1eiIvPjwvZz48L2c+PC9nPjwvc3ZnPgo=' : - IMAGE_PATH + '/move.png'; - -/** - * - */ -Editor.rowMoveImage = (mxClient.IS_SVG) ? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAEBAMAAACw6DhOAAAAGFBMVEUzMzP///9tbW1QUFCKiopBQUF8fHxfX1/IXlmXAAAAFElEQVQImWNgNVdzYBAUFBRggLMAEzYBy29kEPgAAAAASUVORK5CYII=' : - IMAGE_PATH + '/thumb_horz.png'; - -/** - * Images below are for lightbox and embedding toolbars. - */ -Editor.helpImage = (mxClient.IS_SVG) ? 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSJub25lIiBkPSJNMCAwaDI0djI0SDB6Ii8+PHBhdGggZD0iTTExIDE4aDJ2LTJoLTJ2MnptMS0xNkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDh6bTAtMTRjLTIuMjEgMC00IDEuNzktNCA0aDJjMC0xLjEuOS0yIDItMnMyIC45IDIgMmMwIDItMyAxLjc1LTMgNWgyYzAtMi4yNSAzLTIuNSAzLTUgMC0yLjIxLTEuNzktNC00LTR6Ii8+PC9zdmc+' : - IMAGE_PATH + '/help.png'; - -/** - * Sets the default font size. - */ -Editor.checkmarkImage = (mxClient.IS_SVG) ? 'data:image/gif;base64,R0lGODlhFQAVAMQfAGxsbHx8fIqKioaGhvb29nJycvr6+sDAwJqamltbW5OTk+np6YGBgeTk5Ly8vJiYmP39/fLy8qWlpa6ursjIyOLi4vj4+N/f3+3t7fT09LCwsHZ2dubm5r6+vmZmZv///yH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEY4NTZERTQ5QUFBMTFFMUE5MTVDOTM5MUZGMTE3M0QiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEY4NTZERTU5QUFBMTFFMUE5MTVDOTM5MUZGMTE3M0QiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Rjg1NkRFMjlBQUExMUUxQTkxNUM5MzkxRkYxMTczRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Rjg1NkRFMzlBQUExMUUxQTkxNUM5MzkxRkYxMTczRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAB8ALAAAAAAVABUAAAVI4CeOZGmeaKqubKtylktSgCOLRyLd3+QJEJnh4VHcMoOfYQXQLBcBD4PA6ngGlIInEHEhPOANRkaIFhq8SuHCE1Hb8Lh8LgsBADs=' : - IMAGE_PATH + '/checkmark.gif'; - -/** - * Images below are for lightbox and embedding toolbars. - */ -Editor.maximizeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAElBMVEUAAAAAAAAAAAAAAAAAAAAAAADgKxmiAAAABXRSTlMA758vX1Pw3BoAAABJSURBVAjXY8AJQkODGBhUQ0MhbAUGBiYY24CBgRnGFmZgMISwgwwDGRhEhVVBbAVmEQYGRwMmBjIAQi/CTIRd6G5AuA3dzYQBAHj0EFdHkvV4AAAAAElFTkSuQmCC'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.zoomOutImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAElBMVEUAAAAAAAAsLCxxcXEhISFgYGChjTUxAAAAAXRSTlMAQObYZgAAAEdJREFUCNdjIAMwCQrB2YKCggJQJqMwA7MglK1owMBgqABVApITgLJZXFxgbIQ4Qj3CHIT5ggoIe5kgNkM1KSDYKBKqxPkDAPo5BAZBE54hAAAAAElFTkSuQmCC'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.zoomInImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAElBMVEUAAAAAAAAsLCwhISFxcXFgYGBavKaoAAAAAXRSTlMAQObYZgAAAElJREFUCNdjIAMwCQrB2YKCggJQJqMIA4sglK3owMzgqABVwsDMwCgAZTMbG8PYCHGEeoQ5CPMFFRD2MkFshmpSQLBRJFSJ8wcAEqcEM2uhl2MAAAAASUVORK5CYII='; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.zoomFitImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVBAMAAABbObilAAAAD1BMVEUAAAAAAAAwMDBwcHBgYGC1xl09AAAAAXRSTlMAQObYZgAAAEFJREFUCNdjIAMwCQrB2YKCggJQJqMwA7MglK1owMBgqABVApITwMdGqEeYgzBfUAFhLxPEZqgmBQQbRUKFOH8AAK5OA3lA+FFOAAAAAElFTkSuQmCC'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.layersImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAMAAACeyVWkAAAAaVBMVEUAAAAgICAICAgdHR0PDw8WFhYICAgLCwsXFxcvLy8ODg4uLi4iIiIqKiokJCQYGBgKCgonJycFBQUCAgIqKiocHBwcHBwODg4eHh4cHBwnJycJCQkUFBQqKiojIyMuLi4ZGRkgICAEBATOWYXAAAAAGnRSTlMAD7+fnz8/H7/ff18/77+vr5+fn39/b28fH2xSoKsAAACQSURBVBjTrYxJEsMgDARZZMAY73sgCcn/HxnhKtnk7j6oRq0psfuoyndZ/SuODkHPLzfVT6KeyPePnJ7KrnkRjWMXTn4SMnN8mXe2SSM3ts8L/ZUxxrbAULSYJJULE0Iw9pjpenoICcgcX61mGgTgtCv9Be99pzCoDhNQWQnchD1mup5++CYGcoQexajZbfwAj/0MD8ZOaUgAAAAASUVORK5CYII='; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.previousImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAAh0lEQVQ4je3UsQnCUBCA4U8hpa1NsoEjpHQJS0dxADdwEMuMIJkgA1hYChbGQgMi+JC8q4L/AB/vDu7x74cWWEZhJU44RmA1zujR5GIbXF9YNrjD/Q0bDRY4fEBZ4P4LlgTnCbAf84pUM8/9hY08tMUtEoQ1LpEgrNBFglChFXR6Q6GfwwR6AGKJMF74Vtt3AAAAAElFTkSuQmCC'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.nextImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAAi0lEQVQ4jeXUIQ7CUAwA0MeGxWI2yylwnALJUdBcgYvM7QYLmjOQIAkIPmJZghiIvypoUtX0tfnJL38X5ZfaEgUeUcManFBHgS0SLlhHggk3bCPBhCf2keCQR8wjwYTDp6YiZxJmOU1jGw7vGALescuBxsArNlOwd/CM1VSM/ut1qCIw+uOwiMJ+OF4CQzBCXm3hyAAAAABJRU5ErkJggg=='; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.editImage = (mxClient.IS_SVG) ? 'data:image/gif;base64,R0lGODlhCwALAIABAFdXV////yH5BAEAAAEALAAAAAALAAsAAAIZjB8AiKuc4jvLOGqzrjX6zmkWyChXaUJBAQA7' : IMAGE_PATH + '/edit.gif'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.zoomOutLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAilBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2N2iNAAAALXRSTlMA+vTcKMM96GRBHwXxi0YaX1HLrKWhiHpWEOnOr52Vb2xKSDcT19PKv5l/Ngdk8+viAAABJklEQVQ4y4WT2XaDMAxEvWD2nSSUNEnTJN3r//+9Sj7ILAY6L0ijC4ONYVZRpo6cByrz2YKSUGorGTpz71lPVHvT+avoB5wIkU/mxk8veceSuNoLg44IzziXjvpih72wKQnm8yc2UoiP/LAd8jQfe2Xf4Pq+2EyYIvv9wbzHHCgwxDdlBtWZOdqDfTCVgqpygQpsZaojVAVc9UjQxnAJDIBhiQv84tq3gMQCAVTxVoSibXJf8tMuc7e1TB/DCmejBNg/w1Y3c+AM5vv4w7xM59/oXamrHaLVqPQ+OTCnmMZxgz0SdL5zji0/ld6j88qGa5KIiBB6WeJGKfUKwSMKLuXgvl1TW0tm5R9UQL/efSDYsnzxD8CinhBsTTdugJatKpJwf8v+ADb8QmvW7AeAAAAAAElFTkSuQmCC'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.zoomInLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAilBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2N2iNAAAALXRSTlMA+vTcKMM96GRBHwXxi0YaX1HLrKWhiHpWEOnOr52Vb2xKSDcT19PKv5l/Ngdk8+viAAABKElEQVQ4y4WT6WKCMBCENwkBwn2oFKvWqr3L+79es4EkQIDOH2d3Pxk2ABiJlB8JCXjqw4LikHVGLHTm3nM3UeVN5690GBBN0GwyV/3kkrUQR+WeKnREeKpzaXWd77CmJiXGfPIEI4V4yQ9TIW/ntlcMBe731Vts9w5TWG8F5j3mQI4hvrKpdGeYA7CX9qAcl650gVJartxRuhyHVghF8idQAIbFLvCLu28BsQEC6aKtCK6Pyb3JT7PmbmtNH8Ny56CotD/2qOs5cJbuffxgXmCib+xddVU5RNOhkvvkhTlFehzVWCOh3++MYElOhfdovaImnRYVmqDdsuhNp1QrBBE6uGC2+3ZNjGdg5B94oD+9uyVgWT79BwAxEBTWdOu3bWBVgsn/N/AHUD9IC01Oe40AAAAASUVORK5CYII='; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.actualSizeLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAilBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2N2iNAAAALXRSTlMA+vTcKMM96GRBHwXxi0YaX1HLrKWhiHpWEOnOr52Vb2xKSDcT19PKv5l/Ngdk8+viAAABIUlEQVQ4y4WT2XqDIBCFBxDc9yTWNEnTJN3r+79eGT4BEbXnaubMr8dBBaM450dCQp4LWFAascGIRd48eB4cNYE7f6XjgGiCFs5c+dml6CFN6j1V6IQIlHPpdV/usKcmJcV88gQTRXjLD9Mhb+fWq8YG9/uCmTCFjeeDeY85UGKIUGUuqzN42kv7oCouq9oHamlzVR1lVfpAIu1QVRiW+sAv7r4FpAYIZZVsRXB9TP5Dfpo1d1trCgzz1iiptH/sUbdz4CzN9+mLeXHn3+hdddd4RDegsrvzwZwSs2GLPRJidAqCLTlVwaMPqpYMWjTWBB2WRW86pVkhSKyDK2bdt2tmagZG4sBD/evdLQHLEvQfAOKRoLCmG1FAB6uKmby+gz+REDn7O5+EwQAAAABJRU5ErkJggg=='; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.printLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAXVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9RKvvlAAAAHnRSTlMAydnl77qbMLT093H7K4Nd4Ktn082+lYt5bkklEgP44nQSAAAApUlEQVQ4y73P2Q6DIBRF0cOgbRHHzhP//5m9mBAQKjG1cT0Yc7ITAMu1LNQgUZiQ2DYoNQ0sCQb6qgHAfRx48opq3J9AZ6xuF7uOew8Ik1OsCZRS2UAC9V+D9a+QZYxNA45YFQftPtSkATOhw7dAc0vPBwKWiIOjP0JZ0yMuQJ27g36DipOUsqRAM0dR8KD1/ILHaHSE/w8DIx09E3g/BTce6rHUB5sAPKvfF+JdAAAAAElFTkSuQmCC'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.layersLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAmVBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+/v7///+bnZkkAAAAMnRSTlMABPr8ByiD88KsTi/rvJb272mjeUA1CuPe1M/KjVxYHxMP6KZ0S9nYzGRGGRaznpGIbzaGUf0AAAHESURBVDjLbZLZYoIwEEVDgLCjbKIgAlqXqt3m/z+uNwu1rcyDhjl3ktnYL7OY254C0VX3yWFZfzDrOClbbgKxi0YDHjwl4jbnRkXxJS/C1YP3DbBhD1n7Ex4uaAqdVDb3yJ/4J/3nJD2to/ngQz/DfUvzMp4JJ5sSCaF5oXmemgQDfDxzbi+Kq4sU+vNcuAmx94JtyOP2DD4Epz2asWSCz4Z/4fECxyNj9zC9xNLHcdPEO+awDKeSaUu0W4twZQiO2hYVisTR3RCtK/c1X6t4xMEpiGqXqVntEBLolkZZsKY4QtwH6jzq67dEHlJysB1aNOD3XT7n1UkasQN59L4yC2RELMDSeCRtz3yV22Ub3ozIUTknYx8JWqDdQxbUes98cR2kZtUSveF/bAhcedwEWmlxIkpZUy4XOCb6VBjjxHvbwo/1lBAHHi2JCr0NI570QhyHq/DhJoE2lLgyA4RVe6KmZ47O/3b86MCP0HWa73A8/C3SUc5Qc1ajt6fgpXJ+RGpMvDSchepZDOOQRcZVIKcK90x2D7etqtI+56+u6n3sPriO6nfphitR4+O2m3EbM7lh3me1FM1o+LMI887rN+s3/wZdTFlpNVJiOAAAAABJRU5ErkJggg=='; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.closeLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAUVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////8IN+deAAAAGnRSTlMAuvAIg/dDM/QlOeuFhj0S5s4vKgzjxJRQNiLSey0AAADNSURBVDjLfZLbEoMgDEQjRRRs1XqX///QNmOHJSnjPkHOGR7IEmeoGtJZstnwjqbRfIsmgEdtPCqe9Ynz7ZSc07rE2QiSc+qv8TvjRXA2PDUm3dpe82iJhOEUfxJJo3aCv+jKmRmH4lcCjCjeh9GWOdL/GZZkXH3PYYDrHBnfc4D/RVZf5sjoC1was+Y6HQxwaUxFvq/a0Pv343VCTxfBSRiB+ab3M3eiQZXmMNBJ3Y8pGRZtYQ7DgHMXJEdPLTaN/qBjzJOBc3nmNcbsA16bMR0oLqf+AAAAAElFTkSuQmCC'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.editLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAgVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9d3yJTAAAAKnRSTlMA+hzi3nRQWyXzkm0h2j3u54gzEgSXjlYoTBgJxL2loGpAOS3Jt7Wxm35Ga7gRAAAA6UlEQVQ4y63Q2XaCMBSF4Q0JBasoQ5DJqbXjfv8HbCK2BZNwo/8FXHx7rcMC7lQu0iX8qU/qtvAWCpoqH8dYzS0SwaV5eK/UAf8X9pd2CWKzuF5Jrftp1owXwnIGLUaL3PYndOHf4kNNXWrXK/m7CHunk7K8LE6YtBpcknwG9GKxnroY+ylBXcx4xKyx/u/EuXi509cP9V7OO1oyHnzrdFTcqLG/4ibBA5pIMr/4xvKzuQDkVy9wW8SgBFD6HDvuzMvrZcC9QlkfMzI7w64m+b4PqBMNHB05lH21PVxJo2/fBXxV4hB38PcD+5AkI4FuETsAAAAASUVORK5CYII='; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.previousLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMA7fci493c0MW8uJ6CZks4MxQHEZL6ewAAAFZJREFUOMvdkskRgDAMA4lDwg2B7b9XOlge/KKvdsa25KFb5XlRvxXC/DNBEv8IFNjBgGdDgXtFgTyhwDXiQAUHCvwa4Uv6mR6UR+1led2mVonvl+tML45qCQNQLIx7AAAAAElFTkSuQmCC'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.nextLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAPFBMVEUAAAD////////////////////////////////////////////////////////////////////////////YSWgTAAAAE3RSTlMA7fci493c0MW8uJ6CZks4MxQHEZL6ewAAAFRJREFUOMvd0skRgCAQBVEFwQ0V7fxzNQP6wI05v6pZ/kyj1b7FNgik2gQzzLcAwiUAigHOTwDHK4A1CmB5BJANJG1hQ9qafYcqFlZP3IFc9eVGrR+iIgkDQRUXIAAAAABJRU5ErkJggg=='; - -/** - * Specifies the image to be used for the refresh button. - */ -Editor.refreshLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAolBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8ELnaCAAAANXRSTlMABfyE2QKU+dfNyyDyoVYKwnTv7N+6rntsYlFNQjEqEw316uSzf2c1JB3GvqebiVw6GAjQB4DQr10AAAE7SURBVDjLvZLXcoMwEABPIgRCx3TT3A3udqL//7UgAdGRcR4yk8k+idsdmgS/QyWEqD/axS2JDV33zlnzLHIzQ2MDq9OeJ3m8l76KKENYlxrmM/b65Ys1+8YxnTEZFIEY0vVhszFWfUGZDJpQTDznTgAe5k4XhQxILB7ruzBQn+kkyDXuHfRtjoYDEvH7J9Lz98dBZXXL94X0Ofco2PFlChKbjVzEdakoSlKjoNoqPYkJ/wUZAYwc+PpLj1Ei7+jdoBWlwQZoJv2H1w3CWgRvo7dd9DP5btgwCWz0M02+oVoxCcIWeY9PNmR6B++m9prMxYEISpCBYBlfy9bc745is7UUULAem1Ww7FfalsiA2uaJsgmWP3pQI9q9/yMLkaaHAp2fxhHff/cNq7dBdHXhGW7l+Mo2zU0Cf8knJ2xA0oJ8enwAAAAASUVORK5CYII='; - -/** - * Specifies the image to be used for the back button. - */ -Editor.backLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAclBMVEUAAAD////////////////+/v7////////////////////////////////////////////+/v7///////////////////////////////////////////////////////////////////////////////8vKLfTAAAAJXRSTlMACh7h9gby3NLIwzwZ55uVJgH57b+8tbCljYV1RRMQ46FrTzQw+vtxOQAAAJ5JREFUOMuF00cWgzAQA1DRDQFCbwFSdf8rZpdVrNH2z3tuMv7mldZQ2WN2yi8x+TT8JvyTkqvwpiKvwsOIrA1fWr+XGTklfj8dOQR+D3KyUF6QufBkJN0hfCazEv6sZBRCJDUcPasGKpu1RLtYE8lkHAPBQLoTsK/SfAyRw5FjAuhCzC2MSj0gJ+66lHatgXdKboD9tfREB5m9/+3iC9jHDYvsGNcUAAAAAElFTkSuQmCC'; - -/** - * Specifies the image to be used for the back button. - */ -Editor.fullscreenLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAllBMVEUAAAD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AJcWoAAAAMXRSTlMA+wIFxPWPCIb446tnUxmsoIykgxTe29jQnpKBe2MNsZhVTR/KyLuWbFhEPjUq7L9z+bQj+gAAAWxJREFUOMttk4l2gkAMRTODCO4FtQgIbnWpS9v8/881iZFh8R51NO8GJ+gAjMN8zuTRFSw04cIOHQcqFHH6oaQFGxf0jeBjEgB8Y52TpW9Ag4zB5QICWOtHrgwGuFZBcw+gPP0MFS7+iiD5inOmDIQS9sZgTwUzwEzyxhxHVEEU7NdDUXsqUPtqjIgR2IZSCT4upzSeIeOdcMHnfDsx3giPoezfU6MrQGB5//SckLEG2xYscK4GfnUFqaix39zrwooaOD/cXoYuvHKQIc7pzd3HVPusp6t2FAW/RmjMonbl8vwHDeZo/GkleJC7e+p5XA/rAq1X/V10wKag04rBpa2/d0LL4OYYceOEtsG5jyMntI1wS+N1BGcQBl/CoLoPOl9ABrW/BP53e1bwSJHHlkIVchJwmHwyyfJ4kIvEnKtwkxNSEct83KSChT7WiWgDZ3ccZ0BM4tloJow2YUAtifNT3njnyD+y/pMsnP4DN3Y4yl1Gyk0AAAAASUVORK5CYII='; - -/** - * All fill styles supported by rough.js. - */ -Editor.roughFillStyles = [{val: 'auto', dispName: 'Auto'}, {val: 'hachure', dispName: 'Hachure'}, {val: 'solid', dispName: 'Solid'}, - {val: 'zigzag', dispName: 'ZigZag'}, {val: 'cross-hatch', dispName: 'Cross Hatch'}, {val: 'dots', dispName: 'Dots'}, - {val: 'dashed', dispName: 'Dashed'}, {val: 'zigzag-line', dispName: 'ZigZag Line'}]; - -/** - * Graph themes for the format panel. - */ -Editor.themes = null; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.ctrlKey = (mxClient.IS_MAC) ? 'Cmd' : 'Ctrl'; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.hintOffset = 20; - -/** - * Specifies if the diagram should be saved automatically if possible. Default - * is true. - */ -Editor.popupsAllowed = true; - -/** - * Editor inherits from mxEventSource - */ -mxUtils.extend(Editor, mxEventSource); - -/** - * Stores initial state of mxClient.NO_FO. - */ -Editor.prototype.originalNoForeignObject = mxClient.NO_FO; - -/** - * Specifies the image URL to be used for the transparent background. - */ -Editor.prototype.transparentImage = (mxClient.IS_SVG) ? 'data:image/gif;base64,R0lGODlhMAAwAIAAAP///wAAACH5BAEAAAAALAAAAAAwADAAAAIxhI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8egpAAA7' : - IMAGE_PATH + '/transparent.gif'; - -/** - * Specifies if the canvas should be extended in all directions. Default is true. - */ -Editor.prototype.extendCanvas = true; - -/** - * Specifies if the app should run in chromeless mode. Default is false. - * This default is only used if the contructor argument is null. - */ -Editor.prototype.chromeless = false; - -/** - * Specifies the order of OK/Cancel buttons in dialogs. Default is true. - * Cancel first is used on Macs, Windows/Confluence uses cancel last. - */ -Editor.prototype.cancelFirst = true; - -/** - * Specifies if the editor is enabled. Default is true. - */ -Editor.prototype.enabled = true; - -/** - * Contains the name which was used for the last save. Default value is null. - */ -Editor.prototype.filename = null; - -/** - * Contains the current modified state of the diagram. This is false for - * new diagrams and after the diagram was saved. - */ -Editor.prototype.modified = false; - -/** - * Specifies if the diagram should be saved automatically if possible. Default - * is true. - */ -Editor.prototype.autosave = true; - -/** - * Specifies the top spacing for the initial page view. Default is 0. - */ -Editor.prototype.initialTopSpacing = 0; - -/** - * Specifies the app name. Default is document.title. - */ -Editor.prototype.appName = document.title; - -/** - * - */ -Editor.prototype.editBlankUrl = window.location.protocol + '//' + window.location.host + '/'; - -/** - * Default value for the graph container overflow style. - */ -Editor.prototype.defaultGraphOverflow = 'hidden'; - -/** - * Initializes the environment. - */ -Editor.prototype.init = function() { }; - -/** - * Sets the XML node for the current diagram. - */ -Editor.prototype.isChromelessView = function() -{ - return this.chromeless; -}; - -/** - * Sets the XML node for the current diagram. - */ -Editor.prototype.setAutosave = function(value) -{ - this.autosave = value; - this.fireEvent(new mxEventObject('autosaveChanged')); -}; - -/** - * - */ -Editor.prototype.getEditBlankUrl = function(params) -{ - return this.editBlankUrl + params; -} - -/** - * - */ -Editor.prototype.editAsNew = function(xml, title) -{ - var p = (title != null) ? '?title=' + encodeURIComponent(title) : ''; - - if (urlParams['ui'] != null) - { - p += ((p.length > 0) ? '&' : '?') + 'ui=' + urlParams['ui']; - } - - if (typeof window.postMessage !== 'undefined' && - (document.documentMode == null || - document.documentMode >= 10)) - { - var wnd = null; - - var l = mxUtils.bind(this, function(evt) - { - if (evt.data == 'ready' && evt.source == wnd) - { - mxEvent.removeListener(window, 'message', l); - wnd.postMessage(xml, '*'); - } - }); - - mxEvent.addListener(window, 'message', l); - wnd = this.graph.openLink(this.getEditBlankUrl( - p + ((p.length > 0) ? '&' : '?') + - 'client=1'), null, true); - } - else - { - this.graph.openLink(this.getEditBlankUrl(p) + - '#R' + encodeURIComponent(xml)); - } -}; - -/** - * Sets the XML node for the current diagram. - */ -Editor.prototype.createGraph = function(themes, model) -{ - var graph = new Graph(null, model, null, null, themes); - graph.transparentBackground = false; - - // Opens all links in a new window while editing - if (!this.chromeless) - { - graph.isBlankLink = function(href) - { - return !this.isExternalProtocol(href); - }; - } - - return graph; -}; - -/** - * Sets the XML node for the current diagram. - */ -Editor.prototype.resetGraph = function() -{ - this.graph.gridEnabled = !this.isChromelessView() || urlParams['grid'] == '1'; - this.graph.graphHandler.guidesEnabled = true; - this.graph.setTooltips(true); - this.graph.setConnectable(true); - this.graph.foldingEnabled = true; - this.graph.scrollbars = this.graph.defaultScrollbars; - this.graph.pageVisible = this.graph.defaultPageVisible; - this.graph.pageBreaksVisible = this.graph.pageVisible; - this.graph.preferPageSize = this.graph.pageBreaksVisible; - this.graph.background = null; - this.graph.pageScale = mxGraph.prototype.pageScale; - this.graph.pageFormat = mxGraph.prototype.pageFormat; - this.graph.currentScale = 1; - this.graph.currentTranslate.x = 0; - this.graph.currentTranslate.y = 0; - this.updateGraphComponents(); - this.graph.view.setScale(1); -}; - -/** - * Sets the XML node for the current diagram. - */ -Editor.prototype.readGraphState = function(node) -{ - this.graph.gridEnabled = node.getAttribute('grid') != '0' && (!this.isChromelessView() || urlParams['grid'] == '1'); - this.graph.gridSize = parseFloat(node.getAttribute('gridSize')) || mxGraph.prototype.gridSize; - this.graph.graphHandler.guidesEnabled = node.getAttribute('guides') != '0'; - this.graph.setTooltips(node.getAttribute('tooltips') != '0'); - this.graph.setConnectable(node.getAttribute('connect') != '0'); - this.graph.connectionArrowsEnabled = node.getAttribute('arrows') != '0'; - this.graph.foldingEnabled = node.getAttribute('fold') != '0'; - - if (this.isChromelessView() && this.graph.foldingEnabled) - { - this.graph.foldingEnabled = urlParams['nav'] == '1'; - this.graph.cellRenderer.forceControlClickHandler = this.graph.foldingEnabled; - } - - var ps = parseFloat(node.getAttribute('pageScale')); - - if (!isNaN(ps) && ps > 0) - { - this.graph.pageScale = ps; - } - else - { - this.graph.pageScale = mxGraph.prototype.pageScale; - } - - if (!this.graph.isLightboxView() && !this.graph.isViewer()) - { - var pv = node.getAttribute('page'); - - if (pv != null) - { - this.graph.pageVisible = (pv != '0'); - } - else - { - this.graph.pageVisible = this.graph.defaultPageVisible; - } - } - else - { - this.graph.pageVisible = false; - } - - this.graph.pageBreaksVisible = this.graph.pageVisible; - this.graph.preferPageSize = this.graph.pageBreaksVisible; - - var pw = parseFloat(node.getAttribute('pageWidth')); - var ph = parseFloat(node.getAttribute('pageHeight')); - - if (!isNaN(pw) && !isNaN(ph)) - { - this.graph.pageFormat = new mxRectangle(0, 0, pw, ph); - } - - // Loads the persistent state settings - var bg = node.getAttribute('background'); - - if (bg != null && bg.length > 0) - { - this.graph.background = bg; - } - else - { - this.graph.background = null; - } -}; - -/** - * Sets the XML node for the current diagram. - */ -Editor.prototype.setGraphXml = function(node) -{ - if (node != null) - { - var dec = new mxCodec(node.ownerDocument); - - if (node.nodeName == 'mxGraphModel') - { - this.graph.model.beginUpdate(); - - try - { - this.graph.model.clear(); - this.graph.view.scale = 1; - this.readGraphState(node); - this.updateGraphComponents(); - dec.decode(node, this.graph.getModel()); - } - finally - { - this.graph.model.endUpdate(); - } - - this.fireEvent(new mxEventObject('resetGraphView')); - } - else if (node.nodeName == 'root') - { - this.resetGraph(); - - // Workaround for invalid XML output in Firefox 20 due to bug in mxUtils.getXml - var wrapper = dec.document.createElement('mxGraphModel'); - wrapper.appendChild(node); - - dec.decode(wrapper, this.graph.getModel()); - this.updateGraphComponents(); - this.fireEvent(new mxEventObject('resetGraphView')); - } - else - { - throw { - message: mxResources.get('cannotOpenFile'), - node: node, - toString: function() { return this.message; } - }; - } - } - else - { - this.resetGraph(); - this.graph.model.clear(); - this.fireEvent(new mxEventObject('resetGraphView')); - } -}; - -/** - * Returns the XML node that represents the current diagram. - */ -Editor.prototype.getGraphXml = function(ignoreSelection) -{ - ignoreSelection = (ignoreSelection != null) ? ignoreSelection : true; - var node = null; - - if (ignoreSelection) - { - var enc = new mxCodec(mxUtils.createXmlDocument()); - node = enc.encode(this.graph.getModel()); - } - else - { - node = this.graph.encodeCells(mxUtils.sortCells(this.graph.model.getTopmostCells( - this.graph.getSelectionCells()))); - } - - if (this.graph.view.translate.x != 0 || this.graph.view.translate.y != 0) - { - node.setAttribute('dx', Math.round(this.graph.view.translate.x * 100) / 100); - node.setAttribute('dy', Math.round(this.graph.view.translate.y * 100) / 100); - } - - node.setAttribute('grid', (this.graph.isGridEnabled()) ? '1' : '0'); - node.setAttribute('gridSize', this.graph.gridSize); - node.setAttribute('guides', (this.graph.graphHandler.guidesEnabled) ? '1' : '0'); - node.setAttribute('tooltips', (this.graph.tooltipHandler.isEnabled()) ? '1' : '0'); - node.setAttribute('connect', (this.graph.connectionHandler.isEnabled()) ? '1' : '0'); - node.setAttribute('arrows', (this.graph.connectionArrowsEnabled) ? '1' : '0'); - node.setAttribute('fold', (this.graph.foldingEnabled) ? '1' : '0'); - node.setAttribute('page', (this.graph.pageVisible) ? '1' : '0'); - node.setAttribute('pageScale', this.graph.pageScale); - node.setAttribute('pageWidth', this.graph.pageFormat.width); - node.setAttribute('pageHeight', this.graph.pageFormat.height); - - if (this.graph.background != null) - { - node.setAttribute('background', this.graph.background); - } - - return node; -}; - -/** - * Keeps the graph container in sync with the persistent graph state - */ -Editor.prototype.updateGraphComponents = function() -{ - var graph = this.graph; - - if (graph.container != null) - { - graph.view.validateBackground(); - graph.container.style.overflow = (graph.scrollbars) ? 'auto' : this.defaultGraphOverflow; - - this.fireEvent(new mxEventObject('updateGraphComponents')); - } -}; - -/** - * Sets the modified flag. - */ -Editor.prototype.setModified = function(value) -{ - this.modified = value; -}; - -/** - * Sets the filename. - */ -Editor.prototype.setFilename = function(value) -{ - this.filename = value; -}; - -/** - * Creates and returns a new undo manager. - */ -Editor.prototype.createUndoManager = function() -{ - var graph = this.graph; - var undoMgr = new mxUndoManager(); - - this.undoListener = function(sender, evt) - { - undoMgr.undoableEditHappened(evt.getProperty('edit')); - }; - - // Installs the command history - var listener = mxUtils.bind(this, function(sender, evt) - { - this.undoListener.apply(this, arguments); - }); - - graph.getModel().addListener(mxEvent.UNDO, listener); - graph.getView().addListener(mxEvent.UNDO, listener); - - // Keeps the selection in sync with the history - var undoHandler = function(sender, evt) - { - var cand = graph.getSelectionCellsForChanges(evt.getProperty('edit').changes, function(change) - { - // Only selects changes to the cell hierarchy - return !(change instanceof mxChildChange); - }); - - if (cand.length > 0) - { - var model = graph.getModel(); - var cells = []; - - for (var i = 0; i < cand.length; i++) - { - if (graph.view.getState(cand[i]) != null) - { - cells.push(cand[i]); - } - } - - graph.setSelectionCells(cells); - } - }; - - undoMgr.addListener(mxEvent.UNDO, undoHandler); - undoMgr.addListener(mxEvent.REDO, undoHandler); - - return undoMgr; -}; - -/** - * Adds basic stencil set (no namespace). - */ -Editor.prototype.initStencilRegistry = function() { }; - -/** - * Creates and returns a new undo manager. - */ -Editor.prototype.destroy = function() -{ - if (this.graph != null) - { - this.graph.destroy(); - this.graph = null; - } -}; - -/** - * Class for asynchronously opening a new window and loading a file at the same - * time. This acts as a bridge between the open dialog and the new editor. - */ -OpenFile = function(done) -{ - this.producer = null; - this.consumer = null; - this.done = done; - this.args = null; -}; - -/** - * Registers the editor from the new window. - */ -OpenFile.prototype.setConsumer = function(value) -{ - this.consumer = value; - this.execute(); -}; - -/** - * Sets the data from the loaded file. - */ -OpenFile.prototype.setData = function() -{ - this.args = arguments; - this.execute(); -}; - -/** - * Displays an error message. - */ -OpenFile.prototype.error = function(msg) -{ - this.cancel(true); - mxUtils.alert(msg); -}; - -/** - * Consumes the data. - */ -OpenFile.prototype.execute = function() -{ - if (this.consumer != null && this.args != null) - { - this.cancel(false); - this.consumer.apply(this, this.args); - } -}; - -/** - * Cancels the operation. - */ -OpenFile.prototype.cancel = function(cancel) -{ - if (this.done != null) - { - this.done((cancel != null) ? cancel : true); - } -}; - -/** - * Basic dialogs that are available in the viewer (print dialog). - */ -function Dialog(editorUi, elt, w, h, modal, closable, onClose, noScroll, transparent, onResize, ignoreBgClick) -{ - var dx = 0; - - if (mxClient.IS_VML && (document.documentMode == null || document.documentMode < 8)) - { - // Adds padding as a workaround for box model in older IE versions - // This needs to match the total padding of geDialog in CSS - dx = 80; - } - - w += dx; - h += dx; - - var w0 = w; - var h0 = h; - - var ds = mxUtils.getDocumentSize(); - - // Workaround for print dialog offset in viewer lightbox - if (window.innerHeight != null) - { - ds.height = window.innerHeight; - } - - var dh = ds.height; - var left = Math.max(1, Math.round((ds.width - w - 64) / 2)); - var top = Math.max(1, Math.round((dh - h - editorUi.footerHeight) / 3)); - - // Keeps window size inside available space - if (!mxClient.IS_QUIRKS) - { - elt.style.maxHeight = '100%'; - } - - w = (document.body != null) ? Math.min(w, document.body.scrollWidth - 64) : w; - h = Math.min(h, dh - 64); - - // Increments zIndex to put subdialogs and background over existing dialogs and background - if (editorUi.dialogs.length > 0) - { - this.zIndex += editorUi.dialogs.length * 2; - } - - if (this.bg == null) - { - this.bg = editorUi.createDiv('background'); - this.bg.style.position = 'absolute'; - this.bg.style.background = Dialog.backdropColor; - this.bg.style.height = dh + 'px'; - this.bg.style.right = '0px'; - this.bg.style.zIndex = this.zIndex - 2; - - mxUtils.setOpacity(this.bg, this.bgOpacity); - - if (mxClient.IS_QUIRKS) - { - new mxDivResizer(this.bg); - } - } - - var origin = mxUtils.getDocumentScrollOrigin(document); - this.bg.style.left = origin.x + 'px'; - this.bg.style.top = origin.y + 'px'; - left += origin.x; - top += origin.y; - - if (modal) - { - document.body.appendChild(this.bg); - } - - var div = editorUi.createDiv(transparent? 'geTransDialog' : 'geDialog'); - var pos = this.getPosition(left, top, w, h); - left = pos.x; - top = pos.y; - - div.style.width = w + 'px'; - div.style.height = h + 'px'; - div.style.left = left + 'px'; - div.style.top = top + 'px'; - div.style.zIndex = this.zIndex; - - div.appendChild(elt); - document.body.appendChild(div); - - // Adds vertical scrollbars if needed - if (!noScroll && elt.clientHeight > div.clientHeight - 64) - { - elt.style.overflowY = 'auto'; - } - - if (closable) - { - var img = document.createElement('img'); - - img.setAttribute('src', Dialog.prototype.closeImage); - img.setAttribute('title', mxResources.get('close')); - img.className = 'geDialogClose'; - img.style.top = (top + 14) + 'px'; - img.style.left = (left + w + 38 - dx) + 'px'; - img.style.zIndex = this.zIndex; - - mxEvent.addListener(img, 'click', mxUtils.bind(this, function() - { - editorUi.hideDialog(true); - })); - - document.body.appendChild(img); - this.dialogImg = img; - - if (!ignoreBgClick) - { - var mouseDownSeen = false; - - mxEvent.addGestureListeners(this.bg, mxUtils.bind(this, function(evt) - { - mouseDownSeen = true; - }), null, mxUtils.bind(this, function(evt) - { - if (mouseDownSeen) - { - editorUi.hideDialog(true); - mouseDownSeen = false; - } - })); - } - } - - this.resizeListener = mxUtils.bind(this, function() - { - if (onResize != null) - { - var newWH = onResize(); - - if (newWH != null) - { - w0 = w = newWH.w; - h0 = h = newWH.h; - } - } - - var ds = mxUtils.getDocumentSize(); - dh = ds.height; - this.bg.style.height = dh + 'px'; - - left = Math.max(1, Math.round((ds.width - w - 64) / 2)); - top = Math.max(1, Math.round((dh - h - editorUi.footerHeight) / 3)); - w = (document.body != null) ? Math.min(w0, document.body.scrollWidth - 64) : w0; - h = Math.min(h0, dh - 64); - - var pos = this.getPosition(left, top, w, h); - left = pos.x; - top = pos.y; - - div.style.left = left + 'px'; - div.style.top = top + 'px'; - div.style.width = w + 'px'; - div.style.height = h + 'px'; - - // Adds vertical scrollbars if needed - if (!noScroll && elt.clientHeight > div.clientHeight - 64) - { - elt.style.overflowY = 'auto'; - } - - if (this.dialogImg != null) - { - this.dialogImg.style.top = (top + 14) + 'px'; - this.dialogImg.style.left = (left + w + 38 - dx) + 'px'; - } - }); - - mxEvent.addListener(window, 'resize', this.resizeListener); - - this.onDialogClose = onClose; - this.container = div; - - editorUi.editor.fireEvent(new mxEventObject('showDialog')); -}; - -/** - * - */ -Dialog.backdropColor = 'white'; - -/** - * - */ -Dialog.prototype.zIndex = mxPopupMenu.prototype.zIndex - 1; - -/** - * - */ -Dialog.prototype.noColorImage = (!mxClient.IS_SVG) ? IMAGE_PATH + '/nocolor.png' : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkEzRDlBMUUwODYxMTExRTFCMzA4RDdDMjJBMEMxRDM3IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkEzRDlBMUUxODYxMTExRTFCMzA4RDdDMjJBMEMxRDM3Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTNEOUExREU4NjExMTFFMUIzMDhEN0MyMkEwQzFEMzciIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTNEOUExREY4NjExMTFFMUIzMDhEN0MyMkEwQzFEMzciLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5xh3fmAAAABlBMVEX////MzMw46qqDAAAAGElEQVR42mJggAJGKGAYIIGBth8KAAIMAEUQAIElnLuQAAAAAElFTkSuQmCC'; - -/** - * - */ -Dialog.prototype.closeImage = (!mxClient.IS_SVG) ? IMAGE_PATH + '/close.png' : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJAQMAAADaX5RTAAAABlBMVEV7mr3///+wksspAAAAAnRSTlP/AOW3MEoAAAAdSURBVAgdY9jXwCDDwNDRwHCwgeExmASygSL7GgB12QiqNHZZIwAAAABJRU5ErkJggg=='; - -/** - * - */ -Dialog.prototype.clearImage = (!mxClient.IS_SVG) ? IMAGE_PATH + '/clear.gif' : 'data:image/gif;base64,R0lGODlhDQAKAIABAMDAwP///yH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUIzOEM1NzI4NjEyMTFFMUEzMkNDMUE3NjZERDE2QjIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUIzOEM1NzM4NjEyMTFFMUEzMkNDMUE3NjZERDE2QjIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QjM4QzU3MDg2MTIxMUUxQTMyQ0MxQTc2NkREMTZCMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QjM4QzU3MTg2MTIxMUUxQTMyQ0MxQTc2NkREMTZCMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAAEALAAAAAANAAoAAAIXTGCJebD9jEOTqRlttXdrB32PJ2ncyRQAOw=='; - -/** - * - */ -Dialog.prototype.lockedImage = (!mxClient.IS_SVG) ? IMAGE_PATH + '/locked.png' : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAMAAABhq6zVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzdDMDZCODExNzIxMTFFNUI0RTk5NTg4OTcyMUUyODEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzdDMDZCODIxNzIxMTFFNUI0RTk5NTg4OTcyMUUyODEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozN0MwNkI3RjE3MjExMUU1QjRFOTk1ODg5NzIxRTI4MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozN0MwNkI4MDE3MjExMUU1QjRFOTk1ODg5NzIxRTI4MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvqMCFYAAAAVUExURZmZmb+/v7KysqysrMzMzLGxsf///4g8N1cAAAAHdFJOU////////wAaSwNGAAAAPElEQVR42lTMQQ4AIQgEwUa0//9kTQirOweYOgDqAMbZUr10AGlAwx4/BJ2QJ4U0L5brYjovvpv32xZgAHZaATFtMbu4AAAAAElFTkSuQmCC'; - -/** - * - */ -Dialog.prototype.unlockedImage = (!mxClient.IS_SVG) ? IMAGE_PATH + '/unlocked.png' : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAMAAABhq6zVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzdDMDZCN0QxNzIxMTFFNUI0RTk5NTg4OTcyMUUyODEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzdDMDZCN0UxNzIxMTFFNUI0RTk5NTg4OTcyMUUyODEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozN0MwNkI3QjE3MjExMUU1QjRFOTk1ODg5NzIxRTI4MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozN0MwNkI3QzE3MjExMUU1QjRFOTk1ODg5NzIxRTI4MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkKMpVwAAAAYUExURZmZmbKysr+/v6ysrOXl5czMzLGxsf///zHN5lwAAAAIdFJOU/////////8A3oO9WQAAADxJREFUeNpUzFESACAEBNBVsfe/cZJU+8Mzs8CIABCidtfGOndnYsT40HDSiCcbPdoJo10o9aI677cpwACRoAF3dFNlswAAAABJRU5ErkJggg=='; - -/** - * Removes the dialog from the DOM. - */ -Dialog.prototype.bgOpacity = 80; - -/** - * Removes the dialog from the DOM. - */ -Dialog.prototype.getPosition = function(left, top) -{ - return new mxPoint(left, top); -}; - -/** - * Removes the dialog from the DOM. - */ -Dialog.prototype.close = function(cancel, isEsc) -{ - if (this.onDialogClose != null) - { - if (this.onDialogClose(cancel, isEsc) == false) - { - return false; - } - - this.onDialogClose = null; - } - - if (this.dialogImg != null) - { - this.dialogImg.parentNode.removeChild(this.dialogImg); - this.dialogImg = null; - } - - if (this.bg != null && this.bg.parentNode != null) - { - this.bg.parentNode.removeChild(this.bg); - } - - mxEvent.removeListener(window, 'resize', this.resizeListener); - this.container.parentNode.removeChild(this.container); -}; - -/** - * - */ -var ErrorDialog = function(editorUi, title, message, buttonText, fn, retry, buttonText2, fn2, hide, buttonText3, fn3) -{ - hide = (hide != null) ? hide : true; - - var div = document.createElement('div'); - div.style.textAlign = 'center'; - - if (title != null) - { - var hd = document.createElement('div'); - hd.style.padding = '0px'; - hd.style.margin = '0px'; - hd.style.fontSize = '18px'; - hd.style.paddingBottom = '16px'; - hd.style.marginBottom = '10px'; - hd.style.borderBottom = '1px solid #c0c0c0'; - hd.style.color = 'gray'; - hd.style.whiteSpace = 'nowrap'; - hd.style.textOverflow = 'ellipsis'; - hd.style.overflow = 'hidden'; - mxUtils.write(hd, title); - hd.setAttribute('title', title); - div.appendChild(hd); - } - - var p2 = document.createElement('div'); - p2.style.lineHeight = '1.2em'; - p2.style.padding = '6px'; - p2.innerHTML = message; - div.appendChild(p2); - - var btns = document.createElement('div'); - btns.style.marginTop = '12px'; - btns.style.textAlign = 'center'; - - if (retry != null) - { - var retryBtn = mxUtils.button(mxResources.get('tryAgain'), function() - { - editorUi.hideDialog(); - retry(); - }); - retryBtn.className = 'geBtn'; - btns.appendChild(retryBtn); - - btns.style.textAlign = 'center'; - } - - if (buttonText3 != null) - { - var btn3 = mxUtils.button(buttonText3, function() - { - if (fn3 != null) - { - fn3(); - } - }); - - btn3.className = 'geBtn'; - btns.appendChild(btn3); - } - - var btn = mxUtils.button(buttonText, function() - { - if (hide) - { - editorUi.hideDialog(); - } - - if (fn != null) - { - fn(); - } - }); - - btn.className = 'geBtn'; - btns.appendChild(btn); - - if (buttonText2 != null) - { - var mainBtn = mxUtils.button(buttonText2, function() - { - if (hide) - { - editorUi.hideDialog(); - } - - if (fn2 != null) - { - fn2(); - } - }); - - mainBtn.className = 'geBtn gePrimaryBtn'; - btns.appendChild(mainBtn); - } - - this.init = function() - { - btn.focus(); - }; - - div.appendChild(btns); - - this.container = div; -}; - -/** - * Constructs a new print dialog. - */ -var PrintDialog = function(editorUi, title) -{ - this.create(editorUi, title); -}; - -/** - * Constructs a new print dialog. - */ -PrintDialog.prototype.create = function(editorUi) -{ - var graph = editorUi.editor.graph; - var row, td; - - var table = document.createElement('table'); - table.style.width = '100%'; - table.style.height = '100%'; - var tbody = document.createElement('tbody'); - - row = document.createElement('tr'); - - var onePageCheckBox = document.createElement('input'); - onePageCheckBox.setAttribute('type', 'checkbox'); - td = document.createElement('td'); - td.setAttribute('colspan', '2'); - td.style.fontSize = '10pt'; - td.appendChild(onePageCheckBox); - - var span = document.createElement('span'); - mxUtils.write(span, ' ' + mxResources.get('fitPage')); - td.appendChild(span); - - mxEvent.addListener(span, 'click', function(evt) - { - onePageCheckBox.checked = !onePageCheckBox.checked; - pageCountCheckBox.checked = !onePageCheckBox.checked; - mxEvent.consume(evt); - }); - - mxEvent.addListener(onePageCheckBox, 'change', function() - { - pageCountCheckBox.checked = !onePageCheckBox.checked; - }); - - row.appendChild(td); - tbody.appendChild(row); - - row = row.cloneNode(false); - - var pageCountCheckBox = document.createElement('input'); - pageCountCheckBox.setAttribute('type', 'checkbox'); - td = document.createElement('td'); - td.style.fontSize = '10pt'; - td.appendChild(pageCountCheckBox); - - var span = document.createElement('span'); - mxUtils.write(span, ' ' + mxResources.get('posterPrint') + ':'); - td.appendChild(span); - - mxEvent.addListener(span, 'click', function(evt) - { - pageCountCheckBox.checked = !pageCountCheckBox.checked; - onePageCheckBox.checked = !pageCountCheckBox.checked; - mxEvent.consume(evt); - }); - - row.appendChild(td); - - var pageCountInput = document.createElement('input'); - pageCountInput.setAttribute('value', '1'); - pageCountInput.setAttribute('type', 'number'); - pageCountInput.setAttribute('min', '1'); - pageCountInput.setAttribute('size', '4'); - pageCountInput.setAttribute('disabled', 'disabled'); - pageCountInput.style.width = '50px'; - - td = document.createElement('td'); - td.style.fontSize = '10pt'; - td.appendChild(pageCountInput); - mxUtils.write(td, ' ' + mxResources.get('pages') + ' (max)'); - row.appendChild(td); - tbody.appendChild(row); - - mxEvent.addListener(pageCountCheckBox, 'change', function() - { - if (pageCountCheckBox.checked) - { - pageCountInput.removeAttribute('disabled'); - } - else - { - pageCountInput.setAttribute('disabled', 'disabled'); - } - - onePageCheckBox.checked = !pageCountCheckBox.checked; - }); - - row = row.cloneNode(false); - - td = document.createElement('td'); - mxUtils.write(td, mxResources.get('pageScale') + ':'); - row.appendChild(td); - - td = document.createElement('td'); - var pageScaleInput = document.createElement('input'); - pageScaleInput.setAttribute('value', '100 %'); - pageScaleInput.setAttribute('size', '5'); - pageScaleInput.style.width = '50px'; - - td.appendChild(pageScaleInput); - row.appendChild(td); - tbody.appendChild(row); - - row = document.createElement('tr'); - td = document.createElement('td'); - td.colSpan = 2; - td.style.paddingTop = '20px'; - td.setAttribute('align', 'right'); - - // Overall scale for print-out to account for print borders in dialogs etc - function preview(print) - { - var autoOrigin = onePageCheckBox.checked || pageCountCheckBox.checked; - var printScale = parseInt(pageScaleInput.value) / 100; - - if (isNaN(printScale)) - { - printScale = 1; - pageScaleInput.value = '100%'; - } - - // Workaround to match available paper size in actual print output - printScale *= 0.75; - - var pf = graph.pageFormat || mxConstants.PAGE_FORMAT_A4_PORTRAIT; - var scale = 1 / graph.pageScale; - - if (autoOrigin) - { - var pageCount = (onePageCheckBox.checked) ? 1 : parseInt(pageCountInput.value); - - if (!isNaN(pageCount)) - { - scale = mxUtils.getScaleForPageCount(pageCount, graph, pf); - } - } - - // Negative coordinates are cropped or shifted if page visible - var gb = graph.getGraphBounds(); - var border = 0; - var x0 = 0; - var y0 = 0; - - // Applies print scale - pf = mxRectangle.fromRectangle(pf); - pf.width = Math.ceil(pf.width * printScale); - pf.height = Math.ceil(pf.height * printScale); - scale *= printScale; - - // Starts at first visible page - if (!autoOrigin && graph.pageVisible) - { - var layout = graph.getPageLayout(); - x0 -= layout.x * pf.width; - y0 -= layout.y * pf.height; - } - else - { - autoOrigin = true; - } - - var preview = PrintDialog.createPrintPreview(graph, scale, pf, border, x0, y0, autoOrigin); - preview.open(); - - if (print) - { - PrintDialog.printPreview(preview); - } - }; - - var cancelBtn = mxUtils.button(mxResources.get('cancel'), function() - { - editorUi.hideDialog(); - }); - cancelBtn.className = 'geBtn'; - - if (editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - } - - if (PrintDialog.previewEnabled) - { - var previewBtn = mxUtils.button(mxResources.get('preview'), function() - { - editorUi.hideDialog(); - preview(false); - }); - previewBtn.className = 'geBtn'; - td.appendChild(previewBtn); - } - - var printBtn = mxUtils.button(mxResources.get((!PrintDialog.previewEnabled) ? 'ok' : 'print'), function() - { - editorUi.hideDialog(); - preview(true); - }); - printBtn.className = 'geBtn gePrimaryBtn'; - td.appendChild(printBtn); - - if (!editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - } - - row.appendChild(td); - tbody.appendChild(row); - - table.appendChild(tbody); - this.container = table; -}; - -/** - * Constructs a new print dialog. - */ -PrintDialog.printPreview = function(preview) -{ - try - { - if (preview.wnd != null) - { - var printFn = function() - { - preview.wnd.focus(); - preview.wnd.print(); - preview.wnd.close(); - }; - - // Workaround for Google Chrome which needs a bit of a - // delay in order to render the SVG contents - // Needs testing in production - if (mxClient.IS_GC) - { - window.setTimeout(printFn, 500); - } - else - { - printFn(); - } - } - } - catch (e) - { - // ignores possible Access Denied - } -}; - -/** - * Constructs a new print dialog. - */ -PrintDialog.createPrintPreview = function(graph, scale, pf, border, x0, y0, autoOrigin) -{ - var preview = new mxPrintPreview(graph, scale, pf, border, x0, y0); - preview.title = mxResources.get('preview'); - preview.printBackgroundImage = true; - preview.autoOrigin = autoOrigin; - var bg = graph.background; - - if (bg == null || bg == '' || bg == mxConstants.NONE) - { - bg = '#ffffff'; - } - - preview.backgroundColor = bg; - - var writeHead = preview.writeHead; - - // Adds a border in the preview - preview.writeHead = function(doc) - { - writeHead.apply(this, arguments); - - doc.writeln(''); - }; - - return preview; -}; - -/** - * Specifies if the preview button should be enabled. Default is true. - */ -PrintDialog.previewEnabled = true; - -/** - * Constructs a new page setup dialog. - */ -var PageSetupDialog = function(editorUi) -{ - var graph = editorUi.editor.graph; - var row, td; - - var table = document.createElement('table'); - table.style.width = '100%'; - table.style.height = '100%'; - var tbody = document.createElement('tbody'); - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.verticalAlign = 'top'; - td.style.fontSize = '10pt'; - mxUtils.write(td, mxResources.get('paperSize') + ':'); - - row.appendChild(td); - - td = document.createElement('td'); - td.style.verticalAlign = 'top'; - td.style.fontSize = '10pt'; - - var accessor = PageSetupDialog.addPageFormatPanel(td, 'pagesetupdialog', graph.pageFormat); - - row.appendChild(td); - tbody.appendChild(row); - - row = document.createElement('tr'); - - td = document.createElement('td'); - mxUtils.write(td, mxResources.get('background') + ':'); - - row.appendChild(td); - - td = document.createElement('td'); - td.style.whiteSpace = 'nowrap'; - - var backgroundInput = document.createElement('input'); - backgroundInput.setAttribute('type', 'text'); - var backgroundButton = document.createElement('button'); - - backgroundButton.style.width = '18px'; - backgroundButton.style.height = '18px'; - backgroundButton.style.marginRight = '20px'; - backgroundButton.style.backgroundPosition = 'center center'; - backgroundButton.style.backgroundRepeat = 'no-repeat'; - - var newBackgroundColor = graph.background; - - function updateBackgroundColor() - { - if (newBackgroundColor == null || newBackgroundColor == mxConstants.NONE) - { - backgroundButton.style.backgroundColor = ''; - backgroundButton.style.backgroundImage = 'url(\'' + Dialog.prototype.noColorImage + '\')'; - } - else - { - backgroundButton.style.backgroundColor = newBackgroundColor; - backgroundButton.style.backgroundImage = ''; - } - }; - - updateBackgroundColor(); - - mxEvent.addListener(backgroundButton, 'click', function(evt) - { - editorUi.pickColor(newBackgroundColor || 'none', function(color) - { - newBackgroundColor = color; - updateBackgroundColor(); - }); - mxEvent.consume(evt); - }); - - td.appendChild(backgroundButton); - - mxUtils.write(td, mxResources.get('gridSize') + ':'); - - var gridSizeInput = document.createElement('input'); - gridSizeInput.setAttribute('type', 'number'); - gridSizeInput.setAttribute('min', '0'); - gridSizeInput.style.width = '40px'; - gridSizeInput.style.marginLeft = '6px'; - - gridSizeInput.value = graph.getGridSize(); - td.appendChild(gridSizeInput); - - mxEvent.addListener(gridSizeInput, 'change', function() - { - var value = parseInt(gridSizeInput.value); - gridSizeInput.value = Math.max(1, (isNaN(value)) ? graph.getGridSize() : value); - }); - - row.appendChild(td); - tbody.appendChild(row); - - row = document.createElement('tr'); - td = document.createElement('td'); - - mxUtils.write(td, mxResources.get('image') + ':'); - - row.appendChild(td); - td = document.createElement('td'); - - var changeImageLink = document.createElement('a'); - changeImageLink.style.textDecoration = 'underline'; - changeImageLink.style.cursor = 'pointer'; - changeImageLink.style.color = '#a0a0a0'; - - var newBackgroundImage = graph.backgroundImage; - - function updateBackgroundImage() - { - if (newBackgroundImage == null) - { - changeImageLink.removeAttribute('title'); - changeImageLink.style.fontSize = ''; - changeImageLink.innerHTML = mxUtils.htmlEntities(mxResources.get('change')) + '...'; - } - else - { - changeImageLink.setAttribute('title', newBackgroundImage.src); - changeImageLink.style.fontSize = '11px'; - changeImageLink.innerHTML = mxUtils.htmlEntities(newBackgroundImage.src.substring(0, 42)) + '...'; - } - }; - - mxEvent.addListener(changeImageLink, 'click', function(evt) - { - editorUi.showBackgroundImageDialog(function(image, failed) - { - if (!failed) - { - newBackgroundImage = image; - updateBackgroundImage(); - } - }, newBackgroundImage); - - mxEvent.consume(evt); - }); - - updateBackgroundImage(); - - td.appendChild(changeImageLink); - - row.appendChild(td); - tbody.appendChild(row); - - row = document.createElement('tr'); - td = document.createElement('td'); - td.colSpan = 2; - td.style.paddingTop = '16px'; - td.setAttribute('align', 'right'); - - var cancelBtn = mxUtils.button(mxResources.get('cancel'), function() - { - editorUi.hideDialog(); - }); - cancelBtn.className = 'geBtn'; - - if (editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - } - - var applyBtn = mxUtils.button(mxResources.get('apply'), function() - { - editorUi.hideDialog(); - var gridSize = parseInt(gridSizeInput.value); - - if (!isNaN(gridSize) && graph.gridSize !== gridSize) - { - graph.setGridSize(gridSize); - } - - var change = new ChangePageSetup(editorUi, newBackgroundColor, - newBackgroundImage, accessor.get()); - change.ignoreColor = graph.background == newBackgroundColor; - - var oldSrc = (graph.backgroundImage != null) ? graph.backgroundImage.src : null; - var newSrc = (newBackgroundImage != null) ? newBackgroundImage.src : null; - - change.ignoreImage = oldSrc === newSrc; - - if (graph.pageFormat.width != change.previousFormat.width || - graph.pageFormat.height != change.previousFormat.height || - !change.ignoreColor || !change.ignoreImage) - { - graph.model.execute(change); - } - }); - applyBtn.className = 'geBtn gePrimaryBtn'; - td.appendChild(applyBtn); - - if (!editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - } - - row.appendChild(td); - tbody.appendChild(row); - - table.appendChild(tbody); - this.container = table; -}; - -/** - * - */ -PageSetupDialog.addPageFormatPanel = function(div, namePostfix, pageFormat, pageFormatListener) -{ - var formatName = 'format-' + namePostfix; - - var portraitCheckBox = document.createElement('input'); - portraitCheckBox.setAttribute('name', formatName); - portraitCheckBox.setAttribute('type', 'radio'); - portraitCheckBox.setAttribute('value', 'portrait'); - - var landscapeCheckBox = document.createElement('input'); - landscapeCheckBox.setAttribute('name', formatName); - landscapeCheckBox.setAttribute('type', 'radio'); - landscapeCheckBox.setAttribute('value', 'landscape'); - - var paperSizeSelect = document.createElement('select'); - paperSizeSelect.style.marginBottom = '8px'; - paperSizeSelect.style.width = '202px'; - - var formatDiv = document.createElement('div'); - formatDiv.style.marginLeft = '4px'; - formatDiv.style.width = '210px'; - formatDiv.style.height = '24px'; - - portraitCheckBox.style.marginRight = '6px'; - formatDiv.appendChild(portraitCheckBox); - - var portraitSpan = document.createElement('span'); - portraitSpan.style.maxWidth = '100px'; - mxUtils.write(portraitSpan, mxResources.get('portrait')); - formatDiv.appendChild(portraitSpan); - - landscapeCheckBox.style.marginLeft = '10px'; - landscapeCheckBox.style.marginRight = '6px'; - formatDiv.appendChild(landscapeCheckBox); - - var landscapeSpan = document.createElement('span'); - landscapeSpan.style.width = '100px'; - mxUtils.write(landscapeSpan, mxResources.get('landscape')); - formatDiv.appendChild(landscapeSpan) - - var customDiv = document.createElement('div'); - customDiv.style.marginLeft = '4px'; - customDiv.style.width = '210px'; - customDiv.style.height = '24px'; - - var widthInput = document.createElement('input'); - widthInput.setAttribute('size', '7'); - widthInput.style.textAlign = 'right'; - customDiv.appendChild(widthInput); - mxUtils.write(customDiv, ' in x '); - - var heightInput = document.createElement('input'); - heightInput.setAttribute('size', '7'); - heightInput.style.textAlign = 'right'; - customDiv.appendChild(heightInput); - mxUtils.write(customDiv, ' in'); - - formatDiv.style.display = 'none'; - customDiv.style.display = 'none'; - - var pf = new Object(); - var formats = PageSetupDialog.getFormats(); - - for (var i = 0; i < formats.length; i++) - { - var f = formats[i]; - pf[f.key] = f; - - var paperSizeOption = document.createElement('option'); - paperSizeOption.setAttribute('value', f.key); - mxUtils.write(paperSizeOption, f.title); - paperSizeSelect.appendChild(paperSizeOption); - } - - var customSize = false; - - function listener(sender, evt, force) - { - if (force || (widthInput != document.activeElement && heightInput != document.activeElement)) - { - var detected = false; - - for (var i = 0; i < formats.length; i++) - { - var f = formats[i]; - - // Special case where custom was chosen - if (customSize) - { - if (f.key == 'custom') - { - paperSizeSelect.value = f.key; - customSize = false; - } - } - else if (f.format != null) - { - // Fixes wrong values for previous A4 and A5 page sizes - if (f.key == 'a4') - { - if (pageFormat.width == 826) - { - pageFormat = mxRectangle.fromRectangle(pageFormat); - pageFormat.width = 827; - } - else if (pageFormat.height == 826) - { - pageFormat = mxRectangle.fromRectangle(pageFormat); - pageFormat.height = 827; - } - } - else if (f.key == 'a5') - { - if (pageFormat.width == 584) - { - pageFormat = mxRectangle.fromRectangle(pageFormat); - pageFormat.width = 583; - } - else if (pageFormat.height == 584) - { - pageFormat = mxRectangle.fromRectangle(pageFormat); - pageFormat.height = 583; - } - } - - if (pageFormat.width == f.format.width && pageFormat.height == f.format.height) - { - paperSizeSelect.value = f.key; - portraitCheckBox.setAttribute('checked', 'checked'); - portraitCheckBox.defaultChecked = true; - portraitCheckBox.checked = true; - landscapeCheckBox.removeAttribute('checked'); - landscapeCheckBox.defaultChecked = false; - landscapeCheckBox.checked = false; - detected = true; - } - else if (pageFormat.width == f.format.height && pageFormat.height == f.format.width) - { - paperSizeSelect.value = f.key; - portraitCheckBox.removeAttribute('checked'); - portraitCheckBox.defaultChecked = false; - portraitCheckBox.checked = false; - landscapeCheckBox.setAttribute('checked', 'checked'); - landscapeCheckBox.defaultChecked = true; - landscapeCheckBox.checked = true; - detected = true; - } - } - } - - // Selects custom format which is last in list - if (!detected) - { - widthInput.value = pageFormat.width / 100; - heightInput.value = pageFormat.height / 100; - portraitCheckBox.setAttribute('checked', 'checked'); - paperSizeSelect.value = 'custom'; - formatDiv.style.display = 'none'; - customDiv.style.display = ''; - } - else - { - formatDiv.style.display = ''; - customDiv.style.display = 'none'; - } - } - }; - - listener(); - - div.appendChild(paperSizeSelect); - mxUtils.br(div); - - div.appendChild(formatDiv); - div.appendChild(customDiv); - - var currentPageFormat = pageFormat; - - var update = function(evt, selectChanged) - { - var f = pf[paperSizeSelect.value]; - - if (f.format != null) - { - widthInput.value = f.format.width / 100; - heightInput.value = f.format.height / 100; - customDiv.style.display = 'none'; - formatDiv.style.display = ''; - } - else - { - formatDiv.style.display = 'none'; - customDiv.style.display = ''; - } - - var wi = parseFloat(widthInput.value); - - if (isNaN(wi) || wi <= 0) - { - widthInput.value = pageFormat.width / 100; - } - - var hi = parseFloat(heightInput.value); - - if (isNaN(hi) || hi <= 0) - { - heightInput.value = pageFormat.height / 100; - } - - var newPageFormat = new mxRectangle(0, 0, - Math.floor(parseFloat(widthInput.value) * 100), - Math.floor(parseFloat(heightInput.value) * 100)); - - if (paperSizeSelect.value != 'custom' && landscapeCheckBox.checked) - { - newPageFormat = new mxRectangle(0, 0, newPageFormat.height, newPageFormat.width); - } - - // Initial select of custom should not update page format to avoid update of combo - if ((!selectChanged || !customSize) && (newPageFormat.width != currentPageFormat.width || - newPageFormat.height != currentPageFormat.height)) - { - currentPageFormat = newPageFormat; - - // Updates page format and reloads format panel - if (pageFormatListener != null) - { - pageFormatListener(currentPageFormat); - } - } - }; - - mxEvent.addListener(portraitSpan, 'click', function(evt) - { - portraitCheckBox.checked = true; - update(evt); - mxEvent.consume(evt); - }); - - mxEvent.addListener(landscapeSpan, 'click', function(evt) - { - landscapeCheckBox.checked = true; - update(evt); - mxEvent.consume(evt); - }); - - mxEvent.addListener(widthInput, 'blur', update); - mxEvent.addListener(widthInput, 'click', update); - mxEvent.addListener(heightInput, 'blur', update); - mxEvent.addListener(heightInput, 'click', update); - mxEvent.addListener(landscapeCheckBox, 'change', update); - mxEvent.addListener(portraitCheckBox, 'change', update); - mxEvent.addListener(paperSizeSelect, 'change', function(evt) - { - // Handles special case where custom was chosen - customSize = paperSizeSelect.value == 'custom'; - update(evt, true); - }); - - update(); - - return {set: function(value) - { - pageFormat = value; - listener(null, null, true); - },get: function() - { - return currentPageFormat; - }, widthInput: widthInput, - heightInput: heightInput}; -}; - -/** - * - */ -PageSetupDialog.getFormats = function() -{ - return [{key: 'letter', title: 'US-Letter (8,5" x 11")', format: mxConstants.PAGE_FORMAT_LETTER_PORTRAIT}, - {key: 'legal', title: 'US-Legal (8,5" x 14")', format: new mxRectangle(0, 0, 850, 1400)}, - {key: 'tabloid', title: 'US-Tabloid (11" x 17")', format: new mxRectangle(0, 0, 1100, 1700)}, - {key: 'executive', title: 'US-Executive (7" x 10")', format: new mxRectangle(0, 0, 700, 1000)}, - {key: 'a0', title: 'A0 (841 mm x 1189 mm)', format: new mxRectangle(0, 0, 3300, 4681)}, - {key: 'a1', title: 'A1 (594 mm x 841 mm)', format: new mxRectangle(0, 0, 2339, 3300)}, - {key: 'a2', title: 'A2 (420 mm x 594 mm)', format: new mxRectangle(0, 0, 1654, 2336)}, - {key: 'a3', title: 'A3 (297 mm x 420 mm)', format: new mxRectangle(0, 0, 1169, 1654)}, - {key: 'a4', title: 'A4 (210 mm x 297 mm)', format: mxConstants.PAGE_FORMAT_A4_PORTRAIT}, - {key: 'a5', title: 'A5 (148 mm x 210 mm)', format: new mxRectangle(0, 0, 583, 827)}, - {key: 'a6', title: 'A6 (105 mm x 148 mm)', format: new mxRectangle(0, 0, 413, 583)}, - {key: 'a7', title: 'A7 (74 mm x 105 mm)', format: new mxRectangle(0, 0, 291, 413)}, - {key: 'b4', title: 'B4 (250 mm x 353 mm)', format: new mxRectangle(0, 0, 980, 1390)}, - {key: 'b5', title: 'B5 (176 mm x 250 mm)', format: new mxRectangle(0, 0, 690, 980)}, - {key: '16-9', title: '16:9 (1600 x 900)', format: new mxRectangle(0, 0, 900, 1600)}, - {key: '16-10', title: '16:10 (1920 x 1200)', format: new mxRectangle(0, 0, 1200, 1920)}, - {key: '4-3', title: '4:3 (1600 x 1200)', format: new mxRectangle(0, 0, 1200, 1600)}, - {key: 'custom', title: mxResources.get('custom'), format: null}]; -}; - -/** - * Constructs a new filename dialog. - */ -var FilenameDialog = function(editorUi, filename, buttonText, fn, label, validateFn, content, helpLink, closeOnBtn, cancelFn, hints, w) -{ - closeOnBtn = (closeOnBtn != null) ? closeOnBtn : true; - var row, td; - - var table = document.createElement('table'); - var tbody = document.createElement('tbody'); - table.style.marginTop = '8px'; - - row = document.createElement('tr'); - - td = document.createElement('td'); - td.style.whiteSpace = 'nowrap'; - td.style.fontSize = '10pt'; - td.style.width = (hints) ? '80px' : '120px'; - mxUtils.write(td, (label || mxResources.get('filename')) + ':'); - - row.appendChild(td); - - var nameInput = document.createElement('input'); - nameInput.setAttribute('value', filename || ''); - nameInput.style.marginLeft = '4px'; - nameInput.style.width = (w != null) ? w + 'px' : '180px'; - - var genericBtn = mxUtils.button(buttonText, function() - { - if (validateFn == null || validateFn(nameInput.value)) - { - if (closeOnBtn) - { - editorUi.hideDialog(); - } - - fn(nameInput.value); - } - }); - genericBtn.className = 'geBtn gePrimaryBtn'; - - this.init = function() - { - if (label == null && content != null) - { - return; - } - - nameInput.focus(); - - if (mxClient.IS_GC || mxClient.IS_FF || document.documentMode >= 5 || mxClient.IS_QUIRKS) - { - nameInput.select(); - } - else - { - document.execCommand('selectAll', false, null); - } - - // Installs drag and drop handler for links - if (Graph.fileSupport) - { - // Setup the dnd listeners - var dlg = table.parentNode; - - if (dlg != null) - { - var graph = editorUi.editor.graph; - var dropElt = null; - - mxEvent.addListener(dlg, 'dragleave', function(evt) - { - if (dropElt != null) - { - dropElt.style.backgroundColor = ''; - dropElt = null; - } - - evt.stopPropagation(); - evt.preventDefault(); - }); - - mxEvent.addListener(dlg, 'dragover', mxUtils.bind(this, function(evt) - { - // IE 10 does not implement pointer-events so it can't have a drop highlight - if (dropElt == null && (!mxClient.IS_IE || document.documentMode > 10)) - { - dropElt = nameInput; - dropElt.style.backgroundColor = '#ebf2f9'; - } - - evt.stopPropagation(); - evt.preventDefault(); - })); - - mxEvent.addListener(dlg, 'drop', mxUtils.bind(this, function(evt) - { - if (dropElt != null) - { - dropElt.style.backgroundColor = ''; - dropElt = null; - } - - if (mxUtils.indexOf(evt.dataTransfer.types, 'text/uri-list') >= 0) - { - nameInput.value = decodeURIComponent(evt.dataTransfer.getData('text/uri-list')); - genericBtn.click(); - } - - evt.stopPropagation(); - evt.preventDefault(); - })); - } - } - }; - - td = document.createElement('td'); - td.style.whiteSpace = 'nowrap'; - td.appendChild(nameInput); - row.appendChild(td); - - if (label != null || content == null) - { - tbody.appendChild(row); - - if (hints != null) - { - if (editorUi.editor.diagramFileTypes != null) - { - var typeSelect = FilenameDialog.createFileTypes(editorUi, nameInput, editorUi.editor.diagramFileTypes); - typeSelect.style.marginLeft = '6px'; - typeSelect.style.width = '74px'; - - td.appendChild(typeSelect); - nameInput.style.width = (w != null) ? (w - 40) + 'px' : '140px'; - } - - td.appendChild(FilenameDialog.createTypeHint(editorUi, nameInput, hints)); - } - } - - if (content != null) - { - row = document.createElement('tr'); - td = document.createElement('td'); - td.colSpan = 2; - td.appendChild(content); - row.appendChild(td); - tbody.appendChild(row); - } - - row = document.createElement('tr'); - td = document.createElement('td'); - td.colSpan = 2; - td.style.paddingTop = '20px'; - td.style.whiteSpace = 'nowrap'; - td.setAttribute('align', 'right'); - - var cancelBtn = mxUtils.button(mxResources.get('cancel'), function() - { - editorUi.hideDialog(); - - if (cancelFn != null) - { - cancelFn(); - } - }); - cancelBtn.className = 'geBtn'; - - if (editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - } - - if (helpLink != null) - { - var helpBtn = mxUtils.button(mxResources.get('help'), function() - { - editorUi.editor.graph.openLink(helpLink); - }); - - helpBtn.className = 'geBtn'; - td.appendChild(helpBtn); - } - - mxEvent.addListener(nameInput, 'keypress', function(e) - { - if (e.keyCode == 13) - { - genericBtn.click(); - } - }); - - td.appendChild(genericBtn); - - if (!editorUi.editor.cancelFirst) - { - td.appendChild(cancelBtn); - } - - row.appendChild(td); - tbody.appendChild(row); - table.appendChild(tbody); - - this.container = table; -}; - -/** - * - */ -FilenameDialog.filenameHelpLink = null; - -/** - * - */ -FilenameDialog.createTypeHint = function(ui, nameInput, hints) -{ - var hint = document.createElement('img'); - hint.style.cssText = 'vertical-align:top;height:16px;width:16px;margin-left:4px;background-repeat:no-repeat;background-position:center bottom;cursor:pointer;'; - mxUtils.setOpacity(hint, 70); - - var nameChanged = function() - { - hint.setAttribute('src', Editor.helpImage); - hint.setAttribute('title', mxResources.get('help')); - - for (var i = 0; i < hints.length; i++) - { - if (hints[i].ext.length > 0 && nameInput.value.toLowerCase().substring( - nameInput.value.length - hints[i].ext.length - 1) == '.' + hints[i].ext) - { - hint.setAttribute('src', mxClient.imageBasePath + '/warning.png'); - hint.setAttribute('title', mxResources.get(hints[i].title)); - break; - } - } - }; - - mxEvent.addListener(nameInput, 'keyup', nameChanged); - mxEvent.addListener(nameInput, 'change', nameChanged); - mxEvent.addListener(hint, 'click', function(evt) - { - var title = hint.getAttribute('title'); - - if (hint.getAttribute('src') == Editor.helpImage) - { - ui.editor.graph.openLink(FilenameDialog.filenameHelpLink); - } - else if (title != '') - { - ui.showError(null, title, mxResources.get('help'), function() - { - ui.editor.graph.openLink(FilenameDialog.filenameHelpLink); - }, null, mxResources.get('ok'), null, null, null, 340, 90); - } - - mxEvent.consume(evt); - }); - - nameChanged(); - - return hint; -}; - -/** - * - */ -FilenameDialog.createFileTypes = function(editorUi, nameInput, types) -{ - var typeSelect = document.createElement('select'); - - for (var i = 0; i < types.length; i++) - { - var typeOption = document.createElement('option'); - typeOption.setAttribute('value', i); - mxUtils.write(typeOption, mxResources.get(types[i].description) + - ' (.' + types[i].extension + ')'); - typeSelect.appendChild(typeOption); - } - - mxEvent.addListener(typeSelect, 'change', function(evt) - { - var ext = types[typeSelect.value].extension; - var idx = nameInput.value.lastIndexOf('.'); - - if (idx > 0) - { - var ext = types[typeSelect.value].extension; - nameInput.value = nameInput.value.substring(0, idx + 1) + ext; - } - else - { - nameInput.value = nameInput.value + '.' + ext; - } - - if ('createEvent' in document) - { - var changeEvent = document.createEvent('HTMLEvents'); - changeEvent.initEvent('change', false, true); - nameInput.dispatchEvent(changeEvent); - } - else - { - nameInput.fireEvent('onchange'); - } - }); - - var nameInputChanged = function(evt) - { - var idx = nameInput.value.lastIndexOf('.'); - var active = 0; - - // Finds current extension - if (idx > 0) - { - var ext = nameInput.value.toLowerCase().substring(idx + 1); - - for (var i = 0; i < types.length; i++) - { - if (ext == types[i].extension) - { - active = i; - break; - } - } - } - - typeSelect.value = active; - }; - - mxEvent.addListener(nameInput, 'change', nameInputChanged); - mxEvent.addListener(nameInput, 'keyup', nameInputChanged); - nameInputChanged(); - - return typeSelect; -}; - -/** - * Static overrides - */ -(function() -{ - // Uses HTML for background pages (to support grid background image) - mxGraphView.prototype.validateBackgroundPage = function() - { - var graph = this.graph; - - if (graph.container != null && !graph.transparentBackground) - { - if (graph.pageVisible) - { - var bounds = this.getBackgroundPageBounds(); - - if (this.backgroundPageShape == null) - { - // Finds first element in graph container - var firstChild = graph.container.firstChild; - - while (firstChild != null && firstChild.nodeType != mxConstants.NODETYPE_ELEMENT) - { - firstChild = firstChild.nextSibling; - } - - if (firstChild != null) - { - this.backgroundPageShape = this.createBackgroundPageShape(bounds); - this.backgroundPageShape.scale = 1; - - // Shadow filter causes problems in outline window in quirks mode. IE8 standards - // also has known rendering issues inside mxWindow but not using shadow is worse. - this.backgroundPageShape.isShadow = !mxClient.IS_QUIRKS; - this.backgroundPageShape.dialect = mxConstants.DIALECT_STRICTHTML; - this.backgroundPageShape.init(graph.container); - - // Required for the browser to render the background page in correct order - firstChild.style.position = 'absolute'; - graph.container.insertBefore(this.backgroundPageShape.node, firstChild); - this.backgroundPageShape.redraw(); - - this.backgroundPageShape.node.className = 'geBackgroundPage'; - - // Adds listener for double click handling on background - mxEvent.addListener(this.backgroundPageShape.node, 'dblclick', - mxUtils.bind(this, function(evt) - { - graph.dblClick(evt); - }) - ); - - // Adds basic listeners for graph event dispatching outside of the - // container and finishing the handling of a single gesture - mxEvent.addGestureListeners(this.backgroundPageShape.node, - mxUtils.bind(this, function(evt) - { - graph.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt)); - }), - mxUtils.bind(this, function(evt) - { - // Hides the tooltip if mouse is outside container - if (graph.tooltipHandler != null && graph.tooltipHandler.isHideOnHover()) - { - graph.tooltipHandler.hide(); - } - - if (graph.isMouseDown && !mxEvent.isConsumed(evt)) - { - graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt)); - } - }), - mxUtils.bind(this, function(evt) - { - graph.fireMouseEvent(mxEvent.MOUSE_UP, new mxMouseEvent(evt)); - }) - ); - } - } - else - { - this.backgroundPageShape.scale = 1; - this.backgroundPageShape.bounds = bounds; - this.backgroundPageShape.redraw(); - } - } - else if (this.backgroundPageShape != null) - { - this.backgroundPageShape.destroy(); - this.backgroundPageShape = null; - } - - this.validateBackgroundStyles(); - } - }; - - // Updates the CSS of the background to draw the grid - mxGraphView.prototype.validateBackgroundStyles = function() - { - var graph = this.graph; - var color = (graph.background == null || graph.background == mxConstants.NONE) ? graph.defaultPageBackgroundColor : graph.background; - var gridColor = (color != null && this.gridColor != color.toLowerCase()) ? this.gridColor : '#ffffff'; - var image = 'none'; - var position = ''; - - if (graph.isGridEnabled()) - { - var phase = 10; - - if (mxClient.IS_SVG) - { - // Generates the SVG required for drawing the dynamic grid - image = unescape(encodeURIComponent(this.createSvgGrid(gridColor))); - image = (window.btoa) ? btoa(image) : Base64.encode(image, true); - image = 'url(' + 'data:image/svg+xml;base64,' + image + ')' - phase = graph.gridSize * this.scale * this.gridSteps; - } - else - { - // Fallback to grid wallpaper with fixed size - image = 'url(' + this.gridImage + ')'; - } - - var x0 = 0; - var y0 = 0; - - if (graph.view.backgroundPageShape != null) - { - var bds = this.getBackgroundPageBounds(); - - x0 = 1 + bds.x; - y0 = 1 + bds.y; - } - - // Computes the offset to maintain origin for grid - position = -Math.round(phase - mxUtils.mod(this.translate.x * this.scale - x0, phase)) + 'px ' + - -Math.round(phase - mxUtils.mod(this.translate.y * this.scale - y0, phase)) + 'px'; - } - - var canvas = graph.view.canvas; - - if (canvas.ownerSVGElement != null) - { - canvas = canvas.ownerSVGElement; - } - - if (graph.view.backgroundPageShape != null) - { - graph.view.backgroundPageShape.node.style.backgroundPosition = position; - graph.view.backgroundPageShape.node.style.backgroundImage = image; - graph.view.backgroundPageShape.node.style.backgroundColor = color; - graph.container.className = 'geDiagramContainer geDiagramBackdrop'; - canvas.style.backgroundImage = 'none'; - canvas.style.backgroundColor = ''; - } - else - { - graph.container.className = 'geDiagramContainer'; - canvas.style.backgroundPosition = position; - canvas.style.backgroundColor = color; - canvas.style.backgroundImage = image; - } - }; - - // Returns the SVG required for painting the background grid. - mxGraphView.prototype.createSvgGrid = function(color) - { - var tmp = this.graph.gridSize * this.scale; - - while (tmp < this.minGridSize) - { - tmp *= 2; - } - - var tmp2 = this.gridSteps * tmp; - - // Small grid lines - var d = []; - - for (var i = 1; i < this.gridSteps; i++) - { - var tmp3 = i * tmp; - d.push('M 0 ' + tmp3 + ' L ' + tmp2 + ' ' + tmp3 + ' M ' + tmp3 + ' 0 L ' + tmp3 + ' ' + tmp2); - } - - // KNOWN: Rounding errors for certain scales (eg. 144%, 121% in Chrome, FF and Safari). Workaround - // in Chrome is to use 100% for the svg size, but this results in blurred grid for large diagrams. - var size = tmp2; - var svg = '' + - '' + - '' + - '' + - ''; - - return svg; - }; - - // Adds panning for the grid with no page view and disabled scrollbars - var mxGraphPanGraph = mxGraph.prototype.panGraph; - mxGraph.prototype.panGraph = function(dx, dy) - { - mxGraphPanGraph.apply(this, arguments); - - if (this.shiftPreview1 != null) - { - var canvas = this.view.canvas; - - if (canvas.ownerSVGElement != null) - { - canvas = canvas.ownerSVGElement; - } - - var phase = this.gridSize * this.view.scale * this.view.gridSteps; - var position = -Math.round(phase - mxUtils.mod(this.view.translate.x * this.view.scale + dx, phase)) + 'px ' + - -Math.round(phase - mxUtils.mod(this.view.translate.y * this.view.scale + dy, phase)) + 'px'; - canvas.style.backgroundPosition = position; - } - }; - - // Draws page breaks only within the page - mxGraph.prototype.updatePageBreaks = function(visible, width, height) - { - var scale = this.view.scale; - var tr = this.view.translate; - var fmt = this.pageFormat; - var ps = scale * this.pageScale; - - var bounds2 = this.view.getBackgroundPageBounds(); - - width = bounds2.width; - height = bounds2.height; - var bounds = new mxRectangle(scale * tr.x, scale * tr.y, fmt.width * ps, fmt.height * ps); - - // Does not show page breaks if the scale is too small - visible = visible && Math.min(bounds.width, bounds.height) > this.minPageBreakDist; - - var horizontalCount = (visible) ? Math.ceil(height / bounds.height) - 1 : 0; - var verticalCount = (visible) ? Math.ceil(width / bounds.width) - 1 : 0; - var right = bounds2.x + width; - var bottom = bounds2.y + height; - - if (this.horizontalPageBreaks == null && horizontalCount > 0) - { - this.horizontalPageBreaks = []; - } - - if (this.verticalPageBreaks == null && verticalCount > 0) - { - this.verticalPageBreaks = []; - } - - var drawPageBreaks = mxUtils.bind(this, function(breaks) - { - if (breaks != null) - { - var count = (breaks == this.horizontalPageBreaks) ? horizontalCount : verticalCount; - - for (var i = 0; i <= count; i++) - { - var pts = (breaks == this.horizontalPageBreaks) ? - [new mxPoint(Math.round(bounds2.x), Math.round(bounds2.y + (i + 1) * bounds.height)), - new mxPoint(Math.round(right), Math.round(bounds2.y + (i + 1) * bounds.height))] : - [new mxPoint(Math.round(bounds2.x + (i + 1) * bounds.width), Math.round(bounds2.y)), - new mxPoint(Math.round(bounds2.x + (i + 1) * bounds.width), Math.round(bottom))]; - - if (breaks[i] != null) - { - breaks[i].points = pts; - breaks[i].redraw(); - } - else - { - var pageBreak = new mxPolyline(pts, this.pageBreakColor); - pageBreak.dialect = this.dialect; - pageBreak.isDashed = this.pageBreakDashed; - pageBreak.pointerEvents = false; - pageBreak.init(this.view.backgroundPane); - pageBreak.redraw(); - - breaks[i] = pageBreak; - } - } - - for (var i = count; i < breaks.length; i++) - { - breaks[i].destroy(); - } - - breaks.splice(count, breaks.length - count); - } - }); - - drawPageBreaks(this.horizontalPageBreaks); - drawPageBreaks(this.verticalPageBreaks); - }; - - // Disables removing relative children and table rows and cells from parents - var mxGraphHandlerShouldRemoveCellsFromParent = mxGraphHandler.prototype.shouldRemoveCellsFromParent; - mxGraphHandler.prototype.shouldRemoveCellsFromParent = function(parent, cells, evt) - { - for (var i = 0; i < cells.length; i++) - { - if (this.graph.isTableCell(cells[i]) || this.graph.isTableRow(cells[i])) - { - return false; - } - else if (this.graph.getModel().isVertex(cells[i])) - { - var geo = this.graph.getCellGeometry(cells[i]); - - if (geo != null && geo.relative) - { - return false; - } - } - } - - return mxGraphHandlerShouldRemoveCellsFromParent.apply(this, arguments); - }; - - // Overrides to ignore hotspot only for target terminal - var mxConnectionHandlerCreateMarker = mxConnectionHandler.prototype.createMarker; - mxConnectionHandler.prototype.createMarker = function() - { - var marker = mxConnectionHandlerCreateMarker.apply(this, arguments); - - marker.intersects = mxUtils.bind(this, function(state, evt) - { - if (this.isConnecting()) - { - return true; - } - - return mxCellMarker.prototype.intersects.apply(marker, arguments); - }); - - return marker; - }; - - // Creates background page shape - mxGraphView.prototype.createBackgroundPageShape = function(bounds) - { - return new mxRectangleShape(bounds, '#ffffff', this.graph.defaultPageBorderColor); - }; - - // Fits the number of background pages to the graph - mxGraphView.prototype.getBackgroundPageBounds = function() - { - var gb = this.getGraphBounds(); - - // Computes unscaled, untranslated graph bounds - var x = (gb.width > 0) ? gb.x / this.scale - this.translate.x : 0; - var y = (gb.height > 0) ? gb.y / this.scale - this.translate.y : 0; - var w = gb.width / this.scale; - var h = gb.height / this.scale; - - var fmt = this.graph.pageFormat; - var ps = this.graph.pageScale; - - var pw = fmt.width * ps; - var ph = fmt.height * ps; - - var x0 = Math.floor(Math.min(0, x) / pw); - var y0 = Math.floor(Math.min(0, y) / ph); - var xe = Math.ceil(Math.max(1, x + w) / pw); - var ye = Math.ceil(Math.max(1, y + h) / ph); - - var rows = xe - x0; - var cols = ye - y0; - - var bounds = new mxRectangle(this.scale * (this.translate.x + x0 * pw), this.scale * - (this.translate.y + y0 * ph), this.scale * rows * pw, this.scale * cols * ph); - - return bounds; - }; - - // Add panning for background page in VML - var graphPanGraph = mxGraph.prototype.panGraph; - mxGraph.prototype.panGraph = function(dx, dy) - { - graphPanGraph.apply(this, arguments); - - if ((this.dialect != mxConstants.DIALECT_SVG && this.view.backgroundPageShape != null) && - (!this.useScrollbarsForPanning || !mxUtils.hasScrollbars(this.container))) - { - this.view.backgroundPageShape.node.style.marginLeft = dx + 'px'; - this.view.backgroundPageShape.node.style.marginTop = dy + 'px'; - } - }; - - /** - * Consumes click events for disabled menu items. - */ - var mxPopupMenuAddItem = mxPopupMenu.prototype.addItem; - mxPopupMenu.prototype.addItem = function(title, image, funct, parent, iconCls, enabled) - { - var result = mxPopupMenuAddItem.apply(this, arguments); - - if (enabled != null && !enabled) - { - mxEvent.addListener(result, 'mousedown', function(evt) - { - mxEvent.consume(evt); - }); - } - - return result; - }; - - /** - * Selects tables before cells and rows. - */ - var mxGraphHandlerIsPropagateSelectionCell = mxGraphHandler.prototype.isPropagateSelectionCell; - mxGraphHandler.prototype.isPropagateSelectionCell = function(cell, immediate, me) - { - var result = false; - var parent = this.graph.model.getParent(cell) - - if (immediate) - { - var geo = (this.graph.model.isEdge(cell)) ? null : - this.graph.getCellGeometry(cell); - - result = !this.graph.model.isEdge(parent) && - !this.graph.isSiblingSelected(cell) && - ((geo != null && geo.relative) || - !this.graph.isContainer(parent) || - this.graph.isPart(cell)); - } - else - { - result = mxGraphHandlerIsPropagateSelectionCell.apply(this, arguments); - - if (this.graph.isTableCell(cell) || this.graph.isTableRow(cell)) - { - var table = parent; - - if (!this.graph.isTable(table)) - { - table = this.graph.model.getParent(table); - } - - result = !this.graph.selectionCellsHandler.isHandled(table) || - (this.graph.isCellSelected(table) && this.graph.isToggleEvent(me.getEvent())) || - (this.graph.isCellSelected(cell) && !this.graph.isToggleEvent(me.getEvent())) || - (this.graph.isTableCell(cell) && this.graph.isCellSelected(parent)); - } - } - - return result; - }; - - /** - * Returns last selected ancestor - */ - mxPopupMenuHandler.prototype.getCellForPopupEvent = function(me) - { - var cell = me.getCell(); - var model = this.graph.getModel(); - var parent = model.getParent(cell); - var state = this.graph.view.getState(parent); - var selected = this.graph.isCellSelected(cell); - - while (state != null && (model.isVertex(parent) || model.isEdge(parent))) - { - var temp = this.graph.isCellSelected(parent); - selected = selected || temp; - - if (temp || (!selected && (this.graph.isTableCell(cell) || - this.graph.isTableRow(cell)))) - { - cell = parent; - } - - parent = model.getParent(parent); - } - - return cell; - }; - -})(); diff --git a/src/main/webapp/js/mxgraph/EditorUi.js b/src/main/webapp/js/mxgraph/EditorUi.js deleted file mode 100644 index 0135ec55..00000000 --- a/src/main/webapp/js/mxgraph/EditorUi.js +++ /dev/null @@ -1,5090 +0,0 @@ -/** - * Copyright (c) 2006-2012, JGraph Ltd - */ -/** - * Constructs a new graph editor - */ -EditorUi = function(editor, container, lightbox) -{ - mxEventSource.call(this); - - this.destroyFunctions = []; - this.editor = editor || new Editor(); - this.container = container || document.body; - - var graph = this.editor.graph; - graph.lightbox = lightbox; - this.initialDefaultVertexStyle = mxUtils.clone(graph.defaultVertexStyle); - this.initialDefaultEdgeStyle = mxUtils.clone(graph.defaultEdgeStyle); - - // Faster scrollwheel zoom is possible with CSS transforms - if (graph.useCssTransforms) - { - this.lazyZoomDelay = 0; - } - - // Pre-fetches submenu image or replaces with embedded image if supported - if (mxClient.IS_SVG) - { - mxPopupMenu.prototype.submenuImage = 'data:image/gif;base64,R0lGODlhCQAJAIAAAP///zMzMyH5BAEAAAAALAAAAAAJAAkAAAIPhI8WebHsHopSOVgb26AAADs='; - } - else - { - new Image().src = mxPopupMenu.prototype.submenuImage; - } - - // Pre-fetches connect image - if (!mxClient.IS_SVG && mxConnectionHandler.prototype.connectImage != null) - { - new Image().src = mxConnectionHandler.prototype.connectImage.src; - } - - // Disables graph and forced panning in chromeless mode - if (this.editor.chromeless && !this.editor.editable) - { - this.footerHeight = 0; - graph.isEnabled = function() { return false; }; - graph.panningHandler.isForcePanningEvent = function(me) - { - return !mxEvent.isPopupTrigger(me.getEvent()); - }; - } - - // Creates the user interface - this.actions = new Actions(this); - this.menus = this.createMenus(); - - if (!graph.standalone) - { - this.createDivs(); - this.createUi(); - this.refresh(); - - // Disables HTML and text selection - var textEditing = mxUtils.bind(this, function(evt) - { - if (evt == null) - { - evt = window.event; - } - - return graph.isEditing() || (evt != null && this.isSelectionAllowed(evt)); - }); - - // Disables text selection while not editing and no dialog visible - if (this.container == document.body) - { - this.menubarContainer.onselectstart = textEditing; - this.menubarContainer.onmousedown = textEditing; - this.toolbarContainer.onselectstart = textEditing; - this.toolbarContainer.onmousedown = textEditing; - this.diagramContainer.onselectstart = textEditing; - this.diagramContainer.onmousedown = textEditing; - this.sidebarContainer.onselectstart = textEditing; - this.sidebarContainer.onmousedown = textEditing; - this.formatContainer.onselectstart = textEditing; - this.formatContainer.onmousedown = textEditing; - this.footerContainer.onselectstart = textEditing; - this.footerContainer.onmousedown = textEditing; - - if (this.tabContainer != null) - { - // Mouse down is needed for drag and drop - this.tabContainer.onselectstart = textEditing; - } - } - - // And uses built-in context menu while editing - if (!this.editor.chromeless || this.editor.editable) - { - // Allows context menu for links in hints - var linkHandler = function(evt) - { - if (evt != null) - { - var source = mxEvent.getSource(evt); - - if (source.nodeName == 'A') - { - while (source != null) - { - if (source.className == 'geHint') - { - return true; - } - - source = source.parentNode; - } - } - } - - return textEditing(evt); - }; - - if (mxClient.IS_IE && (typeof(document.documentMode) === 'undefined' || document.documentMode < 9)) - { - mxEvent.addListener(this.diagramContainer, 'contextmenu', linkHandler); - } - else - { - // Allows browser context menu outside of diagram and sidebar - this.diagramContainer.oncontextmenu = linkHandler; - } - } - else - { - graph.panningHandler.usePopupTrigger = false; - } - - // Contains the main graph instance inside the given panel - graph.init(this.diagramContainer); - - // Improves line wrapping for in-place editor - if (mxClient.IS_SVG && graph.view.getDrawPane() != null) - { - var root = graph.view.getDrawPane().ownerSVGElement; - - if (root != null) - { - root.style.position = 'absolute'; - } - } - - // Creates hover icons - this.hoverIcons = this.createHoverIcons(); - - // Hides hover icons when cells are moved - if (graph.graphHandler != null) - { - var graphHandlerStart = graph.graphHandler.start; - - graph.graphHandler.start = function() - { - if (ui.hoverIcons != null) - { - ui.hoverIcons.reset(); - } - - graphHandlerStart.apply(this, arguments); - }; - } - - // Adds tooltip when mouse is over scrollbars to show space-drag panning option - mxEvent.addListener(this.diagramContainer, 'mousemove', mxUtils.bind(this, function(evt) - { - var off = mxUtils.getOffset(this.diagramContainer); - - if (mxEvent.getClientX(evt) - off.x - this.diagramContainer.clientWidth > 0 || - mxEvent.getClientY(evt) - off.y - this.diagramContainer.clientHeight > 0) - { - this.diagramContainer.setAttribute('title', mxResources.get('panTooltip')); - } - else - { - this.diagramContainer.removeAttribute('title'); - } - })); - - // Escape key hides dialogs, adds space+drag panning - var spaceKeyPressed = false; - - // Overrides hovericons to disable while space key is pressed - var hoverIconsIsResetEvent = this.hoverIcons.isResetEvent; - - this.hoverIcons.isResetEvent = function(evt, allowShift) - { - return spaceKeyPressed || hoverIconsIsResetEvent.apply(this, arguments); - }; - - this.keydownHandler = mxUtils.bind(this, function(evt) - { - if (evt.which == 32 /* Space */ && !graph.isEditing()) - { - spaceKeyPressed = true; - this.hoverIcons.reset(); - graph.container.style.cursor = 'move'; - - // Disables scroll after space keystroke with scrollbars - if (!graph.isEditing() && mxEvent.getSource(evt) == graph.container) - { - mxEvent.consume(evt); - } - } - else if (!mxEvent.isConsumed(evt) && evt.keyCode == 27 /* Escape */) - { - this.hideDialog(null, true); - } - }); - - mxEvent.addListener(document, 'keydown', this.keydownHandler); - - this.keyupHandler = mxUtils.bind(this, function(evt) - { - graph.container.style.cursor = ''; - spaceKeyPressed = false; - }); - - mxEvent.addListener(document, 'keyup', this.keyupHandler); - - // Forces panning for middle and right mouse buttons - var panningHandlerIsForcePanningEvent = graph.panningHandler.isForcePanningEvent; - graph.panningHandler.isForcePanningEvent = function(me) - { - // Ctrl+left button is reported as right button in FF on Mac - return panningHandlerIsForcePanningEvent.apply(this, arguments) || - spaceKeyPressed || (mxEvent.isMouseEvent(me.getEvent()) && - (this.usePopupTrigger || !mxEvent.isPopupTrigger(me.getEvent())) && - ((!mxEvent.isControlDown(me.getEvent()) && - mxEvent.isRightMouseButton(me.getEvent())) || - mxEvent.isMiddleMouseButton(me.getEvent()))); - }; - - // Ctrl/Cmd+Enter applies editing value except in Safari where Ctrl+Enter creates - // a new line (while Enter creates a new paragraph and Shift+Enter stops) - var cellEditorIsStopEditingEvent = graph.cellEditor.isStopEditingEvent; - graph.cellEditor.isStopEditingEvent = function(evt) - { - return cellEditorIsStopEditingEvent.apply(this, arguments) || - (evt.keyCode == 13 && ((!mxClient.IS_SF && mxEvent.isControlDown(evt)) || - (mxClient.IS_MAC && mxEvent.isMetaDown(evt)) || - (mxClient.IS_SF && mxEvent.isShiftDown(evt)))); - }; - - // Adds space+wheel for zoom - var graphIsZoomWheelEvent = graph.isZoomWheelEvent; - - graph.isZoomWheelEvent = function() - { - return spaceKeyPressed || graphIsZoomWheelEvent.apply(this, arguments); - }; - - // Switches toolbar for text editing - var textMode = false; - var fontMenu = null; - var sizeMenu = null; - var nodes = null; - - var updateToolbar = mxUtils.bind(this, function() - { - if (this.toolbar != null && textMode != graph.cellEditor.isContentEditing()) - { - var node = this.toolbar.container.firstChild; - var newNodes = []; - - while (node != null) - { - var tmp = node.nextSibling; - - if (mxUtils.indexOf(this.toolbar.staticElements, node) < 0) - { - node.parentNode.removeChild(node); - newNodes.push(node); - } - - node = tmp; - } - - // Saves references to special items - var tmp1 = this.toolbar.fontMenu; - var tmp2 = this.toolbar.sizeMenu; - - if (nodes == null) - { - this.toolbar.createTextToolbar(); - } - else - { - for (var i = 0; i < nodes.length; i++) - { - this.toolbar.container.appendChild(nodes[i]); - } - - // Restores references to special items - this.toolbar.fontMenu = fontMenu; - this.toolbar.sizeMenu = sizeMenu; - } - - textMode = graph.cellEditor.isContentEditing(); - fontMenu = tmp1; - sizeMenu = tmp2; - nodes = newNodes; - } - }); - - var ui = this; - - // Overrides cell editor to update toolbar - var cellEditorStartEditing = graph.cellEditor.startEditing; - graph.cellEditor.startEditing = function() - { - cellEditorStartEditing.apply(this, arguments); - updateToolbar(); - - if (graph.cellEditor.isContentEditing()) - { - var updating = false; - - var updateCssHandler = function() - { - if (!updating) - { - updating = true; - - window.setTimeout(function() - { - var node = graph.getSelectedEditingElement(); - - if (node != null) - { - var css = mxUtils.getCurrentStyle(node); - - if (css != null && ui.toolbar != null) - { - ui.toolbar.setFontName(Graph.stripQuotes(css.fontFamily)); - ui.toolbar.setFontSize(parseInt(css.fontSize)); - } - } - - updating = false; - }, 0); - } - }; - - mxEvent.addListener(graph.cellEditor.textarea, 'input', updateCssHandler) - mxEvent.addListener(graph.cellEditor.textarea, 'touchend', updateCssHandler); - mxEvent.addListener(graph.cellEditor.textarea, 'mouseup', updateCssHandler); - mxEvent.addListener(graph.cellEditor.textarea, 'keyup', updateCssHandler); - updateCssHandler(); - } - }; - - // Updates toolbar and handles possible errors - var cellEditorStopEditing = graph.cellEditor.stopEditing; - graph.cellEditor.stopEditing = function(cell, trigger) - { - try - { - cellEditorStopEditing.apply(this, arguments); - updateToolbar(); - } - catch (e) - { - ui.handleError(e); - } - }; - - // Enables scrollbars and sets cursor style for the container - graph.container.setAttribute('tabindex', '0'); - graph.container.style.cursor = 'default'; - - // Workaround for page scroll if embedded via iframe - if (window.self === window.top && graph.container.parentNode != null) - { - try - { - graph.container.focus(); - } - catch (e) - { - // ignores error in old versions of IE - } - } - - // Keeps graph container focused on mouse down - var graphFireMouseEvent = graph.fireMouseEvent; - graph.fireMouseEvent = function(evtName, me, sender) - { - if (evtName == mxEvent.MOUSE_DOWN) - { - this.container.focus(); - } - - graphFireMouseEvent.apply(this, arguments); - }; - - // Configures automatic expand on mouseover - graph.popupMenuHandler.autoExpand = true; - - // Installs context menu - if (this.menus != null) - { - graph.popupMenuHandler.factoryMethod = mxUtils.bind(this, function(menu, cell, evt) - { - this.menus.createPopupMenu(menu, cell, evt); - }); - } - - // Hides context menu - mxEvent.addGestureListeners(document, mxUtils.bind(this, function(evt) - { - graph.popupMenuHandler.hideMenu(); - })); - - // Create handler for key events - this.keyHandler = this.createKeyHandler(editor); - - // Getter for key handler - this.getKeyHandler = function() - { - return keyHandler; - }; - - // Stores the current style and assigns it to new cells - var styles = ['rounded', 'shadow', 'glass', 'dashed', 'dashPattern', 'labelBackgroundColor', - 'comic', 'sketch', 'fillWeight', 'hachureGap', 'hachureAngle', 'jiggle', - 'disableMultiStroke', 'disableMultiStrokeFill', 'fillStyle', 'curveFitting', - 'simplification', 'sketchStyle']; - var connectStyles = ['shape', 'edgeStyle', 'curved', 'rounded', 'elbow', 'jumpStyle', 'jumpSize', - 'comic', 'sketch', 'fillWeight', 'hachureGap', 'hachureAngle', 'jiggle', - 'disableMultiStroke', 'disableMultiStrokeFill', 'fillStyle', 'curveFitting', - 'simplification', 'sketchStyle']; - - // Note: Everything that is not in styles is ignored (styles is augmented below) - this.setDefaultStyle = function(cell) - { - try - { - var state = graph.view.getState(cell); - - if (state != null) - { - // Ignores default styles - var clone = cell.clone(); - clone.style = '' - var defaultStyle = graph.getCellStyle(clone); - var values = []; - var keys = []; - - for (var key in state.style) - { - if (defaultStyle[key] != state.style[key]) - { - values.push(state.style[key]); - keys.push(key); - } - } - - // Handles special case for value "none" - var cellStyle = graph.getModel().getStyle(state.cell); - var tokens = (cellStyle != null) ? cellStyle.split(';') : []; - - for (var i = 0; i < tokens.length; i++) - { - var tmp = tokens[i]; - var pos = tmp.indexOf('='); - - if (pos >= 0) - { - var key = tmp.substring(0, pos); - var value = tmp.substring(pos + 1); - - if (defaultStyle[key] != null && value == 'none') - { - values.push(value); - keys.push(key); - } - } - } - - // Resets current style - if (graph.getModel().isEdge(state.cell)) - { - graph.currentEdgeStyle = {}; - } - else - { - graph.currentVertexStyle = {} - } - - this.fireEvent(new mxEventObject('styleChanged', 'keys', keys, 'values', values, 'cells', [state.cell])); - } - } - catch (e) - { - this.handleError(e); - } - }; - - this.clearDefaultStyle = function() - { - graph.currentEdgeStyle = mxUtils.clone(graph.defaultEdgeStyle); - graph.currentVertexStyle = mxUtils.clone(graph.defaultVertexStyle); - - // Updates UI - this.fireEvent(new mxEventObject('styleChanged', 'keys', [], 'values', [], 'cells', [])); - }; - - // Keys that should be ignored if the cell has a value (known: new default for all cells is html=1 so - // for the html key this effecticely only works for edges inserted via the connection handler) - var valueStyles = ['fontFamily', 'fontSource', 'fontSize', 'fontColor']; - - // Keys that always update the current edge style regardless of selection - var alwaysEdgeStyles = ['edgeStyle', 'startArrow', 'startFill', 'startSize', 'endArrow', - 'endFill', 'endSize']; - - // Keys that are ignored together (if one appears all are ignored) - var keyGroups = [['startArrow', 'startFill', 'startSize', 'sourcePerimeterSpacing', - 'endArrow', 'endFill', 'endSize', 'targetPerimeterSpacing'], - ['strokeColor', 'strokeWidth'], - ['fillColor', 'gradientColor'], - valueStyles, - ['opacity'], - ['align'], - ['html']]; - - // Adds all keys used above to the styles array - for (var i = 0; i < keyGroups.length; i++) - { - for (var j = 0; j < keyGroups[i].length; j++) - { - styles.push(keyGroups[i][j]); - } - } - - for (var i = 0; i < connectStyles.length; i++) - { - if (mxUtils.indexOf(styles, connectStyles[i]) < 0) - { - styles.push(connectStyles[i]); - } - } - - // Implements a global current style for edges and vertices that is applied to new cells - var insertHandler = function(cells, asText, model) - { - model = (model != null) ? model : graph.getModel(); - - model.beginUpdate(); - try - { - for (var i = 0; i < cells.length; i++) - { - var cell = cells[i]; - - var appliedStyles; - - if (asText) - { - // Applies only basic text styles - appliedStyles = ['fontSize', 'fontFamily', 'fontColor']; - } - else - { - // Removes styles defined in the cell style from the styles to be applied - var cellStyle = model.getStyle(cell); - var tokens = (cellStyle != null) ? cellStyle.split(';') : []; - appliedStyles = styles.slice(); - - for (var j = 0; j < tokens.length; j++) - { - var tmp = tokens[j]; - var pos = tmp.indexOf('='); - - if (pos >= 0) - { - var key = tmp.substring(0, pos); - var index = mxUtils.indexOf(appliedStyles, key); - - if (index >= 0) - { - appliedStyles.splice(index, 1); - } - - // Handles special cases where one defined style ignores other styles - for (var k = 0; k < keyGroups.length; k++) - { - var group = keyGroups[k]; - - if (mxUtils.indexOf(group, key) >= 0) - { - for (var l = 0; l < group.length; l++) - { - var index2 = mxUtils.indexOf(appliedStyles, group[l]); - - if (index2 >= 0) - { - appliedStyles.splice(index2, 1); - } - } - } - } - } - } - } - - // Applies the current style to the cell - var edge = model.isEdge(cell); - var current = (edge) ? graph.currentEdgeStyle : graph.currentVertexStyle; - var newStyle = model.getStyle(cell); - - for (var j = 0; j < appliedStyles.length; j++) - { - var key = appliedStyles[j]; - var styleValue = current[key]; - - if (styleValue != null && (key != 'shape' || edge)) - { - // Special case: Connect styles are not applied here but in the connection handler - if (!edge || mxUtils.indexOf(connectStyles, key) < 0) - { - newStyle = mxUtils.setStyle(newStyle, key, styleValue); - } - } - } - - model.setStyle(cell, newStyle); - } - } - finally - { - model.endUpdate(); - } - }; - - graph.addListener('cellsInserted', function(sender, evt) - { - insertHandler(evt.getProperty('cells')); - }); - - graph.addListener('textInserted', function(sender, evt) - { - insertHandler(evt.getProperty('cells'), true); - }); - - this.insertHandler = insertHandler; - - graph.connectionHandler.addListener(mxEvent.CONNECT, function(sender, evt) - { - var cells = [evt.getProperty('cell')]; - - if (evt.getProperty('terminalInserted')) - { - cells.push(evt.getProperty('terminal')); - } - - insertHandler(cells); - }); - - this.addListener('styleChanged', mxUtils.bind(this, function(sender, evt) - { - // Checks if edges and/or vertices were modified - var cells = evt.getProperty('cells'); - var vertex = false; - var edge = false; - - if (cells.length > 0) - { - for (var i = 0; i < cells.length; i++) - { - vertex = graph.getModel().isVertex(cells[i]) || vertex; - edge = graph.getModel().isEdge(cells[i]) || edge; - - if (edge && vertex) - { - break; - } - } - } - else - { - vertex = true; - edge = true; - } - - var keys = evt.getProperty('keys'); - var values = evt.getProperty('values'); - - for (var i = 0; i < keys.length; i++) - { - var common = mxUtils.indexOf(valueStyles, keys[i]) >= 0; - - // Ignores transparent stroke colors - if (keys[i] != 'strokeColor' || (values[i] != null && values[i] != 'none')) - { - // Special case: Edge style and shape - if (mxUtils.indexOf(connectStyles, keys[i]) >= 0) - { - if (edge || mxUtils.indexOf(alwaysEdgeStyles, keys[i]) >= 0) - { - if (values[i] == null) - { - delete graph.currentEdgeStyle[keys[i]]; - } - else - { - graph.currentEdgeStyle[keys[i]] = values[i]; - } - } - // Uses style for vertex if defined in styles - else if (vertex && mxUtils.indexOf(styles, keys[i]) >= 0) - { - if (values[i] == null) - { - delete graph.currentVertexStyle[keys[i]]; - } - else - { - graph.currentVertexStyle[keys[i]] = values[i]; - } - } - } - else if (mxUtils.indexOf(styles, keys[i]) >= 0) - { - if (vertex || common) - { - if (values[i] == null) - { - delete graph.currentVertexStyle[keys[i]]; - } - else - { - graph.currentVertexStyle[keys[i]] = values[i]; - } - } - - if (edge || common || mxUtils.indexOf(alwaysEdgeStyles, keys[i]) >= 0) - { - if (values[i] == null) - { - delete graph.currentEdgeStyle[keys[i]]; - } - else - { - graph.currentEdgeStyle[keys[i]] = values[i]; - } - } - } - } - } - - if (this.toolbar != null) - { - this.toolbar.setFontName(graph.currentVertexStyle['fontFamily'] || Menus.prototype.defaultFont); - this.toolbar.setFontSize(graph.currentVertexStyle['fontSize'] || Menus.prototype.defaultFontSize); - - if (this.toolbar.edgeStyleMenu != null) - { - // Updates toolbar icon for edge style - var edgeStyleDiv = this.toolbar.edgeStyleMenu.getElementsByTagName('div')[0]; - - if (graph.currentEdgeStyle['edgeStyle'] == 'orthogonalEdgeStyle' && graph.currentEdgeStyle['curved'] == '1') - { - edgeStyleDiv.className = 'geSprite geSprite-curved'; - } - else if (graph.currentEdgeStyle['edgeStyle'] == 'straight' || graph.currentEdgeStyle['edgeStyle'] == 'none' || - graph.currentEdgeStyle['edgeStyle'] == null) - { - edgeStyleDiv.className = 'geSprite geSprite-straight'; - } - else if (graph.currentEdgeStyle['edgeStyle'] == 'entityRelationEdgeStyle') - { - edgeStyleDiv.className = 'geSprite geSprite-entity'; - } - else if (graph.currentEdgeStyle['edgeStyle'] == 'elbowEdgeStyle') - { - edgeStyleDiv.className = 'geSprite geSprite-' + ((graph.currentEdgeStyle['elbow'] == 'vertical') ? - 'verticalelbow' : 'horizontalelbow'); - } - else if (graph.currentEdgeStyle['edgeStyle'] == 'isometricEdgeStyle') - { - edgeStyleDiv.className = 'geSprite geSprite-' + ((graph.currentEdgeStyle['elbow'] == 'vertical') ? - 'verticalisometric' : 'horizontalisometric'); - } - else - { - edgeStyleDiv.className = 'geSprite geSprite-orthogonal'; - } - } - - if (this.toolbar.edgeShapeMenu != null) - { - // Updates icon for edge shape - var edgeShapeDiv = this.toolbar.edgeShapeMenu.getElementsByTagName('div')[0]; - - if (graph.currentEdgeStyle['shape'] == 'link') - { - edgeShapeDiv.className = 'geSprite geSprite-linkedge'; - } - else if (graph.currentEdgeStyle['shape'] == 'flexArrow') - { - edgeShapeDiv.className = 'geSprite geSprite-arrow'; - } - else if (graph.currentEdgeStyle['shape'] == 'arrow') - { - edgeShapeDiv.className = 'geSprite geSprite-simplearrow'; - } - else - { - edgeShapeDiv.className = 'geSprite geSprite-connection'; - } - } - - // Updates icon for optinal line start shape - if (this.toolbar.lineStartMenu != null) - { - var lineStartDiv = this.toolbar.lineStartMenu.getElementsByTagName('div')[0]; - - lineStartDiv.className = this.getCssClassForMarker('start', - graph.currentEdgeStyle['shape'], graph.currentEdgeStyle[mxConstants.STYLE_STARTARROW], - mxUtils.getValue(graph.currentEdgeStyle, 'startFill', '1')); - } - - // Updates icon for optinal line end shape - if (this.toolbar.lineEndMenu != null) - { - var lineEndDiv = this.toolbar.lineEndMenu.getElementsByTagName('div')[0]; - - lineEndDiv.className = this.getCssClassForMarker('end', - graph.currentEdgeStyle['shape'], graph.currentEdgeStyle[mxConstants.STYLE_ENDARROW], - mxUtils.getValue(graph.currentEdgeStyle, 'endFill', '1')); - } - } - })); - - // Update font size and font family labels - if (this.toolbar != null) - { - var update = mxUtils.bind(this, function() - { - var ff = graph.currentVertexStyle['fontFamily'] || 'Helvetica'; - var fs = String(graph.currentVertexStyle['fontSize'] || '12'); - var state = graph.getView().getState(graph.getSelectionCell()); - - if (state != null) - { - ff = state.style[mxConstants.STYLE_FONTFAMILY] || ff; - fs = state.style[mxConstants.STYLE_FONTSIZE] || fs; - - if (ff.length > 10) - { - ff = ff.substring(0, 8) + '...'; - } - } - - this.toolbar.setFontName(ff); - this.toolbar.setFontSize(fs); - }); - - graph.getSelectionModel().addListener(mxEvent.CHANGE, update); - graph.getModel().addListener(mxEvent.CHANGE, update); - } - - // Makes sure the current layer is visible when cells are added - graph.addListener(mxEvent.CELLS_ADDED, function(sender, evt) - { - var cells = evt.getProperty('cells'); - var parent = evt.getProperty('parent'); - - if (graph.getModel().isLayer(parent) && !graph.isCellVisible(parent) && cells != null && cells.length > 0) - { - graph.getModel().setVisible(parent, true); - } - }); - - // Global handler to hide the current menu - this.gestureHandler = mxUtils.bind(this, function(evt) - { - if (this.currentMenu != null && mxEvent.getSource(evt) != this.currentMenu.div) - { - this.hideCurrentMenu(); - } - }); - - mxEvent.addGestureListeners(document, this.gestureHandler); - - // Updates the editor UI after the window has been resized or the orientation changes - // Timeout is workaround for old IE versions which have a delay for DOM client sizes. - // Should not use delay > 0 to avoid handle multiple repaints during window resize - this.resizeHandler = mxUtils.bind(this, function() - { - window.setTimeout(mxUtils.bind(this, function() - { - if (this.editor.graph != null) - { - this.refresh(); - } - }), 0); - }); - - mxEvent.addListener(window, 'resize', this.resizeHandler); - - this.orientationChangeHandler = mxUtils.bind(this, function() - { - this.refresh(); - }); - - mxEvent.addListener(window, 'orientationchange', this.orientationChangeHandler); - - // Workaround for bug on iOS see - // http://stackoverflow.com/questions/19012135/ios-7-ipad-safari-landscape-innerheight-outerheight-layout-issue - if (mxClient.IS_IOS && !window.navigator.standalone) - { - this.scrollHandler = mxUtils.bind(this, function() - { - window.scrollTo(0, 0); - }); - - mxEvent.addListener(window, 'scroll', this.scrollHandler); - } - - /** - * Sets the initial scrollbar locations after a file was loaded. - */ - this.editor.addListener('resetGraphView', mxUtils.bind(this, function() - { - this.resetScrollbars(); - })); - - /** - * Repaints the grid. - */ - this.addListener('gridEnabledChanged', mxUtils.bind(this, function() - { - graph.view.validateBackground(); - })); - - this.addListener('backgroundColorChanged', mxUtils.bind(this, function() - { - graph.view.validateBackground(); - })); - - /** - * Repaints the grid. - */ - graph.addListener('gridSizeChanged', mxUtils.bind(this, function() - { - if (graph.isGridEnabled()) - { - graph.view.validateBackground(); - } - })); - - // Resets UI, updates action and menu states - this.editor.resetGraph(); - } - - this.init(); - - if (!graph.standalone) - { - this.open(); - } -}; - -// Extends mxEventSource -mxUtils.extend(EditorUi, mxEventSource); - -/** - * Global config that specifies if the compact UI elements should be used. - */ -EditorUi.compactUi = true; - -/** - * Specifies the size of the split bar. - */ -EditorUi.prototype.splitSize = (mxClient.IS_TOUCH || mxClient.IS_POINTER) ? 12 : 8; - -/** - * Specifies the height of the menubar. Default is 30. - */ -EditorUi.prototype.menubarHeight = 30; - -/** - * Specifies the width of the format panel should be enabled. Default is true. - */ -EditorUi.prototype.formatEnabled = true; - -/** - * Specifies the width of the format panel. Default is 240. - */ -EditorUi.prototype.formatWidth = 240; - -/** - * Specifies the height of the toolbar. Default is 38. - */ -EditorUi.prototype.toolbarHeight = 38; - -/** - * Specifies the height of the footer. Default is 28. - */ -EditorUi.prototype.footerHeight = 28; - -/** - * Specifies the height of the optional sidebarFooterContainer. Default is 34. - */ -EditorUi.prototype.sidebarFooterHeight = 34; - -/** - * Specifies the position of the horizontal split bar. Default is 240 or 118 for - * screen widths <= 640px. - */ -EditorUi.prototype.hsplitPosition = (screen.width <= 640) ? 118 : ((urlParams['sidebar-entries'] != 'large') ? 212 : 240); - -/** - * Specifies if animations are allowed in . Default is true. - */ -EditorUi.prototype.allowAnimation = true; - -/** - * Default is 2. - */ -EditorUi.prototype.lightboxMaxFitScale = 2; - -/** - * Default is 4. - */ -EditorUi.prototype.lightboxVerticalDivider = 4; - -/** - * Specifies if single click on horizontal split should collapse sidebar. Default is false. - */ -EditorUi.prototype.hsplitClickEnabled = false; - -/** - * Installs the listeners to update the action states. - */ -EditorUi.prototype.init = function() -{ - var graph = this.editor.graph; - - if (!graph.standalone) - { - if (urlParams['shape-picker'] != '0') - { - this.installShapePicker(); - } - - // Hides tooltips and connection points when scrolling - mxEvent.addListener(graph.container, 'scroll', mxUtils.bind(this, function() - { - graph.tooltipHandler.hide(); - - if (graph.connectionHandler != null && graph.connectionHandler.constraintHandler != null) - { - graph.connectionHandler.constraintHandler.reset(); - } - })); - - // Hides tooltip on escape - graph.addListener(mxEvent.ESCAPE, mxUtils.bind(this, function() - { - graph.tooltipHandler.hide(); - var rb = graph.getRubberband(); - - if (rb != null) - { - rb.cancel(); - } - })); - - mxEvent.addListener(graph.container, 'keydown', mxUtils.bind(this, function(evt) - { - this.onKeyDown(evt); - })); - - mxEvent.addListener(graph.container, 'keypress', mxUtils.bind(this, function(evt) - { - this.onKeyPress(evt); - })); - - // Updates action states - this.addUndoListener(); - this.addBeforeUnloadListener(); - - graph.getSelectionModel().addListener(mxEvent.CHANGE, mxUtils.bind(this, function() - { - this.updateActionStates(); - })); - - graph.getModel().addListener(mxEvent.CHANGE, mxUtils.bind(this, function() - { - this.updateActionStates(); - })); - - // Changes action states after change of default parent - var graphSetDefaultParent = graph.setDefaultParent; - var ui = this; - - this.editor.graph.setDefaultParent = function() - { - graphSetDefaultParent.apply(this, arguments); - ui.updateActionStates(); - }; - - // Hack to make editLink available in vertex handler - graph.editLink = ui.actions.get('editLink').funct; - - this.updateActionStates(); - this.initClipboard(); - this.initCanvas(); - - if (this.format != null) - { - this.format.init(); - } - } -}; - -/** - * Returns true if the given event should start editing. This implementation returns true. - */ -EditorUi.prototype.installShapePicker = function() -{ - var graph = this.editor.graph; - var ui = this; - - // Uses this event to process mouseDown to check the selection state before it is changed - graph.addListener(mxEvent.FIRE_MOUSE_EVENT, mxUtils.bind(this, function(sender, evt) - { - if (evt.getProperty('eventName') == 'mouseDown') - { - ui.hideShapePicker(); - } - })); - - graph.addListener(mxEvent.ESCAPE, mxUtils.bind(this, function() - { - ui.hideShapePicker(true); - })); - - graph.getSelectionModel().addListener(mxEvent.CHANGE, mxUtils.bind(this, function() - { - ui.hideShapePicker(true); - })); - - graph.getModel().addListener(mxEvent.CHANGE, mxUtils.bind(this, function() - { - ui.hideShapePicker(true); - })); - - // Counts as popup menu - var popupMenuHandlerIsMenuShowing = graph.popupMenuHandler.isMenuShowing; - - graph.popupMenuHandler.isMenuShowing = function() - { - return popupMenuHandlerIsMenuShowing.apply(this, arguments) || ui.shapePicker != null; - }; - - // Adds dbl click dialog for inserting shapes - var graphDblClick = graph.dblClick; - - graph.dblClick = function(evt, cell) - { - if (this.isEnabled()) - { - if (cell == null && ui.sidebar != null && !mxEvent.isShiftDown(evt)) - { - mxEvent.consume(evt); - var pt = mxUtils.convertPoint(this.container, mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - - // Asynchronous to avoid direct insert after double tap - window.setTimeout(mxUtils.bind(this, function() - { - ui.showShapePicker(pt.x, pt.y); - }), 30); - } - else - { - graphDblClick.apply(this, arguments); - } - } - }; - - if (this.hoverIcons != null) - { - var hoverIconsDrag = this.hoverIcons.drag; - - this.hoverIcons.drag = function() - { - ui.hideShapePicker(); - hoverIconsDrag.apply(this, arguments); - }; - - var hoverIconsExecute = this.hoverIcons.execute; - - this.hoverIcons.execute = function(state, dir, me) - { - var evt = me.getEvent(); - - if (!this.graph.isCloneEvent(evt) && !mxEvent.isShiftDown(evt)) - { - this.graph.connectVertex(state.cell, dir, this.graph.defaultEdgeLength, evt, null, null, mxUtils.bind(this, function(x, y, execute) - { - var temp = graph.getCompositeParent(state.cell); - var geo = graph.getCellGeometry(temp); - me.consume(); - - while (temp != null && graph.model.isVertex(temp) && geo != null && geo.relative) - { - cell = temp; - temp = graph.model.getParent(cell) - geo = graph.getCellGeometry(temp); - } - - // Asynchronous to avoid direct insert after double tap - window.setTimeout(mxUtils.bind(this, function() - { - ui.showShapePicker(me.getGraphX(), me.getGraphY(), temp, mxUtils.bind(this, function(cell) - { - execute(cell); - }), dir); - }), 30); - }), mxUtils.bind(this, function(result) - { - this.graph.selectCellsForConnectVertex(result, evt, this); - })); - } - else - { - hoverIconsExecute.apply(this, arguments); - } - }; - } -}; - -/** - * Creates a temporary graph instance for rendering off-screen content. - */ -EditorUi.prototype.showShapePicker = function(x, y, source, callback, direction) -{ - var cells = this.getCellsForShapePicker(source); - - if (cells != null && cells.length > 0) - { - var ui = this; - var graph = this.editor.graph; - var div = document.createElement('div'); - var sourceState = graph.view.getState(source); - var style = (source != null && (sourceState == null || - !graph.isTransparentState(sourceState))) ? - graph.copyStyle(source) : null; - - // Do not place entry under pointer for touch devices - div.className = 'geToolbarContainer geSidebarContainer geSidebar'; - div.style.cssText = 'position:absolute;left:' + x + 'px;top:' + y + - 'px;width:140px;border-radius:10px;padding:4px;text-align:center;' + - 'box-shadow:0px 0px 3px 1px #d1d1d1;padding: 6px 0 8px 0;'; - mxUtils.setPrefixedStyle(div.style, 'transform', 'translate(-22px,-22px)'); - - if (graph.background != null && graph.background != mxConstants.NONE) - { - div.style.backgroundColor = graph.background; - } - - graph.container.appendChild(div); - - var addCell = mxUtils.bind(this, function(cell) - { - // Wrapper needed to catch events - var node = document.createElement('a'); - node.className = 'geItem'; - node.style.cssText = 'position:relative;display:inline-block;position:relative;' + - 'width:30px;height:30px;cursor:pointer;overflow:hidden;padding:3px 0 0 3px;'; - div.appendChild(node); - - if (style != null) - { - this.sidebar.graph.pasteStyle(style, [cell]); - } - else - { - ui.insertHandler([cell], cell.value != '', this.sidebar.graph.model); - } - - this.sidebar.createThumb([cell], 25, 25, node, null, true, false, cell.geometry.width, cell.geometry.height); - - mxEvent.addListener(node, 'click', function() - { - var clone = graph.cloneCell(cell); - - if (callback != null) - { - callback(clone); - } - else - { - clone.geometry.x = graph.snap(Math.round(x / graph.view.scale) - - graph.view.translate.x - cell.geometry.width / 2); - clone.geometry.y = graph.snap(Math.round(y / graph.view.scale) - - graph.view.translate.y - cell.geometry.height / 2); - - graph.model.beginUpdate(); - try - { - graph.addCell(clone); - } - finally - { - graph.model.endUpdate(); - } - - graph.setSelectionCell(clone); - graph.scrollCellToVisible(clone); - graph.startEditingAtCell(clone); - - if (ui.hoverIcons != null) - { - ui.hoverIcons.update(graph.view.getState(clone)); - } - } - - ui.hideShapePicker(); - }); - }); - - for (var i = 0; i < cells.length; i++) - { - addCell(cells[i]); - } - - if (ui.hoverIcons != null) - { - ui.hoverIcons.reset(); - } - - graph.popupMenuHandler.hideMenu(); - graph.tooltipHandler.hideTooltip(); - this.hideCurrentMenu(); - this.hideShapePicker(); - - this.shapePickerCallback = callback; - this.shapePicker = div; - } -}; - -/** - * Creates a temporary graph instance for rendering off-screen content. - */ -EditorUi.prototype.getCellsForShapePicker = function(cell) -{ - var createVertex = mxUtils.bind(this, function(style, w, h, value) - { - return this.editor.graph.createVertex(null, null, value || '', 0, 0, w || 120, h || 60, style, false); - }); - - return [(cell != null) ? this.editor.graph.cloneCell(cell) : - createVertex('text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;', 40, 20, 'Text'), - createVertex('whiteSpace=wrap;html=1;'), - createVertex('ellipse;whiteSpace=wrap;html=1;', 120, 80), - createVertex('rhombus;whiteSpace=wrap;html=1;', 80, 80), - createVertex('shape=parallelogram;perimeter=parallelogramPerimeter;whiteSpace=wrap;html=1;fixedSize=1;'), - createVertex('shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;fixedSize=1;', 120, 60), - createVertex('shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;', 120, 80), - createVertex('shape=step;perimeter=stepPerimeter;whiteSpace=wrap;html=1;fixedSize=1;', 120, 80), - createVertex('shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;'), - createVertex('shape=cube;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;darkOpacity=0.05;darkOpacity2=0.1;', 120, 80), - createVertex('shape=note;whiteSpace=wrap;html=1;backgroundOutline=1;darkOpacity=0.05;', 80, 100), - createVertex('triangle;whiteSpace=wrap;html=1;', 60, 80), - createVertex('shape=document;whiteSpace=wrap;html=1;boundedLbl=1;', 120, 80), - createVertex('shape=tape;whiteSpace=wrap;html=1;', 120, 100), - createVertex('ellipse;shape=cloud;whiteSpace=wrap;html=1;', 120, 80), - createVertex('shape=cylinder;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;', 60, 80)]; -}; - -/** - * Creates a temporary graph instance for rendering off-screen content. - */ -EditorUi.prototype.hideShapePicker = function(cancel) -{ - if (this.shapePicker != null) - { - this.shapePicker.parentNode.removeChild(this.shapePicker); - this.shapePicker = null; - - if (!cancel && this.shapePickerCallback != null) - { - this.shapePickerCallback(); - } - - this.shapePickerCallback = null; - } -}; - -/** - * Returns true if the given event should start editing. This implementation returns true. - */ -EditorUi.prototype.onKeyDown = function(evt) -{ - var graph = this.editor.graph; - - // Tab selects next cell - if (evt.which == 9 && graph.isEnabled() && !mxEvent.isAltDown(evt) && - (!graph.isEditing() || !mxEvent.isShiftDown(evt))) - { - if (graph.isEditing()) - { - graph.stopEditing(false); - } - else - { - graph.selectCell(!mxEvent.isShiftDown(evt)); - } - - mxEvent.consume(evt); - } -}; - -/** - * Returns true if the given event should start editing. This implementation returns true. - */ -EditorUi.prototype.onKeyPress = function(evt) -{ - var graph = this.editor.graph; - - // KNOWN: Focus does not work if label is empty in quirks mode - if (this.isImmediateEditingEvent(evt) && !graph.isEditing() && !graph.isSelectionEmpty() && evt.which !== 0 && - evt.which !== 27 && !mxEvent.isAltDown(evt) && !mxEvent.isControlDown(evt) && !mxEvent.isMetaDown(evt)) - { - graph.escape(); - graph.startEditing(); - - // Workaround for FF where char is lost if cursor is placed before char - if (mxClient.IS_FF) - { - var ce = graph.cellEditor; - - if (ce.textarea != null) - { - ce.textarea.innerHTML = String.fromCharCode(evt.which); - - // Moves cursor to end of textarea - var range = document.createRange(); - range.selectNodeContents(ce.textarea); - range.collapse(false); - var sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } - } - } -}; - -/** - * Returns true if the given event should start editing. This implementation returns true. - */ -EditorUi.prototype.isImmediateEditingEvent = function(evt) -{ - return true; -}; - -/** - * Private helper method. - */ -EditorUi.prototype.getCssClassForMarker = function(prefix, shape, marker, fill) -{ - var result = ''; - - if (shape == 'flexArrow') - { - result = (marker != null && marker != mxConstants.NONE) ? - 'geSprite geSprite-' + prefix + 'blocktrans' : 'geSprite geSprite-noarrow'; - } - else - { - // SVG marker sprites - if (marker == 'box' || marker == 'halfCircle') - { - result = 'geSprite geSvgSprite geSprite-' + marker + ((prefix == 'end') ? ' geFlipSprite' : ''); - } - else if (marker == mxConstants.ARROW_CLASSIC) - { - result = (fill == '1') ? 'geSprite geSprite-' + prefix + 'classic' : 'geSprite geSprite-' + prefix + 'classictrans'; - } - else if (marker == mxConstants.ARROW_CLASSIC_THIN) - { - result = (fill == '1') ? 'geSprite geSprite-' + prefix + 'classicthin' : 'geSprite geSprite-' + prefix + 'classicthintrans'; - } - else if (marker == mxConstants.ARROW_OPEN) - { - result = 'geSprite geSprite-' + prefix + 'open'; - } - else if (marker == mxConstants.ARROW_OPEN_THIN) - { - result = 'geSprite geSprite-' + prefix + 'openthin'; - } - else if (marker == mxConstants.ARROW_BLOCK) - { - result = (fill == '1') ? 'geSprite geSprite-' + prefix + 'block' : 'geSprite geSprite-' + prefix + 'blocktrans'; - } - else if (marker == mxConstants.ARROW_BLOCK_THIN) - { - result = (fill == '1') ? 'geSprite geSprite-' + prefix + 'blockthin' : 'geSprite geSprite-' + prefix + 'blockthintrans'; - } - else if (marker == mxConstants.ARROW_OVAL) - { - result = (fill == '1') ? 'geSprite geSprite-' + prefix + 'oval' : 'geSprite geSprite-' + prefix + 'ovaltrans'; - } - else if (marker == mxConstants.ARROW_DIAMOND) - { - result = (fill == '1') ? 'geSprite geSprite-' + prefix + 'diamond' : 'geSprite geSprite-' + prefix + 'diamondtrans'; - } - else if (marker == mxConstants.ARROW_DIAMOND_THIN) - { - result = (fill == '1') ? 'geSprite geSprite-' + prefix + 'thindiamond' : 'geSprite geSprite-' + prefix + 'thindiamondtrans'; - } - else if (marker == 'openAsync') - { - result = 'geSprite geSprite-' + prefix + 'openasync'; - } - else if (marker == 'dash') - { - result = 'geSprite geSprite-' + prefix + 'dash'; - } - else if (marker == 'cross') - { - result = 'geSprite geSprite-' + prefix + 'cross'; - } - else if (marker == 'async') - { - result = (fill == '1') ? 'geSprite geSprite-' + prefix + 'async' : 'geSprite geSprite-' + prefix + 'asynctrans'; - } - else if (marker == 'circle' || marker == 'circlePlus') - { - result = (fill == '1' || marker == 'circle') ? 'geSprite geSprite-' + prefix + 'circle' : 'geSprite geSprite-' + prefix + 'circleplus'; - } - else if (marker == 'ERone') - { - result = 'geSprite geSprite-' + prefix + 'erone'; - } - else if (marker == 'ERmandOne') - { - result = 'geSprite geSprite-' + prefix + 'eronetoone'; - } - else if (marker == 'ERmany') - { - result = 'geSprite geSprite-' + prefix + 'ermany'; - } - else if (marker == 'ERoneToMany') - { - result = 'geSprite geSprite-' + prefix + 'eronetomany'; - } - else if (marker == 'ERzeroToOne') - { - result = 'geSprite geSprite-' + prefix + 'eroneopt'; - } - else if (marker == 'ERzeroToMany') - { - result = 'geSprite geSprite-' + prefix + 'ermanyopt'; - } - else - { - result = 'geSprite geSprite-noarrow'; - } - } - - return result; -}; - -/** - * Overridden in Menus.js - */ -EditorUi.prototype.createMenus = function() -{ - return null; -}; - -/** - * Hook for allowing selection and context menu for certain events. - */ -EditorUi.prototype.updatePasteActionStates = function() -{ - var graph = this.editor.graph; - var paste = this.actions.get('paste'); - var pasteHere = this.actions.get('pasteHere'); - - paste.setEnabled(this.editor.graph.cellEditor.isContentEditing() || (!mxClipboard.isEmpty() && - graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent()))); - pasteHere.setEnabled(paste.isEnabled()); -}; - -/** - * Hook for allowing selection and context menu for certain events. - */ -EditorUi.prototype.initClipboard = function() -{ - var ui = this; - - var mxClipboardCut = mxClipboard.cut; - mxClipboard.cut = function(graph) - { - if (graph.cellEditor.isContentEditing()) - { - document.execCommand('cut', false, null); - } - else - { - mxClipboardCut.apply(this, arguments); - } - - ui.updatePasteActionStates(); - }; - - var mxClipboardCopy = mxClipboard.copy; - mxClipboard.copy = function(graph) - { - var result = null; - - if (graph.cellEditor.isContentEditing()) - { - document.execCommand('copy', false, null); - } - else - { - result = result || graph.getSelectionCells(); - result = graph.getExportableCells(graph.model.getTopmostCells(result)); - - var cloneMap = new Object(); - var lookup = graph.createCellLookup(result); - var clones = graph.cloneCells(result, null, cloneMap); - - // Uses temporary model to force new IDs to be assigned - // to avoid having to carry over the mapping from object - // ID to cell ID to the paste operation - var model = new mxGraphModel(); - var parent = model.getChildAt(model.getRoot(), 0); - - for (var i = 0; i < clones.length; i++) - { - model.add(parent, clones[i]); - - // Checks for orphaned relative children and makes absolute - var state = graph.view.getState(result[i]); - - if (state != null) - { - var geo = graph.getCellGeometry(clones[i]); - - if (geo != null && geo.relative && !model.isEdge(result[i]) && - lookup[mxObjectIdentity.get(model.getParent(result[i]))] == null) - { - geo.offset = null; - geo.relative = false; - geo.x = state.x / state.view.scale - state.view.translate.x; - geo.y = state.y / state.view.scale - state.view.translate.y; - } - } - } - - graph.updateCustomLinks(graph.createCellMapping(cloneMap, lookup), clones); - - mxClipboard.insertCount = 1; - mxClipboard.setCells(clones); - } - - ui.updatePasteActionStates(); - - return result; - }; - - var mxClipboardPaste = mxClipboard.paste; - mxClipboard.paste = function(graph) - { - var result = null; - - if (graph.cellEditor.isContentEditing()) - { - document.execCommand('paste', false, null); - } - else - { - result = mxClipboardPaste.apply(this, arguments); - } - - ui.updatePasteActionStates(); - - return result; - }; - - // Overrides cell editor to update paste action state - var cellEditorStartEditing = this.editor.graph.cellEditor.startEditing; - - this.editor.graph.cellEditor.startEditing = function() - { - cellEditorStartEditing.apply(this, arguments); - ui.updatePasteActionStates(); - }; - - var cellEditorStopEditing = this.editor.graph.cellEditor.stopEditing; - - this.editor.graph.cellEditor.stopEditing = function(cell, trigger) - { - cellEditorStopEditing.apply(this, arguments); - ui.updatePasteActionStates(); - }; - - this.updatePasteActionStates(); -}; - -/** - * Delay between zoom steps when not using preview. - */ -EditorUi.prototype.lazyZoomDelay = 20; - -/** - * Delay before update of DOM when using preview. - */ -EditorUi.prototype.wheelZoomDelay = 400; - -/** - * Delay before update of DOM when using preview. - */ -EditorUi.prototype.buttonZoomDelay = 600; - -/** - * Initializes the infinite canvas. - */ -EditorUi.prototype.initCanvas = function() -{ - // Initial page layout view, scrollBuffer and timer-based scrolling - var graph = this.editor.graph; - graph.timerAutoScroll = true; - - /** - * Returns the padding for pages in page view with scrollbars. - */ - graph.getPagePadding = function() - { - return new mxPoint(Math.max(0, Math.round((graph.container.offsetWidth - 34) / graph.view.scale)), - Math.max(0, Math.round((graph.container.offsetHeight - 34) / graph.view.scale))); - }; - - // Fits the number of background pages to the graph - graph.view.getBackgroundPageBounds = function() - { - var layout = this.graph.getPageLayout(); - var page = this.graph.getPageSize(); - - return new mxRectangle(this.scale * (this.translate.x + layout.x * page.width), - this.scale * (this.translate.y + layout.y * page.height), - this.scale * layout.width * page.width, - this.scale * layout.height * page.height); - }; - - graph.getPreferredPageSize = function(bounds, width, height) - { - var pages = this.getPageLayout(); - var size = this.getPageSize(); - - return new mxRectangle(0, 0, pages.width * size.width, pages.height * size.height); - }; - - // Scales pages/graph to fit available size - var resize = null; - var ui = this; - - if (this.editor.isChromelessView()) - { - resize = mxUtils.bind(this, function(autoscale, maxScale, cx, cy) - { - if (graph.container != null && !graph.isViewer()) - { - cx = (cx != null) ? cx : 0; - cy = (cy != null) ? cy : 0; - - var bds = (graph.pageVisible) ? graph.view.getBackgroundPageBounds() : graph.getGraphBounds(); - var scroll = mxUtils.hasScrollbars(graph.container); - var tr = graph.view.translate; - var s = graph.view.scale; - - // Normalizes the bounds - var b = mxRectangle.fromRectangle(bds); - b.x = b.x / s - tr.x; - b.y = b.y / s - tr.y; - b.width /= s; - b.height /= s; - - var st = graph.container.scrollTop; - var sl = graph.container.scrollLeft; - var sb = (mxClient.IS_QUIRKS || document.documentMode >= 8) ? 20 : 14; - - if (document.documentMode == 8 || document.documentMode == 9) - { - sb += 3; - } - - var cw = graph.container.offsetWidth - sb; - var ch = graph.container.offsetHeight - sb; - - var ns = (autoscale) ? Math.max(0.3, Math.min(maxScale || 1, cw / b.width)) : s; - var dx = ((cw - ns * b.width) / 2) / ns; - var dy = (this.lightboxVerticalDivider == 0) ? 0 : ((ch - ns * b.height) / this.lightboxVerticalDivider) / ns; - - if (scroll) - { - dx = Math.max(dx, 0); - dy = Math.max(dy, 0); - } - - if (scroll || bds.width < cw || bds.height < ch) - { - graph.view.scaleAndTranslate(ns, Math.floor(dx - b.x), Math.floor(dy - b.y)); - graph.container.scrollTop = st * ns / s; - graph.container.scrollLeft = sl * ns / s; - } - else if (cx != 0 || cy != 0) - { - var t = graph.view.translate; - graph.view.setTranslate(Math.floor(t.x + cx / s), Math.floor(t.y + cy / s)); - } - } - }); - - // Hack to make function available to subclassers - this.chromelessResize = resize; - - // Hook for subclassers for override - this.chromelessWindowResize = mxUtils.bind(this, function() - { - this.chromelessResize(false); - }); - - // Removable resize listener - var autoscaleResize = mxUtils.bind(this, function() - { - this.chromelessWindowResize(false); - }); - - mxEvent.addListener(window, 'resize', autoscaleResize); - - this.destroyFunctions.push(function() - { - mxEvent.removeListener(window, 'resize', autoscaleResize); - }); - - this.editor.addListener('resetGraphView', mxUtils.bind(this, function() - { - this.chromelessResize(true); - })); - - this.actions.get('zoomIn').funct = mxUtils.bind(this, function(evt) - { - graph.zoomIn(); - this.chromelessResize(false); - }); - this.actions.get('zoomOut').funct = mxUtils.bind(this, function(evt) - { - graph.zoomOut(); - this.chromelessResize(false); - }); - - // Creates toolbar for viewer - do not use CSS here - // as this may be used in a viewer that has no CSS - if (urlParams['toolbar'] != '0') - { - var toolbarConfig = JSON.parse(decodeURIComponent(urlParams['toolbar-config'] || '{}')); - - this.chromelessToolbar = document.createElement('div'); - this.chromelessToolbar.style.position = 'fixed'; - this.chromelessToolbar.style.overflow = 'hidden'; - this.chromelessToolbar.style.boxSizing = 'border-box'; - this.chromelessToolbar.style.whiteSpace = 'nowrap'; - this.chromelessToolbar.style.backgroundColor = '#000000'; - this.chromelessToolbar.style.padding = '10px 10px 8px 10px'; - this.chromelessToolbar.style.left = (graph.isViewer()) ? '0' : '50%'; - - if (!mxClient.IS_VML) - { - mxUtils.setPrefixedStyle(this.chromelessToolbar.style, 'borderRadius', '20px'); - mxUtils.setPrefixedStyle(this.chromelessToolbar.style, 'transition', 'opacity 600ms ease-in-out'); - } - - var updateChromelessToolbarPosition = mxUtils.bind(this, function() - { - var css = mxUtils.getCurrentStyle(graph.container); - - if (graph.isViewer()) - { - this.chromelessToolbar.style.top = '0'; - } - else - { - this.chromelessToolbar.style.bottom = ((css != null) ? parseInt(css['margin-bottom'] || 0) : 0) + - ((this.tabContainer != null) ? (20 + parseInt(this.tabContainer.style.height)) : 20) + 'px'; - } - }); - - this.editor.addListener('resetGraphView', updateChromelessToolbarPosition); - updateChromelessToolbarPosition(); - - var btnCount = 0; - - var addButton = mxUtils.bind(this, function(fn, imgSrc, tip) - { - btnCount++; - - var a = document.createElement('span'); - a.style.paddingLeft = '8px'; - a.style.paddingRight = '8px'; - a.style.cursor = 'pointer'; - mxEvent.addListener(a, 'click', fn); - - if (tip != null) - { - a.setAttribute('title', tip); - } - - var img = document.createElement('img'); - img.setAttribute('border', '0'); - img.setAttribute('src', imgSrc); - - a.appendChild(img); - this.chromelessToolbar.appendChild(a); - - return a; - }); - - if (toolbarConfig.backBtn != null) - { - addButton(mxUtils.bind(this, function(evt) - { - window.location.href = toolbarConfig.backBtn.url; - mxEvent.consume(evt); - }), Editor.backLargeImage, mxResources.get('back', null, 'Back')); - } - - if (this.isPagesEnabled()) - { - var prevButton = addButton(mxUtils.bind(this, function(evt) - { - this.actions.get('previousPage').funct(); - mxEvent.consume(evt); - }), Editor.previousLargeImage, mxResources.get('previousPage')); - - var pageInfo = document.createElement('div'); - pageInfo.style.display = 'inline-block'; - pageInfo.style.verticalAlign = 'top'; - pageInfo.style.fontFamily = 'Helvetica,Arial'; - pageInfo.style.marginTop = '8px'; - pageInfo.style.fontSize = '14px'; - pageInfo.style.color = '#ffffff'; - this.chromelessToolbar.appendChild(pageInfo); - - var nextButton = addButton(mxUtils.bind(this, function(evt) - { - this.actions.get('nextPage').funct(); - mxEvent.consume(evt); - }), Editor.nextLargeImage, mxResources.get('nextPage')); - - var updatePageInfo = mxUtils.bind(this, function() - { - if (this.pages != null && this.pages.length > 1 && this.currentPage != null) - { - pageInfo.innerHTML = ''; - mxUtils.write(pageInfo, (mxUtils.indexOf(this.pages, this.currentPage) + 1) + ' / ' + this.pages.length); - } - }); - - prevButton.style.paddingLeft = '0px'; - prevButton.style.paddingRight = '4px'; - nextButton.style.paddingLeft = '4px'; - nextButton.style.paddingRight = '0px'; - - var updatePageButtons = mxUtils.bind(this, function() - { - if (this.pages != null && this.pages.length > 1 && this.currentPage != null) - { - nextButton.style.display = ''; - prevButton.style.display = ''; - pageInfo.style.display = 'inline-block'; - } - else - { - nextButton.style.display = 'none'; - prevButton.style.display = 'none'; - pageInfo.style.display = 'none'; - } - - updatePageInfo(); - }); - - this.editor.addListener('resetGraphView', updatePageButtons); - this.editor.addListener('pageSelected', updatePageInfo); - } - - addButton(mxUtils.bind(this, function(evt) - { - this.actions.get('zoomOut').funct(); - mxEvent.consume(evt); - }), Editor.zoomOutLargeImage, mxResources.get('zoomOut') + ' (Alt+Mousewheel)'); - - addButton(mxUtils.bind(this, function(evt) - { - this.actions.get('zoomIn').funct(); - mxEvent.consume(evt); - }), Editor.zoomInLargeImage, mxResources.get('zoomIn') + ' (Alt+Mousewheel)'); - - addButton(mxUtils.bind(this, function(evt) - { - if (graph.isLightboxView()) - { - if (graph.view.scale == 1) - { - this.lightboxFit(); - } - else - { - graph.zoomTo(1); - } - - this.chromelessResize(false); - } - else - { - this.chromelessResize(true); - } - - mxEvent.consume(evt); - }), Editor.actualSizeLargeImage, mxResources.get('fit')); - - // Changes toolbar opacity on hover - var fadeThread = null; - var fadeThread2 = null; - - var fadeOut = mxUtils.bind(this, function(delay) - { - if (fadeThread != null) - { - window.clearTimeout(fadeThread); - fadeThread = null; - } - - if (fadeThread2 != null) - { - window.clearTimeout(fadeThread2); - fadeThread2 = null; - } - - fadeThread = window.setTimeout(mxUtils.bind(this, function() - { - mxUtils.setOpacity(this.chromelessToolbar, 0); - fadeThread = null; - - fadeThread2 = window.setTimeout(mxUtils.bind(this, function() - { - this.chromelessToolbar.style.display = 'none'; - fadeThread2 = null; - }), 600); - }), delay || 200); - }); - - var fadeIn = mxUtils.bind(this, function(opacity) - { - if (fadeThread != null) - { - window.clearTimeout(fadeThread); - fadeThread = null; - } - - if (fadeThread2 != null) - { - window.clearTimeout(fadeThread2); - fadeThread2 = null; - } - - this.chromelessToolbar.style.display = ''; - mxUtils.setOpacity(this.chromelessToolbar, opacity || 30); - }); - - if (urlParams['layers'] == '1') - { - this.layersDialog = null; - - var layersButton = addButton(mxUtils.bind(this, function(evt) - { - if (this.layersDialog != null) - { - this.layersDialog.parentNode.removeChild(this.layersDialog); - this.layersDialog = null; - } - else - { - this.layersDialog = graph.createLayersDialog(); - - mxEvent.addListener(this.layersDialog, 'mouseleave', mxUtils.bind(this, function() - { - this.layersDialog.parentNode.removeChild(this.layersDialog); - this.layersDialog = null; - })); - - var r = layersButton.getBoundingClientRect(); - - mxUtils.setPrefixedStyle(this.layersDialog.style, 'borderRadius', '5px'); - this.layersDialog.style.position = 'fixed'; - this.layersDialog.style.fontFamily = 'Helvetica,Arial'; - this.layersDialog.style.backgroundColor = '#000000'; - this.layersDialog.style.width = '160px'; - this.layersDialog.style.padding = '4px 2px 4px 2px'; - this.layersDialog.style.color = '#ffffff'; - mxUtils.setOpacity(this.layersDialog, 70); - this.layersDialog.style.left = r.left + 'px'; - this.layersDialog.style.bottom = parseInt(this.chromelessToolbar.style.bottom) + - this.chromelessToolbar.offsetHeight + 4 + 'px'; - - // Puts the dialog on top of the container z-index - var style = mxUtils.getCurrentStyle(this.editor.graph.container); - this.layersDialog.style.zIndex = style.zIndex; - - document.body.appendChild(this.layersDialog); - } - - mxEvent.consume(evt); - }), Editor.layersLargeImage, mxResources.get('layers')); - - // Shows/hides layers button depending on content - var model = graph.getModel(); - - model.addListener(mxEvent.CHANGE, function() - { - layersButton.style.display = (model.getChildCount(model.root) > 1) ? '' : 'none'; - }); - } - - if (urlParams['openInSameWin'] != '1') - { - this.addChromelessToolbarItems(addButton); - } - - if (this.editor.editButtonLink != null || this.editor.editButtonFunc != null) - { - addButton(mxUtils.bind(this, function(evt) - { - if (this.editor.editButtonFunc != null) - { - this.editor.editButtonFunc(); - } - else if (this.editor.editButtonLink == '_blank') - { - this.editor.editAsNew(this.getEditBlankXml()); - } - else - { - graph.openLink(this.editor.editButtonLink, 'editWindow'); - } - - mxEvent.consume(evt); - }), Editor.editLargeImage, mxResources.get('edit')); - } - - if (this.lightboxToolbarActions != null) - { - for (var i = 0; i < this.lightboxToolbarActions.length; i++) - { - var lbAction = this.lightboxToolbarActions[i]; - addButton(lbAction.fn, lbAction.icon, lbAction.tooltip); - } - } - - if (toolbarConfig.refreshBtn != null) - { - addButton(mxUtils.bind(this, function(evt) - { - if (toolbarConfig.refreshBtn.url) - { - window.location.href = toolbarConfig.refreshBtn.url; - } - else - { - window.location.reload(); - } - - mxEvent.consume(evt); - }), Editor.refreshLargeImage, mxResources.get('refresh', null, 'Refresh')); - } - - if (toolbarConfig.fullscreenBtn != null && window.self !== window.top) - { - addButton(mxUtils.bind(this, function(evt) - { - if (toolbarConfig.fullscreenBtn.url) - { - graph.openLink(toolbarConfig.fullscreenBtn.url); - } - else - { - graph.openLink(window.location.href); - } - - mxEvent.consume(evt); - }), Editor.fullscreenLargeImage, mxResources.get('openInNewWindow', null, 'Open in New Window')); - } - - if ((toolbarConfig.closeBtn && window.self === window.top) || - (graph.lightbox && (urlParams['close'] == '1' || this.container != document.body))) - - { - addButton(mxUtils.bind(this, function(evt) - { - if (urlParams['close'] == '1' || toolbarConfig.closeBtn) - { - window.close(); - } - else - { - this.destroy(); - mxEvent.consume(evt); - } - }), Editor.closeLargeImage, mxResources.get('close') + ' (Escape)'); - } - - // Initial state invisible - this.chromelessToolbar.style.display = 'none'; - - if (!graph.isViewer()) - { - mxUtils.setPrefixedStyle(this.chromelessToolbar.style, 'transform', 'translate(-50%,0)'); - } - - graph.container.appendChild(this.chromelessToolbar); - - mxEvent.addListener(graph.container, (mxClient.IS_POINTER) ? 'pointermove' : 'mousemove', mxUtils.bind(this, function(evt) - { - if (!mxEvent.isTouchEvent(evt)) - { - if (!mxEvent.isShiftDown(evt)) - { - fadeIn(30); - } - - fadeOut(); - } - })); - - mxEvent.addListener(this.chromelessToolbar, (mxClient.IS_POINTER) ? 'pointermove' : 'mousemove', function(evt) - { - mxEvent.consume(evt); - }); - - mxEvent.addListener(this.chromelessToolbar, 'mouseenter', mxUtils.bind(this, function(evt) - { - if (!mxEvent.isShiftDown(evt)) - { - fadeIn(100); - } - else - { - fadeOut(); - } - })); - - mxEvent.addListener(this.chromelessToolbar, 'mousemove', mxUtils.bind(this, function(evt) - { - if (!mxEvent.isShiftDown(evt)) - { - fadeIn(100); - } - else - { - fadeOut(); - } - - mxEvent.consume(evt); - })); - - mxEvent.addListener(this.chromelessToolbar, 'mouseleave', mxUtils.bind(this, function(evt) - { - if (!mxEvent.isTouchEvent(evt)) - { - fadeIn(30); - } - })); - - // Shows/hides toolbar for touch devices - var tol = graph.getTolerance(); - - graph.addMouseListener( - { - startX: 0, - startY: 0, - scrollLeft: 0, - scrollTop: 0, - mouseDown: function(sender, me) - { - this.startX = me.getGraphX(); - this.startY = me.getGraphY(); - this.scrollLeft = graph.container.scrollLeft; - this.scrollTop = graph.container.scrollTop; - }, - mouseMove: function(sender, me) {}, - mouseUp: function(sender, me) - { - if (mxEvent.isTouchEvent(me.getEvent())) - { - if ((Math.abs(this.scrollLeft - graph.container.scrollLeft) < tol && - Math.abs(this.scrollTop - graph.container.scrollTop) < tol) && - (Math.abs(this.startX - me.getGraphX()) < tol && - Math.abs(this.startY - me.getGraphY()) < tol)) - { - if (parseFloat(ui.chromelessToolbar.style.opacity || 0) > 0) - { - fadeOut(); - } - else - { - fadeIn(30); - } - } - } - } - }); - } // end if toolbar - - // Installs handling of highlight and handling links to relative links and anchors - if (!this.editor.editable) - { - this.addChromelessClickHandler(); - } - } - else if (this.editor.extendCanvas) - { - /** - * Guesses autoTranslate to avoid another repaint (see below). - * Works if only the scale of the graph changes or if pages - * are visible and the visible pages do not change. - */ - var graphViewValidate = graph.view.validate; - graph.view.validate = function() - { - if (this.graph.container != null && mxUtils.hasScrollbars(this.graph.container)) - { - var pad = this.graph.getPagePadding(); - var size = this.graph.getPageSize(); - - // Updating scrollbars here causes flickering in quirks and is not needed - // if zoom method is always used to set the current scale on the graph. - var tx = this.translate.x; - var ty = this.translate.y; - this.translate.x = pad.x - (this.x0 || 0) * size.width; - this.translate.y = pad.y - (this.y0 || 0) * size.height; - } - - graphViewValidate.apply(this, arguments); - }; - - if (!graph.isViewer()) - { - var graphSizeDidChange = graph.sizeDidChange; - - graph.sizeDidChange = function() - { - if (this.container != null && mxUtils.hasScrollbars(this.container)) - { - var pages = this.getPageLayout(); - var pad = this.getPagePadding(); - var size = this.getPageSize(); - - // Updates the minimum graph size - var minw = Math.ceil(2 * pad.x + pages.width * size.width); - var minh = Math.ceil(2 * pad.y + pages.height * size.height); - - var min = graph.minimumGraphSize; - - // LATER: Fix flicker of scrollbar size in IE quirks mode - // after delayed call in window.resize event handler - if (min == null || min.width != minw || min.height != minh) - { - graph.minimumGraphSize = new mxRectangle(0, 0, minw, minh); - } - - // Updates auto-translate to include padding and graph size - var dx = pad.x - pages.x * size.width; - var dy = pad.y - pages.y * size.height; - - if (!this.autoTranslate && (this.view.translate.x != dx || this.view.translate.y != dy)) - { - this.autoTranslate = true; - this.view.x0 = pages.x; - this.view.y0 = pages.y; - - // NOTE: THIS INVOKES THIS METHOD AGAIN. UNFORTUNATELY THERE IS NO WAY AROUND THIS SINCE THE - // BOUNDS ARE KNOWN AFTER THE VALIDATION AND SETTING THE TRANSLATE TRIGGERS A REVALIDATION. - // SHOULD MOVE TRANSLATE/SCALE TO VIEW. - var tx = graph.view.translate.x; - var ty = graph.view.translate.y; - graph.view.setTranslate(dx, dy); - - // LATER: Fix rounding errors for small zoom - graph.container.scrollLeft += Math.round((dx - tx) * graph.view.scale); - graph.container.scrollTop += Math.round((dy - ty) * graph.view.scale); - - this.autoTranslate = false; - - return; - } - - graphSizeDidChange.apply(this, arguments); - } - else - { - // Fires event but does not invoke superclass - this.fireEvent(new mxEventObject(mxEvent.SIZE, 'bounds', this.getGraphBounds())); - } - }; - } - } - - // Accumulates the zoom factor while the rendering is taking place - // so that not the complete sequence of zoom steps must be painted - var bgGroup = graph.view.getBackgroundPane(); - var mainGroup = graph.view.getDrawPane(); - graph.cumulativeZoomFactor = 1; - var updateZoomTimeout = null; - var cursorPosition = null; - var scrollPosition = null; - var forcedZoom = null; - var filter = null; - - var scheduleZoom = function(delay) - { - if (updateZoomTimeout != null) - { - window.clearTimeout(updateZoomTimeout); - } - - window.setTimeout(function() - { - if (!graph.isMouseDown || forcedZoom) - { - updateZoomTimeout = window.setTimeout(mxUtils.bind(this, function() - { - if (graph.isFastZoomEnabled()) - { - // Transforms background page - if (graph.view.backgroundPageShape != null && graph.view.backgroundPageShape.node != null) - { - mxUtils.setPrefixedStyle(graph.view.backgroundPageShape.node.style, 'transform-origin', null); - mxUtils.setPrefixedStyle(graph.view.backgroundPageShape.node.style, 'transform', null); - } - - // Transforms graph and background image - mainGroup.style.transformOrigin = ''; - bgGroup.style.transformOrigin = ''; - - // Workaround for no reset of transform in Safari - if (mxClient.IS_SF) - { - mainGroup.style.transform = 'scale(1)'; - bgGroup.style.transform = 'scale(1)'; - - window.setTimeout(function() - { - mainGroup.style.transform = ''; - bgGroup.style.transform = ''; - }, 0) - } - else - { - mainGroup.style.transform = ''; - bgGroup.style.transform = ''; - } - - // Shows interactive elements - graph.view.getDecoratorPane().style.opacity = ''; - graph.view.getOverlayPane().style.opacity = ''; - } - - var sp = new mxPoint(graph.container.scrollLeft, graph.container.scrollTop); - var offset = mxUtils.getOffset(graph.container); - var prev = graph.view.scale; - var dx = 0; - var dy = 0; - - if (cursorPosition != null) - { - dx = graph.container.offsetWidth / 2 - cursorPosition.x + offset.x; - dy = graph.container.offsetHeight / 2 - cursorPosition.y + offset.y; - } - - graph.zoom(graph.cumulativeZoomFactor); - var s = graph.view.scale; - - if (s != prev) - { - if (scrollPosition != null) - { - dx += sp.x - scrollPosition.x; - dy += sp.y - scrollPosition.y; - } - - if (resize != null) - { - ui.chromelessResize(false, null, dx * (graph.cumulativeZoomFactor - 1), - dy * (graph.cumulativeZoomFactor - 1)); - } - - if (mxUtils.hasScrollbars(graph.container) && (dx != 0 || dy != 0)) - { - graph.container.scrollLeft -= dx * (graph.cumulativeZoomFactor - 1); - graph.container.scrollTop -= dy * (graph.cumulativeZoomFactor - 1); - } - } - - if (filter != null) - { - mainGroup.setAttribute('filter', filter); - } - - graph.cumulativeZoomFactor = 1; - updateZoomTimeout = null; - scrollPosition = null; - cursorPosition = null; - forcedZoom = null; - filter = null; - }), (delay != null) ? delay : ((graph.isFastZoomEnabled()) ? ui.wheelZoomDelay : ui.lazyZoomDelay)); - } - }, 0); - }; - - graph.lazyZoom = function(zoomIn, ignoreCursorPosition, delay) - { - // TODO: Fix ignored cursor position if scrollbars are disabled - ignoreCursorPosition = ignoreCursorPosition || !graph.scrollbars; - - if (ignoreCursorPosition) - { - cursorPosition = new mxPoint( - graph.container.offsetLeft + graph.container.clientWidth / 2, - graph.container.offsetTop + graph.container.clientHeight / 2); - } - - // Switches to 5% zoom steps below 15% - if (zoomIn) - { - if (this.view.scale * this.cumulativeZoomFactor <= 0.15) - { - this.cumulativeZoomFactor *= (this.view.scale + 0.05) / this.view.scale; - } - else - { - // Uses to 5% zoom steps for better grid rendering in webkit - // and to avoid rounding errors for zoom steps - this.cumulativeZoomFactor *= this.zoomFactor; - this.cumulativeZoomFactor = Math.round(this.view.scale * this.cumulativeZoomFactor * 20) / 20 / this.view.scale; - } - } - else - { - if (this.view.scale * this.cumulativeZoomFactor <= 0.15) - { - this.cumulativeZoomFactor *= (this.view.scale - 0.05) / this.view.scale; - } - else - { - // Uses to 5% zoom steps for better grid rendering in webkit - // and to avoid rounding errors for zoom steps - this.cumulativeZoomFactor /= this.zoomFactor; - this.cumulativeZoomFactor = Math.round(this.view.scale * this.cumulativeZoomFactor * 20) / 20 / this.view.scale; - } - } - - this.cumulativeZoomFactor = Math.max(0.05, Math.min(this.view.scale * this.cumulativeZoomFactor, 160)) / this.view.scale; - - if (graph.isFastZoomEnabled()) - { - if (filter == null && mainGroup.getAttribute('filter') != '') - { - filter = mainGroup.getAttribute('filter'); - mainGroup.removeAttribute('filter'); - } - - scrollPosition = new mxPoint(graph.container.scrollLeft, graph.container.scrollTop); - - var cx = (ignoreCursorPosition) ? graph.container.scrollLeft + graph.container.clientWidth / 2 : - cursorPosition.x + graph.container.scrollLeft - graph.container.offsetLeft; - var cy = (ignoreCursorPosition) ? graph.container.scrollTop + graph.container.clientHeight / 2 : - cursorPosition.y + graph.container.scrollTop - graph.container.offsetTop; - mainGroup.style.transformOrigin = cx + 'px ' + cy + 'px'; - mainGroup.style.transform = 'scale(' + this.cumulativeZoomFactor + ')'; - bgGroup.style.transformOrigin = cx + 'px ' + cy + 'px'; - bgGroup.style.transform = 'scale(' + this.cumulativeZoomFactor + ')'; - - if (graph.view.backgroundPageShape != null && graph.view.backgroundPageShape.node != null) - { - var page = graph.view.backgroundPageShape.node; - - mxUtils.setPrefixedStyle(page.style, 'transform-origin', - ((ignoreCursorPosition) ? ((graph.container.clientWidth / 2 + graph.container.scrollLeft - - page.offsetLeft) + 'px') : ((cursorPosition.x + graph.container.scrollLeft - - page.offsetLeft - graph.container.offsetLeft) + 'px')) + ' ' + - ((ignoreCursorPosition) ? ((graph.container.clientHeight / 2 + graph.container.scrollTop - - page.offsetTop) + 'px') : ((cursorPosition.y + graph.container.scrollTop - - page.offsetTop - graph.container.offsetTop) + 'px'))); - mxUtils.setPrefixedStyle(page.style, 'transform', - 'scale(' + this.cumulativeZoomFactor + ')'); - } - - graph.view.getDecoratorPane().style.opacity = '0'; - graph.view.getOverlayPane().style.opacity = '0'; - - if (ui.hoverIcons != null) - { - ui.hoverIcons.reset(); - } - } - - scheduleZoom(delay); - }; - - // Holds back repaint until after mouse gestures - mxEvent.addGestureListeners(graph.container, function(evt) - { - if (updateZoomTimeout != null) - { - window.clearTimeout(updateZoomTimeout); - } - }, null, function(evt) - { - if (graph.cumulativeZoomFactor != 1) - { - scheduleZoom(0); - } - }); - - // Holds back repaint until scroll ends - mxEvent.addListener(graph.container, 'scroll', function(evt) - { - if (updateZoomTimeout != null && !graph.isMouseDown && graph.cumulativeZoomFactor != 1) - { - scheduleZoom(0); - } - }); - - mxEvent.addMouseWheelListener(mxUtils.bind(this, function(evt, up, force, cx, cy) - { - if (this.dialogs == null || this.dialogs.length == 0) - { - // Scrolls with scrollbars turned off - if (!graph.scrollbars && !force && graph.isScrollWheelEvent(evt)) - { - var t = graph.view.getTranslate(); - var step = 40 / graph.view.scale; - - if (!mxEvent.isShiftDown(evt)) - { - graph.view.setTranslate(t.x, t.y + ((up) ? step : -step)); - } - else - { - graph.view.setTranslate(t.x + ((up) ? -step : step), t.y); - } - } - else if (force || graph.isZoomWheelEvent(evt)) - { - var source = mxEvent.getSource(evt); - - while (source != null) - { - if (source == graph.container) - { - graph.tooltipHandler.hideTooltip(); - cursorPosition = (cx != null && cy!= null) ? new mxPoint(cx, cy) : - new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - forcedZoom = force; - graph.lazyZoom(up); - mxEvent.consume(evt); - - return false; - } - - source = source.parentNode; - } - } - } - }), graph.container); - - // Uses fast zoom for pinch gestures on iOS - graph.panningHandler.zoomGraph = function(evt) - { - graph.cumulativeZoomFactor = evt.scale; - graph.lazyZoom(evt.scale > 0, true); - mxEvent.consume(evt); - }; -}; - -/** - * Creates a temporary graph instance for rendering off-screen content. - */ -EditorUi.prototype.addChromelessToolbarItems = function(addButton) -{ - addButton(mxUtils.bind(this, function(evt) - { - this.actions.get('print').funct(); - mxEvent.consume(evt); - }), Editor.printLargeImage, mxResources.get('print')); -}; - -/** - * Creates a temporary graph instance for rendering off-screen content. - */ -EditorUi.prototype.isPagesEnabled = function() -{ - return this.editor.editable || urlParams['hide-pages'] != '1'; -}; - -/** - * Creates a temporary graph instance for rendering off-screen content. - */ -EditorUi.prototype.createTemporaryGraph = function(stylesheet) -{ - var graph = new Graph(document.createElement('div')); - graph.stylesheet.styles = mxUtils.clone(stylesheet.styles); - graph.resetViewOnRootChange = false; - graph.setConnectable(false); - graph.gridEnabled = false; - graph.autoScroll = false; - graph.setTooltips(false); - graph.setEnabled(false); - - // Container must be in the DOM for correct HTML rendering - graph.container.style.visibility = 'hidden'; - graph.container.style.position = 'absolute'; - graph.container.style.overflow = 'hidden'; - graph.container.style.height = '1px'; - graph.container.style.width = '1px'; - - return graph; -}; - -/** - * - */ -EditorUi.prototype.addChromelessClickHandler = function() -{ - var hl = urlParams['highlight']; - - // Adds leading # for highlight color code - if (hl != null && hl.length > 0) - { - hl = '#' + hl; - } - - this.editor.graph.addClickHandler(hl); -}; - -/** - * - */ -EditorUi.prototype.toggleFormatPanel = function(visible) -{ - visible = (visible != null) ? visible : this.formatWidth == 0; - - if (this.format != null) - { - this.formatWidth = (visible) ? 240 : 0; - this.formatContainer.style.display = (visible) ? '' : 'none'; - this.refresh(); - this.format.refresh(); - this.fireEvent(new mxEventObject('formatWidthChanged')); - } -}; - -/** - * Adds support for placeholders in labels. - */ -EditorUi.prototype.lightboxFit = function(maxHeight) -{ - if (this.isDiagramEmpty()) - { - this.editor.graph.view.setScale(1); - } - else - { - var p = urlParams['border']; - var border = 60; - - if (p != null) - { - border = parseInt(p); - } - - // LATER: Use initial graph bounds to avoid rounding errors - this.editor.graph.maxFitScale = this.lightboxMaxFitScale; - this.editor.graph.fit(border, null, null, null, null, null, maxHeight); - this.editor.graph.maxFitScale = null; - } -}; - -/** - * Translates this point by the given vector. - * - * @param {number} dx X-coordinate of the translation. - * @param {number} dy Y-coordinate of the translation. - */ -EditorUi.prototype.isDiagramEmpty = function() -{ - var model = this.editor.graph.getModel(); - - return model.getChildCount(model.root) == 1 && model.getChildCount(model.getChildAt(model.root, 0)) == 0; -}; - -/** - * Hook for allowing selection and context menu for certain events. - */ -EditorUi.prototype.isSelectionAllowed = function(evt) -{ - return mxEvent.getSource(evt).nodeName == 'SELECT' || (mxEvent.getSource(evt).nodeName == 'INPUT' && - mxUtils.isAncestorNode(this.formatContainer, mxEvent.getSource(evt))); -}; - -/** - * Installs dialog if browser window is closed without saving - * This must be disabled during save and image export. - */ -EditorUi.prototype.addBeforeUnloadListener = function() -{ - // Installs dialog if browser window is closed without saving - // This must be disabled during save and image export - window.onbeforeunload = mxUtils.bind(this, function() - { - if (!this.editor.isChromelessView()) - { - return this.onBeforeUnload(); - } - }); -}; - -/** - * Sets the onbeforeunload for the application - */ -EditorUi.prototype.onBeforeUnload = function() -{ - if (this.editor.modified) - { - return mxResources.get('allChangesLost'); - } -}; - -/** - * Opens the current diagram via the window.opener if one exists. - */ -EditorUi.prototype.open = function() -{ - // Cross-domain window access is not allowed in FF, so if we - // were opened from another domain then this will fail. - try - { - if (window.opener != null && window.opener.openFile != null) - { - window.opener.openFile.setConsumer(mxUtils.bind(this, function(xml, filename) - { - try - { - var doc = mxUtils.parseXml(xml); - this.editor.setGraphXml(doc.documentElement); - this.editor.setModified(false); - this.editor.undoManager.clear(); - - if (filename != null) - { - this.editor.setFilename(filename); - this.updateDocumentTitle(); - } - - return; - } - catch (e) - { - mxUtils.alert(mxResources.get('invalidOrMissingFile') + ': ' + e.message); - } - })); - } - } - catch(e) - { - // ignore - } - - // Fires as the last step if no file was loaded - this.editor.graph.view.validate(); - - // Required only in special cases where an initial file is opened - // and the minimumGraphSize changes and CSS must be updated. - this.editor.graph.sizeDidChange(); - this.editor.fireEvent(new mxEventObject('resetGraphView')); -}; - -/** - * Shows the given popup menu. - */ -EditorUi.prototype.showPopupMenu = function(fn, x, y, evt) -{ - this.editor.graph.popupMenuHandler.hideMenu(); - - var menu = new mxPopupMenu(fn); - menu.div.className += ' geMenubarMenu'; - menu.smartSeparators = true; - menu.showDisabled = true; - menu.autoExpand = true; - - // Disables autoexpand and destroys menu when hidden - menu.hideMenu = mxUtils.bind(this, function() - { - mxPopupMenu.prototype.hideMenu.apply(menu, arguments); - menu.destroy(); - }); - - menu.popup(x, y, null, evt); - - // Allows hiding by clicking on document - this.setCurrentMenu(menu); -}; - -/** - * Sets the current menu and element. - */ -EditorUi.prototype.setCurrentMenu = function(menu, elt) -{ - this.currentMenuElt = elt; - this.currentMenu = menu; -}; - -/** - * Resets the current menu and element. - */ -EditorUi.prototype.resetCurrentMenu = function() -{ - this.currentMenuElt = null; - this.currentMenu = null; -}; - -/** - * Hides and destroys the current menu. - */ -EditorUi.prototype.hideCurrentMenu = function() -{ - if (this.currentMenu != null) - { - this.currentMenu.hideMenu(); - this.resetCurrentMenu(); - } -}; - -/** - * Updates the document title. - */ -EditorUi.prototype.updateDocumentTitle = function() -{ - var title = this.editor.getOrCreateFilename(); - - if (this.editor.appName != null) - { - title += ' - ' + this.editor.appName; - } - - document.title = title; -}; - -/** - * Updates the document title. - */ -EditorUi.prototype.createHoverIcons = function() -{ - return new HoverIcons(this.editor.graph); -}; - -/** - * Returns the URL for a copy of this editor with no state. - */ -EditorUi.prototype.redo = function() -{ - try - { - var graph = this.editor.graph; - - if (graph.isEditing()) - { - document.execCommand('redo', false, null); - } - else - { - this.editor.undoManager.redo(); - } - } - catch (e) - { - // ignore all errors - } -}; - -/** - * Returns the URL for a copy of this editor with no state. - */ -EditorUi.prototype.undo = function() -{ - try - { - var graph = this.editor.graph; - - if (graph.isEditing()) - { - // Stops editing and executes undo on graph if native undo - // does not affect current editing value - var value = graph.cellEditor.textarea.innerHTML; - document.execCommand('undo', false, null); - - if (value == graph.cellEditor.textarea.innerHTML) - { - graph.stopEditing(true); - this.editor.undoManager.undo(); - } - } - else - { - this.editor.undoManager.undo(); - } - } - catch (e) - { - // ignore all errors - } -}; - -/** - * Returns the URL for a copy of this editor with no state. - */ -EditorUi.prototype.canRedo = function() -{ - return this.editor.graph.isEditing() || this.editor.undoManager.canRedo(); -}; - -/** - * Returns the URL for a copy of this editor with no state. - */ -EditorUi.prototype.canUndo = function() -{ - return this.editor.graph.isEditing() || this.editor.undoManager.canUndo(); -}; - -/** - * - */ -EditorUi.prototype.getEditBlankXml = function() -{ - return mxUtils.getXml(this.editor.getGraphXml()); -}; - -/** - * Returns the URL for a copy of this editor with no state. - */ -EditorUi.prototype.getUrl = function(pathname) -{ - var href = (pathname != null) ? pathname : window.location.pathname; - var parms = (href.indexOf('?') > 0) ? 1 : 0; - - // Removes template URL parameter for new blank diagram - for (var key in urlParams) - { - if (parms == 0) - { - href += '?'; - } - else - { - href += '&'; - } - - href += key + '=' + urlParams[key]; - parms++; - } - - return href; -}; - -/** - * Specifies if the graph has scrollbars. - */ -EditorUi.prototype.setScrollbars = function(value) -{ - var graph = this.editor.graph; - var prev = graph.container.style.overflow; - graph.scrollbars = value; - this.editor.updateGraphComponents(); - - if (prev != graph.container.style.overflow) - { - graph.container.scrollTop = 0; - graph.container.scrollLeft = 0; - graph.view.scaleAndTranslate(1, 0, 0); - this.resetScrollbars(); - } - - this.fireEvent(new mxEventObject('scrollbarsChanged')); -}; - -/** - * Returns true if the graph has scrollbars. - */ -EditorUi.prototype.hasScrollbars = function() -{ - return this.editor.graph.scrollbars; -}; - -/** - * Resets the state of the scrollbars. - */ -EditorUi.prototype.resetScrollbars = function() -{ - var graph = this.editor.graph; - - if (!this.editor.extendCanvas) - { - graph.container.scrollTop = 0; - graph.container.scrollLeft = 0; - - if (!mxUtils.hasScrollbars(graph.container)) - { - graph.view.setTranslate(0, 0); - } - } - else if (!this.editor.isChromelessView()) - { - if (mxUtils.hasScrollbars(graph.container)) - { - if (graph.pageVisible) - { - var pad = graph.getPagePadding(); - graph.container.scrollTop = Math.floor(pad.y - this.editor.initialTopSpacing) - 1; - graph.container.scrollLeft = Math.floor(Math.min(pad.x, - (graph.container.scrollWidth - graph.container.clientWidth) / 2)) - 1; - - // Scrolls graph to visible area - var bounds = graph.getGraphBounds(); - - if (bounds.width > 0 && bounds.height > 0) - { - if (bounds.x > graph.container.scrollLeft + graph.container.clientWidth * 0.9) - { - graph.container.scrollLeft = Math.min(bounds.x + bounds.width - graph.container.clientWidth, bounds.x - 10); - } - - if (bounds.y > graph.container.scrollTop + graph.container.clientHeight * 0.9) - { - graph.container.scrollTop = Math.min(bounds.y + bounds.height - graph.container.clientHeight, bounds.y - 10); - } - } - } - else - { - var bounds = graph.getGraphBounds(); - var width = Math.max(bounds.width, graph.scrollTileSize.width * graph.view.scale); - var height = Math.max(bounds.height, graph.scrollTileSize.height * graph.view.scale); - graph.container.scrollTop = Math.floor(Math.max(0, bounds.y - Math.max(20, (graph.container.clientHeight - height) / 4))); - graph.container.scrollLeft = Math.floor(Math.max(0, bounds.x - Math.max(0, (graph.container.clientWidth - width) / 2))); - } - } - else - { - var b = mxRectangle.fromRectangle((graph.pageVisible) ? graph.view.getBackgroundPageBounds() : graph.getGraphBounds()) - var tr = graph.view.translate; - var s = graph.view.scale; - b.x = b.x / s - tr.x; - b.y = b.y / s - tr.y; - b.width /= s; - b.height /= s; - - var dy = (graph.pageVisible) ? 0 : Math.max(0, (graph.container.clientHeight - b.height) / 4); - - graph.view.setTranslate(Math.floor(Math.max(0, - (graph.container.clientWidth - b.width) / 2) - b.x + 2), - Math.floor(dy - b.y + 1)); - } - } -}; - -/** - * Loads the stylesheet for this graph. - */ -EditorUi.prototype.setPageVisible = function(value) -{ - var graph = this.editor.graph; - var hasScrollbars = mxUtils.hasScrollbars(graph.container); - var tx = 0; - var ty = 0; - - if (hasScrollbars) - { - tx = graph.view.translate.x * graph.view.scale - graph.container.scrollLeft; - ty = graph.view.translate.y * graph.view.scale - graph.container.scrollTop; - } - - graph.pageVisible = value; - graph.pageBreaksVisible = value; - graph.preferPageSize = value; - graph.view.validateBackground(); - - // Workaround for possible handle offset - if (hasScrollbars) - { - var cells = graph.getSelectionCells(); - graph.clearSelection(); - graph.setSelectionCells(cells); - } - - // Calls updatePageBreaks - graph.sizeDidChange(); - - if (hasScrollbars) - { - graph.container.scrollLeft = graph.view.translate.x * graph.view.scale - tx; - graph.container.scrollTop = graph.view.translate.y * graph.view.scale - ty; - } - - this.fireEvent(new mxEventObject('pageViewChanged')); -}; - -/** - * Class: ChangeGridColor - * - * Undoable change to grid color. - */ -function ChangeGridColor(ui, color) -{ - this.ui = ui; - this.color = color; -}; - -/** - * Executes selection of a new page. - */ -ChangeGridColor.prototype.execute = function() -{ - var temp = this.ui.editor.graph.view.gridColor; - this.ui.setGridColor(this.color); - this.color = temp; -}; - -// Registers codec for ChangePageSetup -(function() -{ - var codec = new mxObjectCodec(new ChangeGridColor(), ['ui']); - - mxCodecRegistry.register(codec); -})(); - -/** - * Change types - */ -function ChangePageSetup(ui, color, image, format, pageScale) -{ - this.ui = ui; - this.color = color; - this.previousColor = color; - this.image = image; - this.previousImage = image; - this.format = format; - this.previousFormat = format; - this.pageScale = pageScale; - this.previousPageScale = pageScale; - - // Needed since null are valid values for color and image - this.ignoreColor = false; - this.ignoreImage = false; -} - -/** - * Implementation of the undoable page rename. - */ -ChangePageSetup.prototype.execute = function() -{ - var graph = this.ui.editor.graph; - - if (!this.ignoreColor) - { - this.color = this.previousColor; - var tmp = graph.background; - this.ui.setBackgroundColor(this.previousColor); - this.previousColor = tmp; - } - - if (!this.ignoreImage) - { - this.image = this.previousImage; - var tmp = graph.backgroundImage; - this.ui.setBackgroundImage(this.previousImage); - this.previousImage = tmp; - } - - if (this.previousFormat != null) - { - this.format = this.previousFormat; - var tmp = graph.pageFormat; - - if (this.previousFormat.width != tmp.width || - this.previousFormat.height != tmp.height) - { - this.ui.setPageFormat(this.previousFormat); - this.previousFormat = tmp; - } - } - - if (this.foldingEnabled != null && this.foldingEnabled != this.ui.editor.graph.foldingEnabled) - { - this.ui.setFoldingEnabled(this.foldingEnabled); - this.foldingEnabled = !this.foldingEnabled; - } - - if (this.previousPageScale != null) - { - var currentPageScale = this.ui.editor.graph.pageScale; - - if (this.previousPageScale != currentPageScale) - { - this.ui.setPageScale(this.previousPageScale); - this.previousPageScale = currentPageScale; - } - } -}; - -// Registers codec for ChangePageSetup -(function() -{ - var codec = new mxObjectCodec(new ChangePageSetup(), ['ui', 'previousColor', 'previousImage', 'previousFormat', 'previousPageScale']); - - codec.afterDecode = function(dec, node, obj) - { - obj.previousColor = obj.color; - obj.previousImage = obj.image; - obj.previousFormat = obj.format; - obj.previousPageScale = obj.pageScale; - - if (obj.foldingEnabled != null) - { - obj.foldingEnabled = !obj.foldingEnabled; - } - - return obj; - }; - - mxCodecRegistry.register(codec); -})(); - -/** - * Loads the stylesheet for this graph. - */ -EditorUi.prototype.setBackgroundColor = function(value) -{ - this.editor.graph.background = value; - this.editor.graph.view.validateBackground(); - - this.fireEvent(new mxEventObject('backgroundColorChanged')); -}; - -/** - * Loads the stylesheet for this graph. - */ -EditorUi.prototype.setFoldingEnabled = function(value) -{ - this.editor.graph.foldingEnabled = value; - this.editor.graph.view.revalidate(); - - this.fireEvent(new mxEventObject('foldingEnabledChanged')); -}; - -/** - * Loads the stylesheet for this graph. - */ -EditorUi.prototype.setPageFormat = function(value) -{ - this.editor.graph.pageFormat = value; - - if (!this.editor.graph.pageVisible) - { - this.actions.get('pageView').funct(); - } - else - { - this.editor.graph.view.validateBackground(); - this.editor.graph.sizeDidChange(); - } - - this.fireEvent(new mxEventObject('pageFormatChanged')); -}; - -/** - * Loads the stylesheet for this graph. - */ -EditorUi.prototype.setPageScale = function(value) -{ - this.editor.graph.pageScale = value; - - if (!this.editor.graph.pageVisible) - { - this.actions.get('pageView').funct(); - } - else - { - this.editor.graph.view.validateBackground(); - this.editor.graph.sizeDidChange(); - } - - this.fireEvent(new mxEventObject('pageScaleChanged')); -}; - -/** - * Loads the stylesheet for this graph. - */ -EditorUi.prototype.setGridColor = function(value) -{ - this.editor.graph.view.gridColor = value; - this.editor.graph.view.validateBackground(); - this.fireEvent(new mxEventObject('gridColorChanged')); -}; - -/** - * Updates the states of the given undo/redo items. - */ -EditorUi.prototype.addUndoListener = function() -{ - var undo = this.actions.get('undo'); - var redo = this.actions.get('redo'); - - var undoMgr = this.editor.undoManager; - - var undoListener = mxUtils.bind(this, function() - { - undo.setEnabled(this.canUndo()); - redo.setEnabled(this.canRedo()); - }); - - undoMgr.addListener(mxEvent.ADD, undoListener); - undoMgr.addListener(mxEvent.UNDO, undoListener); - undoMgr.addListener(mxEvent.REDO, undoListener); - undoMgr.addListener(mxEvent.CLEAR, undoListener); - - // Overrides cell editor to update action states - var cellEditorStartEditing = this.editor.graph.cellEditor.startEditing; - - this.editor.graph.cellEditor.startEditing = function() - { - cellEditorStartEditing.apply(this, arguments); - undoListener(); - }; - - var cellEditorStopEditing = this.editor.graph.cellEditor.stopEditing; - - this.editor.graph.cellEditor.stopEditing = function(cell, trigger) - { - cellEditorStopEditing.apply(this, arguments); - undoListener(); - }; - - // Updates the button states once - undoListener(); -}; - -/** -* Updates the states of the given toolbar items based on the selection. -*/ -EditorUi.prototype.updateActionStates = function() -{ - var graph = this.editor.graph; - var selected = !graph.isSelectionEmpty(); - var vertexSelected = false; - var groupSelected = false; - var edgeSelected = false; - - var cells = graph.getSelectionCells(); - - if (cells != null) - { - for (var i = 0; i < cells.length; i++) - { - var cell = cells[i]; - - if (graph.getModel().isEdge(cell)) - { - edgeSelected = true; - } - - if (graph.getModel().isVertex(cell)) - { - vertexSelected = true; - - if (graph.getModel().getChildCount(cell) > 0 || - graph.isContainer(cell)) - { - groupSelected = true; - } - } - - if (edgeSelected && vertexSelected) - { - break; - } - } - } - - // Updates action states - var actions = ['cut', 'copy', 'bold', 'italic', 'underline', 'delete', 'duplicate', - 'editStyle', 'editTooltip', 'editLink', 'backgroundColor', 'borderColor', - 'edit', 'toFront', 'toBack', 'lockUnlock', 'solid', 'dashed', 'pasteSize', - 'dotted', 'fillColor', 'gradientColor', 'shadow', 'fontColor', - 'formattedText', 'rounded', 'toggleRounded', 'sharp', 'strokeColor']; - - for (var i = 0; i < actions.length; i++) - { - this.actions.get(actions[i]).setEnabled(selected); - } - - this.actions.get('setAsDefaultStyle').setEnabled(graph.getSelectionCount() == 1); - this.actions.get('clearWaypoints').setEnabled(!graph.isSelectionEmpty()); - this.actions.get('copySize').setEnabled(graph.getSelectionCount() == 1); - this.actions.get('turn').setEnabled(!graph.isSelectionEmpty()); - this.actions.get('curved').setEnabled(edgeSelected); - this.actions.get('rotation').setEnabled(vertexSelected); - this.actions.get('wordWrap').setEnabled(vertexSelected); - this.actions.get('autosize').setEnabled(vertexSelected); - var oneVertexSelected = vertexSelected && graph.getSelectionCount() == 1; - this.actions.get('group').setEnabled(graph.getSelectionCount() > 1 || - (oneVertexSelected && !graph.isContainer(graph.getSelectionCell()))); - this.actions.get('ungroup').setEnabled(groupSelected); - this.actions.get('removeFromGroup').setEnabled(oneVertexSelected && - graph.getModel().isVertex(graph.getModel().getParent(graph.getSelectionCell()))); - - // Updates menu states - var state = graph.view.getState(graph.getSelectionCell()); - this.menus.get('navigation').setEnabled(selected || graph.view.currentRoot != null); - this.actions.get('collapsible').setEnabled(vertexSelected && - (graph.isContainer(graph.getSelectionCell()) || graph.model.getChildCount(graph.getSelectionCell()) > 0)); - this.actions.get('home').setEnabled(graph.view.currentRoot != null); - this.actions.get('exitGroup').setEnabled(graph.view.currentRoot != null); - this.actions.get('enterGroup').setEnabled(graph.getSelectionCount() == 1 && graph.isValidRoot(graph.getSelectionCell())); - var foldable = graph.getSelectionCount() == 1 && graph.isCellFoldable(graph.getSelectionCell()); - this.actions.get('expand').setEnabled(foldable); - this.actions.get('collapse').setEnabled(foldable); - this.actions.get('editLink').setEnabled(graph.getSelectionCount() == 1); - this.actions.get('openLink').setEnabled(graph.getSelectionCount() == 1 && - graph.getLinkForCell(graph.getSelectionCell()) != null); - this.actions.get('guides').setEnabled(graph.isEnabled()); - this.actions.get('grid').setEnabled(!this.editor.chromeless || this.editor.editable); - - var unlocked = graph.isEnabled() && !graph.isCellLocked(graph.getDefaultParent()); - this.menus.get('layout').setEnabled(unlocked); - this.menus.get('insert').setEnabled(unlocked); - this.menus.get('direction').setEnabled(unlocked && vertexSelected); - this.menus.get('align').setEnabled(unlocked && vertexSelected && graph.getSelectionCount() > 1); - this.menus.get('distribute').setEnabled(unlocked && vertexSelected && graph.getSelectionCount() > 1); - this.actions.get('selectVertices').setEnabled(unlocked); - this.actions.get('selectEdges').setEnabled(unlocked); - this.actions.get('selectAll').setEnabled(unlocked); - this.actions.get('selectNone').setEnabled(unlocked); - - this.updatePasteActionStates(); -}; - -EditorUi.prototype.zeroOffset = new mxPoint(0, 0); - -EditorUi.prototype.getDiagramContainerOffset = function() -{ - return this.zeroOffset; -}; - -/** - * Refreshes the viewport. - */ -EditorUi.prototype.refresh = function(sizeDidChange) -{ - sizeDidChange = (sizeDidChange != null) ? sizeDidChange : true; - - var quirks = mxClient.IS_IE && (document.documentMode == null || document.documentMode == 5); - var w = this.container.clientWidth; - var h = this.container.clientHeight; - - if (this.container == document.body) - { - w = document.body.clientWidth || document.documentElement.clientWidth; - h = (quirks) ? document.body.clientHeight || document.documentElement.clientHeight : document.documentElement.clientHeight; - } - - // Workaround for bug on iOS see - // http://stackoverflow.com/questions/19012135/ios-7-ipad-safari-landscape-innerheight-outerheight-layout-issue - // FIXME: Fix if footer visible - var off = 0; - - if (mxClient.IS_IOS && !window.navigator.standalone) - { - if (window.innerHeight != document.documentElement.clientHeight) - { - off = document.documentElement.clientHeight - window.innerHeight; - window.scrollTo(0, 0); - } - } - - var effHsplitPosition = Math.max(0, Math.min(this.hsplitPosition, w - this.splitSize - 20)); - var tmp = 0; - - if (this.menubar != null) - { - this.menubarContainer.style.height = this.menubarHeight + 'px'; - tmp += this.menubarHeight; - } - - if (this.toolbar != null) - { - this.toolbarContainer.style.top = this.menubarHeight + 'px'; - this.toolbarContainer.style.height = this.toolbarHeight + 'px'; - tmp += this.toolbarHeight; - } - - if (tmp > 0 && !mxClient.IS_QUIRKS) - { - tmp += 1; - } - - var sidebarFooterHeight = 0; - - if (this.sidebarFooterContainer != null) - { - var bottom = this.footerHeight + off; - sidebarFooterHeight = Math.max(0, Math.min(h - tmp - bottom, this.sidebarFooterHeight)); - this.sidebarFooterContainer.style.width = effHsplitPosition + 'px'; - this.sidebarFooterContainer.style.height = sidebarFooterHeight + 'px'; - this.sidebarFooterContainer.style.bottom = bottom + 'px'; - } - - var fw = (this.format != null) ? this.formatWidth : 0; - this.sidebarContainer.style.top = tmp + 'px'; - this.sidebarContainer.style.width = effHsplitPosition + 'px'; - this.formatContainer.style.top = tmp + 'px'; - this.formatContainer.style.width = fw + 'px'; - this.formatContainer.style.display = (this.format != null) ? '' : 'none'; - - var diagContOffset = this.getDiagramContainerOffset(); - var contLeft = (this.hsplit.parentNode != null) ? (effHsplitPosition + this.splitSize) : 0; - this.diagramContainer.style.left = (contLeft + diagContOffset.x) + 'px'; - this.diagramContainer.style.top = (tmp + diagContOffset.y) + 'px'; - this.footerContainer.style.height = this.footerHeight + 'px'; - this.hsplit.style.top = this.sidebarContainer.style.top; - this.hsplit.style.bottom = (this.footerHeight + off) + 'px'; - this.hsplit.style.left = effHsplitPosition + 'px'; - this.footerContainer.style.display = (this.footerHeight == 0) ? 'none' : ''; - - if (this.tabContainer != null) - { - this.tabContainer.style.left = contLeft + 'px'; - } - - if (quirks) - { - this.menubarContainer.style.width = w + 'px'; - this.toolbarContainer.style.width = this.menubarContainer.style.width; - var sidebarHeight = Math.max(0, h - this.footerHeight - this.menubarHeight - this.toolbarHeight); - this.sidebarContainer.style.height = (sidebarHeight - sidebarFooterHeight) + 'px'; - this.formatContainer.style.height = sidebarHeight + 'px'; - this.diagramContainer.style.width = (this.hsplit.parentNode != null) ? Math.max(0, w - effHsplitPosition - this.splitSize - fw) + 'px' : w + 'px'; - this.footerContainer.style.width = this.menubarContainer.style.width; - var diagramHeight = Math.max(0, h - this.footerHeight - this.menubarHeight - this.toolbarHeight); - - if (this.tabContainer != null) - { - this.tabContainer.style.width = this.diagramContainer.style.width; - this.tabContainer.style.bottom = (this.footerHeight + off) + 'px'; - diagramHeight -= this.tabContainer.clientHeight; - } - - this.diagramContainer.style.height = diagramHeight + 'px'; - this.hsplit.style.height = diagramHeight + 'px'; - } - else - { - if (this.footerHeight > 0) - { - this.footerContainer.style.bottom = off + 'px'; - } - - this.diagramContainer.style.right = fw + 'px'; - var th = 0; - - if (this.tabContainer != null) - { - this.tabContainer.style.bottom = (this.footerHeight + off) + 'px'; - this.tabContainer.style.right = this.diagramContainer.style.right; - th = this.tabContainer.clientHeight; - } - - this.sidebarContainer.style.bottom = (this.footerHeight + sidebarFooterHeight + off) + 'px'; - this.formatContainer.style.bottom = (this.footerHeight + off) + 'px'; - this.diagramContainer.style.bottom = (this.footerHeight + off + th) + 'px'; - } - - if (sizeDidChange) - { - this.editor.graph.sizeDidChange(); - } -}; - -/** - * Creates the required containers. - */ -EditorUi.prototype.createTabContainer = function() -{ - return null; -}; - -/** - * Creates the required containers. - */ -EditorUi.prototype.createDivs = function() -{ - this.menubarContainer = this.createDiv('geMenubarContainer'); - this.toolbarContainer = this.createDiv('geToolbarContainer'); - this.sidebarContainer = this.createDiv('geSidebarContainer'); - this.formatContainer = this.createDiv('geSidebarContainer geFormatContainer'); - this.diagramContainer = this.createDiv('geDiagramContainer'); - this.footerContainer = this.createDiv('geFooterContainer'); - this.hsplit = this.createDiv('geHsplit'); - this.hsplit.setAttribute('title', mxResources.get('collapseExpand')); - - // Sets static style for containers - this.menubarContainer.style.top = '0px'; - this.menubarContainer.style.left = '0px'; - this.menubarContainer.style.right = '0px'; - this.toolbarContainer.style.left = '0px'; - this.toolbarContainer.style.right = '0px'; - this.sidebarContainer.style.left = '0px'; - this.formatContainer.style.right = '0px'; - this.formatContainer.style.zIndex = '1'; - this.diagramContainer.style.right = ((this.format != null) ? this.formatWidth : 0) + 'px'; - this.footerContainer.style.left = '0px'; - this.footerContainer.style.right = '0px'; - this.footerContainer.style.bottom = '0px'; - this.footerContainer.style.zIndex = mxPopupMenu.prototype.zIndex - 2; - this.hsplit.style.width = this.splitSize + 'px'; - this.sidebarFooterContainer = this.createSidebarFooterContainer(); - - if (this.sidebarFooterContainer) - { - this.sidebarFooterContainer.style.left = '0px'; - } - - if (!this.editor.chromeless) - { - this.tabContainer = this.createTabContainer(); - } - else - { - this.diagramContainer.style.border = 'none'; - } -}; - -/** - * Hook for sidebar footer container. This implementation returns null. - */ -EditorUi.prototype.createSidebarFooterContainer = function() -{ - return null; -}; - -/** - * Creates the required containers. - */ -EditorUi.prototype.createUi = function() -{ - // Creates menubar - this.menubar = (this.editor.chromeless) ? null : this.menus.createMenubar(this.createDiv('geMenubar')); - - if (this.menubar != null) - { - this.menubarContainer.appendChild(this.menubar.container); - } - - // Adds status bar in menubar - if (this.menubar != null) - { - this.statusContainer = this.createStatusContainer(); - - // Connects the status bar to the editor status - this.editor.addListener('statusChanged', mxUtils.bind(this, function() - { - this.setStatusText(this.editor.getStatus()); - })); - - this.setStatusText(this.editor.getStatus()); - this.menubar.container.appendChild(this.statusContainer); - - // Inserts into DOM - this.container.appendChild(this.menubarContainer); - } - - // Creates the sidebar - this.sidebar = (this.editor.chromeless) ? null : this.createSidebar(this.sidebarContainer); - - if (this.sidebar != null) - { - this.container.appendChild(this.sidebarContainer); - } - - // Creates the format sidebar - this.format = (this.editor.chromeless || !this.formatEnabled) ? null : this.createFormat(this.formatContainer); - - if (this.format != null) - { - this.container.appendChild(this.formatContainer); - } - - // Creates the footer - var footer = (this.editor.chromeless) ? null : this.createFooter(); - - if (footer != null) - { - this.footerContainer.appendChild(footer); - this.container.appendChild(this.footerContainer); - } - - if (this.sidebar != null && this.sidebarFooterContainer) - { - this.container.appendChild(this.sidebarFooterContainer); - } - - this.container.appendChild(this.diagramContainer); - - if (this.container != null && this.tabContainer != null) - { - this.container.appendChild(this.tabContainer); - } - - // Creates toolbar - this.toolbar = (this.editor.chromeless) ? null : this.createToolbar(this.createDiv('geToolbar')); - - if (this.toolbar != null) - { - this.toolbarContainer.appendChild(this.toolbar.container); - this.container.appendChild(this.toolbarContainer); - } - - // HSplit - if (this.sidebar != null) - { - this.container.appendChild(this.hsplit); - - this.addSplitHandler(this.hsplit, true, 0, mxUtils.bind(this, function(value) - { - this.hsplitPosition = value; - this.refresh(); - })); - } -}; - -/** - * Creates a new toolbar for the given container. - */ -EditorUi.prototype.createStatusContainer = function() -{ - var container = document.createElement('a'); - container.className = 'geItem geStatus'; - - return container; -}; - -/** - * Creates a new toolbar for the given container. - */ -EditorUi.prototype.setStatusText = function(value) -{ - this.statusContainer.innerHTML = value; -}; - -/** - * Creates a new toolbar for the given container. - */ -EditorUi.prototype.createToolbar = function(container) -{ - return new Toolbar(this, container); -}; - -/** - * Creates a new sidebar for the given container. - */ -EditorUi.prototype.createSidebar = function(container) -{ - return new Sidebar(this, container); -}; - -/** - * Creates a new sidebar for the given container. - */ -EditorUi.prototype.createFormat = function(container) -{ - return new Format(this, container); -}; - -/** - * Creates and returns a new footer. - */ -EditorUi.prototype.createFooter = function() -{ - return this.createDiv('geFooter'); -}; - -/** - * Creates the actual toolbar for the toolbar container. - */ -EditorUi.prototype.createDiv = function(classname) -{ - var elt = document.createElement('div'); - elt.className = classname; - - return elt; -}; - -/** - * Updates the states of the given undo/redo items. - */ -EditorUi.prototype.addSplitHandler = function(elt, horizontal, dx, onChange) -{ - var start = null; - var initial = null; - var ignoreClick = true; - var last = null; - - // Disables built-in pan and zoom in IE10 and later - if (mxClient.IS_POINTER) - { - elt.style.touchAction = 'none'; - } - - var getValue = mxUtils.bind(this, function() - { - var result = parseInt(((horizontal) ? elt.style.left : elt.style.bottom)); - - // Takes into account hidden footer - if (!horizontal) - { - result = result + dx - this.footerHeight; - } - - return result; - }); - - function moveHandler(evt) - { - if (start != null) - { - var pt = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - onChange(Math.max(0, initial + ((horizontal) ? (pt.x - start.x) : (start.y - pt.y)) - dx)); - mxEvent.consume(evt); - - if (initial != getValue()) - { - ignoreClick = true; - last = null; - } - } - }; - - function dropHandler(evt) - { - moveHandler(evt); - initial = null; - start = null; - }; - - mxEvent.addGestureListeners(elt, function(evt) - { - start = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - initial = getValue(); - ignoreClick = false; - mxEvent.consume(evt); - }); - - mxEvent.addListener(elt, 'click', mxUtils.bind(this, function(evt) - { - if (!ignoreClick && this.hsplitClickEnabled) - { - var next = (last != null) ? last - dx : 0; - last = getValue(); - onChange(next); - mxEvent.consume(evt); - } - })); - - mxEvent.addGestureListeners(document, null, moveHandler, dropHandler); - - this.destroyFunctions.push(function() - { - mxEvent.removeGestureListeners(document, null, moveHandler, dropHandler); - }); -}; - -/** - * Translates this point by the given vector. - * - * @param {number} dx X-coordinate of the translation. - * @param {number} dy Y-coordinate of the translation. - */ -EditorUi.prototype.handleError = function(resp, title, fn, invokeFnOnClose, notFoundMessage) -{ - var e = (resp != null && resp.error != null) ? resp.error : resp; - - if (e != null || title != null) - { - var msg = mxUtils.htmlEntities(mxResources.get('unknownError')); - var btn = mxResources.get('ok'); - title = (title != null) ? title : mxResources.get('error'); - - if (e != null && e.message != null) - { - msg = mxUtils.htmlEntities(e.message); - } - - this.showError(title, msg, btn, fn, null, null, null, null, null, - null, null, null, (invokeFnOnClose) ? fn : null); - } - else if (fn != null) - { - fn(); - } -}; - -/** - * Translates this point by the given vector. - * - * @param {number} dx X-coordinate of the translation. - * @param {number} dy Y-coordinate of the translation. - */ -EditorUi.prototype.showError = function(title, msg, btn, fn, retry, btn2, fn2, btn3, fn3, w, h, hide, onClose) -{ - var dlg = new ErrorDialog(this, title, msg, btn || mxResources.get('ok'), - fn, retry, btn2, fn2, hide, btn3, fn3); - var lines = Math.ceil((msg != null) ? msg.length / 50 : 1); - this.showDialog(dlg.container, w || 340, h || (100 + lines * 20), true, false, onClose); - dlg.init(); -}; - -/** - * Displays a print dialog. - */ -EditorUi.prototype.showDialog = function(elt, w, h, modal, closable, onClose, noScroll, transparent, onResize, ignoreBgClick) -{ - this.editor.graph.tooltipHandler.resetTimer(); - this.editor.graph.tooltipHandler.hideTooltip(); - - if (this.dialogs == null) - { - this.dialogs = []; - } - - this.dialog = new Dialog(this, elt, w, h, modal, closable, onClose, noScroll, transparent, onResize, ignoreBgClick); - this.dialogs.push(this.dialog); -}; - -/** - * Displays a print dialog. - */ -EditorUi.prototype.hideDialog = function(cancel, isEsc, matchContainer) -{ - if (this.dialogs != null && this.dialogs.length > 0) - { - if (matchContainer != null && matchContainer != this.dialog.container.firstChild) - { - return; - } - - var dlg = this.dialogs.pop(); - - if (dlg.close(cancel, isEsc) == false) - { - //add the dialog back if dialog closing is cancelled - this.dialogs.push(dlg); - return; - } - - this.dialog = (this.dialogs.length > 0) ? this.dialogs[this.dialogs.length - 1] : null; - this.editor.fireEvent(new mxEventObject('hideDialog')); - - if (this.dialog == null && this.editor.graph.container.style.visibility != 'hidden') - { - window.setTimeout(mxUtils.bind(this, function() - { - if (this.editor.graph.isEditing() && this.editor.graph.cellEditor.textarea != null) - { - this.editor.graph.cellEditor.textarea.focus(); - } - else - { - mxUtils.clearSelection(); - this.editor.graph.container.focus(); - } - }), 0); - } - } -}; - -/** - * Handles ctrl+enter keystroke to clone cells. - */ -EditorUi.prototype.ctrlEnter = function() -{ - var graph = this.editor.graph; - - if (graph.isEnabled()) - { - try - { - var cells = graph.getSelectionCells(); - var lookup = new mxDictionary(); - var newCells = []; - - for (var i = 0; i < cells.length; i++) - { - // Clones table rows instead of cells - var cell = (graph.isTableCell(cells[i])) ? graph.model.getParent(cells[i]) : cells[i]; - - if (cell != null && !lookup.get(cell)) - { - lookup.put(cell, true); - newCells.push(cell); - } - } - - graph.setSelectionCells(graph.duplicateCells(newCells, false)); - } - catch (e) - { - this.handleError(e); - } - } -}; - -/** - * Display a color dialog. - */ -EditorUi.prototype.pickColor = function(color, apply) -{ - var graph = this.editor.graph; - var selState = graph.cellEditor.saveSelection(); - var h = 226 + ((Math.ceil(ColorDialog.prototype.presetColors.length / 12) + - Math.ceil(ColorDialog.prototype.defaultColors.length / 12)) * 17); - - var dlg = new ColorDialog(this, color || 'none', function(color) - { - graph.cellEditor.restoreSelection(selState); - apply(color); - }, function() - { - graph.cellEditor.restoreSelection(selState); - }); - this.showDialog(dlg.container, 230, h, true, false); - dlg.init(); -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -EditorUi.prototype.openFile = function() -{ - // Closes dialog after open - window.openFile = new OpenFile(mxUtils.bind(this, function(cancel) - { - this.hideDialog(cancel); - })); - - // Removes openFile if dialog is closed - this.showDialog(new OpenDialog(this).container, (Editor.useLocalStorage) ? 640 : 320, - (Editor.useLocalStorage) ? 480 : 220, true, true, function() - { - window.openFile = null; - }); -}; - -/** - * Extracs the graph model from the given HTML data from a data transfer event. - */ -EditorUi.prototype.extractGraphModelFromHtml = function(data) -{ - var result = null; - - try - { - var idx = data.indexOf('<mxGraphModel '); - - if (idx >= 0) - { - var idx2 = data.lastIndexOf('</mxGraphModel>'); - - if (idx2 > idx) - { - result = data.substring(idx, idx2 + 21).replace(/>/g, '>'). - replace(/</g, '<').replace(/\\"/g, '"').replace(/\n/g, ''); - } - } - } - catch (e) - { - // ignore - } - - return result; -}; - -/** - * Opens the given files in the editor. - */ -EditorUi.prototype.extractGraphModelFromEvent = function(evt) -{ - var result = null; - var data = null; - - if (evt != null) - { - var provider = (evt.dataTransfer != null) ? evt.dataTransfer : evt.clipboardData; - - if (provider != null) - { - if (document.documentMode == 10 || document.documentMode == 11) - { - data = provider.getData('Text'); - } - else - { - data = (mxUtils.indexOf(provider.types, 'text/html') >= 0) ? provider.getData('text/html') : null; - - if (mxUtils.indexOf(provider.types, 'text/plain' && (data == null || data.length == 0))) - { - data = provider.getData('text/plain'); - } - } - - if (data != null) - { - data = Graph.zapGremlins(mxUtils.trim(data)); - - // Tries parsing as HTML document with embedded XML - var xml = this.extractGraphModelFromHtml(data); - - if (xml != null) - { - data = xml; - } - } - } - } - - if (data != null && this.isCompatibleString(data)) - { - result = data; - } - - return result; -}; - -/** - * Hook for subclassers to return true if event data is a supported format. - * This implementation always returns false. - */ -EditorUi.prototype.isCompatibleString = function(data) -{ - return false; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -EditorUi.prototype.saveFile = function(forceDialog) -{ - if (!forceDialog && this.editor.filename != null) - { - this.save(this.editor.getOrCreateFilename()); - } - else - { - var dlg = new FilenameDialog(this, this.editor.getOrCreateFilename(), mxResources.get('save'), mxUtils.bind(this, function(name) - { - this.save(name); - }), null, mxUtils.bind(this, function(name) - { - if (name != null && name.length > 0) - { - return true; - } - - mxUtils.confirm(mxResources.get('invalidName')); - - return false; - })); - this.showDialog(dlg.container, 300, 100, true, true); - dlg.init(); - } -}; - -/** - * Saves the current graph under the given filename. - */ -EditorUi.prototype.save = function(name) -{ - if (name != null) - { - if (this.editor.graph.isEditing()) - { - this.editor.graph.stopEditing(); - } - - var xml = mxUtils.getXml(this.editor.getGraphXml()); - - try - { - if (Editor.useLocalStorage) - { - if (localStorage.getItem(name) != null && - !mxUtils.confirm(mxResources.get('replaceIt', [name]))) - { - return; - } - - localStorage.setItem(name, xml); - this.editor.setStatus(mxUtils.htmlEntities(mxResources.get('saved')) + ' ' + new Date()); - } - else - { - if (xml.length < MAX_REQUEST_SIZE) - { - new mxXmlRequest(SAVE_URL, 'filename=' + encodeURIComponent(name) + - '&xml=' + encodeURIComponent(xml)).simulate(document, '_blank'); - } - else - { - mxUtils.alert(mxResources.get('drawingTooLarge')); - mxUtils.popup(xml); - - return; - } - } - - this.editor.setModified(false); - this.editor.setFilename(name); - this.updateDocumentTitle(); - } - catch (e) - { - this.editor.setStatus(mxUtils.htmlEntities(mxResources.get('errorSavingFile'))); - } - } -}; - -/** - * Executes the given layout. - */ -EditorUi.prototype.executeLayout = function(exec, animate, post) -{ - var graph = this.editor.graph; - - if (graph.isEnabled()) - { - graph.getModel().beginUpdate(); - try - { - exec(); - } - catch (e) - { - throw e; - } - finally - { - // Animates the changes in the graph model except - // for Camino, where animation is too slow - if (this.allowAnimation && animate && (navigator.userAgent == null || - navigator.userAgent.indexOf('Camino') < 0)) - { - // New API for animating graph layout results asynchronously - var morph = new mxMorphing(graph); - morph.addListener(mxEvent.DONE, mxUtils.bind(this, function() - { - graph.getModel().endUpdate(); - - if (post != null) - { - post(); - } - })); - - morph.startAnimation(); - } - else - { - graph.getModel().endUpdate(); - - if (post != null) - { - post(); - } - } - } - } -}; - -/** - * Hides the current menu. - */ -EditorUi.prototype.showImageDialog = function(title, value, fn, ignoreExisting) -{ - var cellEditor = this.editor.graph.cellEditor; - var selState = cellEditor.saveSelection(); - var newValue = mxUtils.prompt(title, value); - cellEditor.restoreSelection(selState); - - if (newValue != null && newValue.length > 0) - { - var img = new Image(); - - img.onload = function() - { - fn(newValue, img.width, img.height); - }; - img.onerror = function() - { - fn(null); - mxUtils.alert(mxResources.get('fileNotFound')); - }; - - img.src = newValue; - } - else - { - fn(null); - } -}; - -/** - * Hides the current menu. - */ -EditorUi.prototype.showLinkDialog = function(value, btnLabel, fn) -{ - var dlg = new LinkDialog(this, value, btnLabel, fn); - this.showDialog(dlg.container, 420, 90, true, true); - dlg.init(); -}; - -/** - * Hides the current menu. - */ -EditorUi.prototype.showDataDialog = function(cell) -{ - if (cell != null) - { - var dlg = new EditDataDialog(this, cell); - this.showDialog(dlg.container, 480, 420, true, false, null, false); - dlg.init(); - } -}; - -/** - * Hides the current menu. - */ -EditorUi.prototype.showBackgroundImageDialog = function(apply, img) -{ - apply = (apply != null) ? apply : mxUtils.bind(this, function(image) - { - var change = new ChangePageSetup(this, null, image); - change.ignoreColor = true; - - this.editor.graph.model.execute(change); - }); - - var newValue = mxUtils.prompt(mxResources.get('backgroundImage'), (img != null) ? img.src : ''); - - if (newValue != null && newValue.length > 0) - { - var img = new Image(); - - img.onload = function() - { - apply(new mxImage(newValue, img.width, img.height), false); - }; - img.onerror = function() - { - apply(null, true); - mxUtils.alert(mxResources.get('fileNotFound')); - }; - - img.src = newValue; - } - else - { - apply(null); - } -}; - -/** - * Loads the stylesheet for this graph. - */ -EditorUi.prototype.setBackgroundImage = function(image) -{ - this.editor.graph.setBackgroundImage(image); - this.editor.graph.view.validateBackgroundImage(); - - this.fireEvent(new mxEventObject('backgroundImageChanged')); -}; - -/** - * Creates the keyboard event handler for the current graph and history. - */ -EditorUi.prototype.confirm = function(msg, okFn, cancelFn) -{ - if (mxUtils.confirm(msg)) - { - if (okFn != null) - { - okFn(); - } - } - else if (cancelFn != null) - { - cancelFn(); - } -}; - -/** - * Creates the keyboard event handler for the current graph and history. - */ -EditorUi.prototype.createOutline = function(wnd) -{ - var outline = new mxOutline(this.editor.graph); - outline.border = 20; - - mxEvent.addListener(window, 'resize', function() - { - outline.update(); - }); - - this.addListener('pageFormatChanged', function() - { - outline.update(); - }); - - return outline; -}; - -// Alt+Shift+Keycode mapping to action -EditorUi.prototype.altShiftActions = {67: 'clearWaypoints', // Alt+Shift+C - 65: 'connectionArrows', // Alt+Shift+A - 76: 'editLink', // Alt+Shift+L - 80: 'connectionPoints', // Alt+Shift+P - 84: 'editTooltip', // Alt+Shift+T - 86: 'pasteSize', // Alt+Shift+V - 88: 'copySize' // Alt+Shift+X -}; - -/** - * Creates the keyboard event handler for the current graph and history. - */ -EditorUi.prototype.createKeyHandler = function(editor) -{ - var editorUi = this; - var graph = this.editor.graph; - var keyHandler = new mxKeyHandler(graph); - - var isEventIgnored = keyHandler.isEventIgnored; - keyHandler.isEventIgnored = function(evt) - { - // Handles undo/redo/ctrl+./,/u via action and allows ctrl+b/i - // only if editing value is HTML (except for FF and Safari) - return !(mxEvent.isShiftDown(evt) && evt.keyCode == 9) && - ((!this.isControlDown(evt) || mxEvent.isShiftDown(evt) || - (evt.keyCode != 90 && evt.keyCode != 89 && evt.keyCode != 188 && - evt.keyCode != 190 && evt.keyCode != 85)) && ((evt.keyCode != 66 && evt.keyCode != 73) || - !this.isControlDown(evt) || (this.graph.cellEditor.isContentEditing() && - !mxClient.IS_FF && !mxClient.IS_SF)) && isEventIgnored.apply(this, arguments)); - }; - - // Ignores graph enabled state but not chromeless state - keyHandler.isEnabledForEvent = function(evt) - { - return (!mxEvent.isConsumed(evt) && this.isGraphEvent(evt) && this.isEnabled() && - (editorUi.dialogs == null || editorUi.dialogs.length == 0)); - }; - - // Routes command-key to control-key on Mac - keyHandler.isControlDown = function(evt) - { - return mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey); - }; - - var queue = []; - var thread = null; - - // Helper function to move cells with the cursor keys - function nudge(keyCode, stepSize, resize) - { - queue.push(function() - { - if (!graph.isSelectionEmpty() && graph.isEnabled()) - { - stepSize = (stepSize != null) ? stepSize : 1; - - if (resize) - { - // Resizes all selected vertices - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - - for (var i = 0; i < cells.length; i++) - { - if (graph.getModel().isVertex(cells[i]) && graph.isCellResizable(cells[i])) - { - var geo = graph.getCellGeometry(cells[i]); - - if (geo != null) - { - geo = geo.clone(); - - if (keyCode == 37) - { - geo.width = Math.max(0, geo.width - stepSize); - } - else if (keyCode == 38) - { - geo.height = Math.max(0, geo.height - stepSize); - } - else if (keyCode == 39) - { - geo.width += stepSize; - } - else if (keyCode == 40) - { - geo.height += stepSize; - } - - graph.getModel().setGeometry(cells[i], geo); - } - } - } - } - finally - { - graph.getModel().endUpdate(); - } - } - else - { - // Moves vertices up/down in a stack layout - var cell = graph.getSelectionCell(); - var parent = graph.model.getParent(cell); - var layout = null; - - if (graph.getSelectionCount() == 1 && graph.model.isVertex(cell) && - graph.layoutManager != null && !graph.isCellLocked(cell)) - { - layout = graph.layoutManager.getLayout(parent); - } - - if (layout != null && layout.constructor == mxStackLayout) - { - var index = parent.getIndex(cell); - - if (keyCode == 37 || keyCode == 38) - { - graph.model.add(parent, cell, Math.max(0, index - 1)); - } - else if (keyCode == 39 ||keyCode == 40) - { - graph.model.add(parent, cell, Math.min(graph.model.getChildCount(parent), index + 1)); - } - } - else - { - var cells = graph.getMovableCells(graph.getSelectionCells()); - var realCells = []; - - for (var i = 0; i < cells.length; i++) - { - // TODO: Use getCompositeParent - var style = graph.getCurrentCellStyle(cells[i]); - - if (mxUtils.getValue(style, 'part', '0') == '1') - { - var parent = graph.model.getParent(cells[i]); - - if (graph.model.isVertex(parent) && mxUtils.indexOf(cells, parent) < 0) - { - realCells.push(parent); - } - } - else - { - realCells.push(cells[i]); - } - } - - if (realCells.length > 0) - { - cells = realCells; - var dx = 0; - var dy = 0; - - if (keyCode == 37) - { - dx = -stepSize; - } - else if (keyCode == 38) - { - dy = -stepSize; - } - else if (keyCode == 39) - { - dx = stepSize; - } - else if (keyCode == 40) - { - dy = stepSize; - } - - graph.moveCells(cells, dx, dy); - } - } - } - } - }); - - if (thread != null) - { - window.clearTimeout(thread); - } - - thread = window.setTimeout(function() - { - if (queue.length > 0) - { - graph.getModel().beginUpdate(); - - try - { - for (var i = 0; i < queue.length; i++) - { - queue[i](); - } - - queue = []; - } - finally - { - graph.getModel().endUpdate(); - } - } - }, 200); - }; - - // Overridden to handle special alt+shift+cursor keyboard shortcuts - var directions = {37: mxConstants.DIRECTION_WEST, 38: mxConstants.DIRECTION_NORTH, - 39: mxConstants.DIRECTION_EAST, 40: mxConstants.DIRECTION_SOUTH}; - - var keyHandlerGetFunction = keyHandler.getFunction; - - mxKeyHandler.prototype.getFunction = function(evt) - { - if (graph.isEnabled()) - { - // TODO: Add alt modified state in core API, here are some specific cases - if (mxEvent.isShiftDown(evt) && mxEvent.isAltDown(evt)) - { - var action = editorUi.actions.get(editorUi.altShiftActions[evt.keyCode]); - - if (action != null) - { - return action.funct; - } - } - - if (evt.keyCode == 9 && mxEvent.isAltDown(evt)) - { - if (graph.cellEditor.isContentEditing()) - { - // Alt+Shift+Tab while editing - return function() - { - document.execCommand('outdent', false, null); - }; - } - else if (mxEvent.isShiftDown(evt)) - { - // Alt+Shift+Tab - return function() - { - graph.selectParentCell(); - }; - } - else - { - // Alt+Tab - return function() - { - graph.selectChildCell(); - }; - } - } - else if (directions[evt.keyCode] != null && !graph.isSelectionEmpty()) - { - // On macOS, Control+Cursor is used by Expose so allow for Alt+Control to resize - if (!this.isControlDown(evt) && mxEvent.isShiftDown(evt) && mxEvent.isAltDown(evt)) - { - if (graph.model.isVertex(graph.getSelectionCell())) - { - return function() - { - var cells = graph.connectVertex(graph.getSelectionCell(), directions[evt.keyCode], - graph.defaultEdgeLength, evt, true); - - if (cells != null && cells.length > 0) - { - if (cells.length == 1 && graph.model.isEdge(cells[0])) - { - graph.setSelectionCell(graph.model.getTerminal(cells[0], false)); - } - else - { - graph.setSelectionCell(cells[cells.length - 1]); - } - - graph.scrollCellToVisible(graph.getSelectionCell()); - - if (editorUi.hoverIcons != null) - { - editorUi.hoverIcons.update(graph.view.getState(graph.getSelectionCell())); - } - } - }; - } - } - else - { - // Avoids consuming event if no vertex is selected by returning null below - // Cursor keys move and resize (ctrl) cells - if (this.isControlDown(evt)) - { - return function() - { - nudge(evt.keyCode, (mxEvent.isShiftDown(evt)) ? graph.gridSize : null, true); - }; - } - else - { - return function() - { - nudge(evt.keyCode, (mxEvent.isShiftDown(evt)) ? graph.gridSize : null); - }; - } - } - } - } - - return keyHandlerGetFunction.apply(this, arguments); - }; - - // Binds keystrokes to actions - keyHandler.bindAction = mxUtils.bind(this, function(code, control, key, shift) - { - var action = this.actions.get(key); - - if (action != null) - { - var f = function() - { - if (action.isEnabled()) - { - action.funct(); - } - }; - - if (control) - { - if (shift) - { - keyHandler.bindControlShiftKey(code, f); - } - else - { - keyHandler.bindControlKey(code, f); - } - } - else - { - if (shift) - { - keyHandler.bindShiftKey(code, f); - } - else - { - keyHandler.bindKey(code, f); - } - } - } - }); - - var ui = this; - var keyHandlerEscape = keyHandler.escape; - keyHandler.escape = function(evt) - { - keyHandlerEscape.apply(this, arguments); - }; - - // Ignores enter keystroke. Remove this line if you want the - // enter keystroke to stop editing. N, W, T are reserved. - keyHandler.enter = function() {}; - - keyHandler.bindControlShiftKey(36, function() { graph.exitGroup(); }); // Ctrl+Shift+Home - keyHandler.bindControlShiftKey(35, function() { graph.enterGroup(); }); // Ctrl+Shift+End - keyHandler.bindShiftKey(36, function() { graph.home(); }); // Ctrl+Shift+Home - keyHandler.bindKey(35, function() { graph.refresh(); }); // End - keyHandler.bindAction(107, true, 'zoomIn'); // Ctrl+Plus - keyHandler.bindAction(109, true, 'zoomOut'); // Ctrl+Minus - keyHandler.bindAction(80, true, 'print'); // Ctrl+P - keyHandler.bindAction(79, true, 'outline', true); // Ctrl+Shift+O - - if (!this.editor.chromeless || this.editor.editable) - { - keyHandler.bindControlKey(36, function() { if (graph.isEnabled()) { graph.foldCells(true); }}); // Ctrl+Home - keyHandler.bindControlKey(35, function() { if (graph.isEnabled()) { graph.foldCells(false); }}); // Ctrl+End - keyHandler.bindControlKey(13, function() { ui.ctrlEnter(); }); // Ctrl+Enter - keyHandler.bindAction(8, false, 'delete'); // Backspace - keyHandler.bindAction(8, true, 'deleteAll'); // Ctrl+Backspace - keyHandler.bindAction(8, false, 'deleteLabels', true); // Shift+Backspace - keyHandler.bindAction(46, false, 'delete'); // Delete - keyHandler.bindAction(46, true, 'deleteAll'); // Ctrl+Delete - keyHandler.bindAction(46, false, 'deleteLabels', true); // Shift+Delete - keyHandler.bindAction(36, false, 'resetView'); // Home - keyHandler.bindAction(72, true, 'fitWindow', true); // Ctrl+Shift+H - keyHandler.bindAction(74, true, 'fitPage'); // Ctrl+J - keyHandler.bindAction(74, true, 'fitTwoPages', true); // Ctrl+Shift+J - keyHandler.bindAction(48, true, 'customZoom'); // Ctrl+0 - keyHandler.bindAction(82, true, 'turn'); // Ctrl+R - keyHandler.bindAction(82, true, 'clearDefaultStyle', true); // Ctrl+Shift+R - keyHandler.bindAction(83, true, 'save'); // Ctrl+S - keyHandler.bindAction(83, true, 'saveAs', true); // Ctrl+Shift+S - keyHandler.bindAction(65, true, 'selectAll'); // Ctrl+A - keyHandler.bindAction(65, true, 'selectNone', true); // Ctrl+A - keyHandler.bindAction(73, true, 'selectVertices', true); // Ctrl+Shift+I - keyHandler.bindAction(69, true, 'selectEdges', true); // Ctrl+Shift+E - keyHandler.bindAction(69, true, 'editStyle'); // Ctrl+E - keyHandler.bindAction(66, true, 'bold'); // Ctrl+B - keyHandler.bindAction(66, true, 'toBack', true); // Ctrl+Shift+B - keyHandler.bindAction(70, true, 'toFront', true); // Ctrl+Shift+F - keyHandler.bindAction(68, true, 'duplicate'); // Ctrl+D - keyHandler.bindAction(68, true, 'setAsDefaultStyle', true); // Ctrl+Shift+D - keyHandler.bindAction(90, true, 'undo'); // Ctrl+Z - keyHandler.bindAction(89, true, 'autosize', true); // Ctrl+Shift+Y - keyHandler.bindAction(88, true, 'cut'); // Ctrl+X - keyHandler.bindAction(67, true, 'copy'); // Ctrl+C - keyHandler.bindAction(86, true, 'paste'); // Ctrl+V - keyHandler.bindAction(71, true, 'group'); // Ctrl+G - keyHandler.bindAction(77, true, 'editData'); // Ctrl+M - keyHandler.bindAction(71, true, 'grid', true); // Ctrl+Shift+G - keyHandler.bindAction(73, true, 'italic'); // Ctrl+I - keyHandler.bindAction(76, true, 'lockUnlock'); // Ctrl+L - keyHandler.bindAction(76, true, 'layers', true); // Ctrl+Shift+L - keyHandler.bindAction(80, true, 'formatPanel', true); // Ctrl+Shift+P - keyHandler.bindAction(85, true, 'underline'); // Ctrl+U - keyHandler.bindAction(85, true, 'ungroup', true); // Ctrl+Shift+U - keyHandler.bindAction(190, true, 'superscript'); // Ctrl+. - keyHandler.bindAction(188, true, 'subscript'); // Ctrl+, - keyHandler.bindAction(9, false, 'indent', true); // Shift+Tab, - keyHandler.bindKey(13, function() { if (graph.isEnabled()) { graph.startEditingAtCell(); }}); // Enter - keyHandler.bindKey(113, function() { if (graph.isEnabled()) { graph.startEditingAtCell(); }}); // F2 - } - - if (!mxClient.IS_WIN) - { - keyHandler.bindAction(90, true, 'redo', true); // Ctrl+Shift+Z - } - else - { - keyHandler.bindAction(89, true, 'redo'); // Ctrl+Y - } - - return keyHandler; -}; - -/** - * Creates the keyboard event handler for the current graph and history. - */ -EditorUi.prototype.destroy = function() -{ - if (this.editor != null) - { - this.editor.destroy(); - this.editor = null; - } - - if (this.menubar != null) - { - this.menubar.destroy(); - this.menubar = null; - } - - if (this.toolbar != null) - { - this.toolbar.destroy(); - this.toolbar = null; - } - - if (this.sidebar != null) - { - this.sidebar.destroy(); - this.sidebar = null; - } - - if (this.keyHandler != null) - { - this.keyHandler.destroy(); - this.keyHandler = null; - } - - if (this.keydownHandler != null) - { - mxEvent.removeListener(document, 'keydown', this.keydownHandler); - this.keydownHandler = null; - } - - if (this.keyupHandler != null) - { - mxEvent.removeListener(document, 'keyup', this.keyupHandler); - this.keyupHandler = null; - } - - if (this.resizeHandler != null) - { - mxEvent.removeListener(window, 'resize', this.resizeHandler); - this.resizeHandler = null; - } - - if (this.gestureHandler != null) - { - mxEvent.removeGestureListeners(document, this.gestureHandler); - this.gestureHandler = null; - } - - if (this.orientationChangeHandler != null) - { - mxEvent.removeListener(window, 'orientationchange', this.orientationChangeHandler); - this.orientationChangeHandler = null; - } - - if (this.scrollHandler != null) - { - mxEvent.removeListener(window, 'scroll', this.scrollHandler); - this.scrollHandler = null; - } - - if (this.destroyFunctions != null) - { - for (var i = 0; i < this.destroyFunctions.length; i++) - { - this.destroyFunctions[i](); - } - - this.destroyFunctions = null; - } - - var c = [this.menubarContainer, this.toolbarContainer, this.sidebarContainer, - this.formatContainer, this.diagramContainer, this.footerContainer, - this.chromelessToolbar, this.hsplit, this.sidebarFooterContainer, - this.layersDialog]; - - for (var i = 0; i < c.length; i++) - { - if (c[i] != null && c[i].parentNode != null) - { - c[i].parentNode.removeChild(c[i]); - } - } -}; diff --git a/src/main/webapp/js/mxgraph/Format.js b/src/main/webapp/js/mxgraph/Format.js deleted file mode 100644 index 021d522b..00000000 --- a/src/main/webapp/js/mxgraph/Format.js +++ /dev/null @@ -1,6629 +0,0 @@ -/** - * Copyright (c) 2006-2012, JGraph Ltd - */ -Format = function(editorUi, container) -{ - this.editorUi = editorUi; - this.container = container; -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.labelIndex = 0; - -/** - * Returns information about the current selection. - */ -Format.prototype.diagramIndex = 0; - -/** - * Returns information about the current selection. - */ -Format.prototype.currentIndex = 0; - -/** - * Returns information about the current selection. - */ -Format.prototype.showCloseButton = true; - -/** - * Background color for inactive tabs. - */ -Format.prototype.inactiveTabBackgroundColor = '#f1f3f4'; - -/** - * Background color for inactive tabs. - */ -Format.prototype.roundableShapes = ['label', 'rectangle', 'internalStorage', 'corner', - 'parallelogram', 'swimlane', 'triangle', 'trapezoid', 'ext', 'step', 'tee', 'process', - 'link', 'rhombus', 'offPageConnector', 'loopLimit', 'hexagon', 'manualInput', 'card', - 'curlyBracket', 'singleArrow', 'callout', 'doubleArrow', 'flexArrow', 'umlLifeline']; - -/** - * Adds the label menu items to the given menu and parent. - */ -Format.prototype.init = function() -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - this.update = mxUtils.bind(this, function(sender, evt) - { - this.clearSelectionState(); - this.refresh(); - }); - - graph.getSelectionModel().addListener(mxEvent.CHANGE, this.update); - graph.addListener(mxEvent.EDITING_STARTED, this.update); - graph.addListener(mxEvent.EDITING_STOPPED, this.update); - graph.getModel().addListener(mxEvent.CHANGE, this.update); - graph.getView().addListener('unitChanged', this.update); - - graph.addListener(mxEvent.ROOT, mxUtils.bind(this, function() - { - this.refresh(); - })); - - ui.addListener('styleChanged', mxUtils.bind(this, function(sender, evt) - { - this.refresh(); - })); - - editor.addListener('autosaveChanged', mxUtils.bind(this, function() - { - this.refresh(); - })); - - this.refresh(); -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.clearSelectionState = function() -{ - this.selectionState = null; -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.getSelectionState = function() -{ - if (this.selectionState == null) - { - this.selectionState = this.createSelectionState(); - } - - return this.selectionState; -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.createSelectionState = function() -{ - var cells = this.editorUi.editor.graph.getSelectionCells(); - var result = this.initSelectionState(); - - for (var i = 0; i < cells.length; i++) - { - this.updateSelectionStateForCell(result, cells[i], cells); - } - - return result; -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.initSelectionState = function() -{ - return {vertices: [], edges: [], x: null, y: null, width: null, height: null, style: {}, - containsImage: false, containsLabel: false, fill: true, glass: true, rounded: true, - autoSize: false, image: true, shadow: true, lineJumps: true, resizable: true, - table: false, cell: false, row: false, movable: true, rotatable: true, stroke: true}; -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.updateSelectionStateForCell = function(result, cell, cells) -{ - var graph = this.editorUi.editor.graph; - - if (graph.getModel().isVertex(cell)) - { - result.resizable = result.resizable && graph.isCellResizable(cell); - result.rotatable = result.rotatable && graph.isCellRotatable(cell); - result.movable = result.movable && graph.isCellMovable(cell) && - !graph.isTableRow(cell) && !graph.isTableCell(cell); - result.table = result.table || graph.isTable(cell); - result.cell = result.cell || graph.isTableCell(cell); - result.row = result.row || graph.isTableRow(cell); - result.vertices.push(cell); - var geo = graph.getCellGeometry(cell); - - if (geo != null) - { - if (geo.width > 0) - { - if (result.width == null) - { - result.width = geo.width; - } - else if (result.width != geo.width) - { - result.width = ''; - } - } - else - { - result.containsLabel = true; - } - - if (geo.height > 0) - { - if (result.height == null) - { - result.height = geo.height; - } - else if (result.height != geo.height) - { - result.height = ''; - } - } - else - { - result.containsLabel = true; - } - - if (!geo.relative || geo.offset != null) - { - var x = (geo.relative) ? geo.offset.x : geo.x; - var y = (geo.relative) ? geo.offset.y : geo.y; - - if (result.x == null) - { - result.x = x; - } - else if (result.x != x) - { - result.x = ''; - } - - if (result.y == null) - { - result.y = y; - } - else if (result.y != y) - { - result.y = ''; - } - } - } - } - else if (graph.getModel().isEdge(cell)) - { - result.edges.push(cell); - result.resizable = false; - result.rotatable = false; - result.movable = false; - } - - var state = graph.view.getState(cell); - - if (state != null) - { - result.autoSize = result.autoSize || this.isAutoSizeState(state); - result.glass = result.glass && this.isGlassState(state); - result.rounded = result.rounded && this.isRoundedState(state); - result.lineJumps = result.lineJumps && this.isLineJumpState(state); - result.image = result.image && this.isImageState(state); - result.shadow = result.shadow && this.isShadowState(state); - result.fill = result.fill && this.isFillState(state); - result.stroke = result.stroke && this.isStrokeState(state); - - var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null); - result.containsImage = result.containsImage || shape == 'image'; - - for (var key in state.style) - { - var value = state.style[key]; - - if (value != null) - { - if (result.style[key] == null) - { - result.style[key] = value; - } - else if (result.style[key] != value) - { - result.style[key] = ''; - } - } - } - } -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isFillState = function(state) -{ - return !this.isSpecialColor(state.style[mxConstants.STYLE_FILLCOLOR]) && - (state.view.graph.model.isVertex(state.cell) || - mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'arrow' || - mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'filledEdge' || - mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'flexArrow'); -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isStrokeState = function(state) -{ - return !this.isSpecialColor(state.style[mxConstants.STYLE_STROKECOLOR]); -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isSpecialColor = function(color) -{ - return mxUtils.indexOf([mxConstants.STYLE_STROKECOLOR, - mxConstants.STYLE_FILLCOLOR, 'inherit', 'swimlane', - 'indicated'], color) >= 0; -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isGlassState = function(state) -{ - var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null); - - return (shape == 'label' || shape == 'rectangle' || shape == 'internalStorage' || - shape == 'ext' || shape == 'umlLifeline' || shape == 'swimlane' || - shape == 'process'); -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isRoundedState = function(state) -{ - return (state.shape != null) ? state.shape.isRoundable() : - mxUtils.indexOf(this.roundableShapes, mxUtils.getValue(state.style, - mxConstants.STYLE_SHAPE, null)) >= 0; -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isLineJumpState = function(state) -{ - var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null); - var curved = mxUtils.getValue(state.style, mxConstants.STYLE_CURVED, false); - - return !curved && (shape == 'connector' || shape == 'filledEdge'); -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isAutoSizeState = function(state) -{ - return mxUtils.getValue(state.style, mxConstants.STYLE_AUTOSIZE, null) == '1'; -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isImageState = function(state) -{ - var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null); - - return (shape == 'label' || shape == 'image'); -}; - -/** - * Returns information about the current selection. - */ -Format.prototype.isShadowState = function(state) -{ - var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null); - - return (shape != 'image'); -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -Format.prototype.clear = function() -{ - this.container.innerHTML = ''; - - // Destroy existing panels - if (this.panels != null) - { - for (var i = 0; i < this.panels.length; i++) - { - this.panels[i].destroy(); - } - } - - this.panels = []; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -Format.prototype.refresh = function() -{ - // Performance tweak: No refresh needed if not visible - if (this.container.style.width == '0px') - { - return; - } - - this.clear(); - var ui = this.editorUi; - var graph = ui.editor.graph; - - var div = document.createElement('div'); - div.style.whiteSpace = 'nowrap'; - div.style.color = 'rgb(112, 112, 112)'; - div.style.textAlign = 'left'; - div.style.cursor = 'default'; - - var label = document.createElement('div'); - label.className = 'geFormatSection'; - label.style.textAlign = 'center'; - label.style.fontWeight = 'bold'; - label.style.paddingTop = '8px'; - label.style.fontSize = '13px'; - label.style.borderWidth = '0px 0px 1px 1px'; - label.style.borderStyle = 'solid'; - label.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block'; - label.style.height = (mxClient.IS_QUIRKS) ? '34px' : '25px'; - label.style.overflow = 'hidden'; - label.style.width = '100%'; - this.container.appendChild(div); - - // Prevents text selection - mxEvent.addListener(label, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown', - mxUtils.bind(this, function(evt) - { - evt.preventDefault(); - })); - - var containsLabel = this.getSelectionState().containsLabel; - var currentLabel = null; - var currentPanel = null; - - var addClickHandler = mxUtils.bind(this, function(elt, panel, index) - { - var clickHandler = mxUtils.bind(this, function(evt) - { - if (currentLabel != elt) - { - if (containsLabel) - { - this.labelIndex = index; - } - else if (graph.isSelectionEmpty()) - { - this.diagramIndex = index; - } - else - { - this.currentIndex = index; - } - - if (currentLabel != null) - { - currentLabel.style.backgroundColor = this.inactiveTabBackgroundColor; - currentLabel.style.borderBottomWidth = '1px'; - } - - currentLabel = elt; - currentLabel.style.backgroundColor = ''; - currentLabel.style.borderBottomWidth = '0px'; - - if (currentPanel != panel) - { - if (currentPanel != null) - { - currentPanel.style.display = 'none'; - } - - currentPanel = panel; - currentPanel.style.display = ''; - } - } - }); - - mxEvent.addListener(elt, 'click', clickHandler); - - // Prevents text selection - mxEvent.addListener(elt, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown', - mxUtils.bind(this, function(evt) - { - evt.preventDefault(); - })); - - if (index == ((containsLabel) ? this.labelIndex : ((graph.isSelectionEmpty()) ? - this.diagramIndex : this.currentIndex))) - { - // Invokes handler directly as a workaround for no click on DIV in KHTML. - clickHandler(); - } - }); - - var idx = 0; - - if (graph.isSelectionEmpty()) - { - mxUtils.write(label, mxResources.get('diagram')); - label.style.borderLeftWidth = '0px'; - - div.appendChild(label); - var diagramPanel = div.cloneNode(false); - this.panels.push(new DiagramFormatPanel(this, ui, diagramPanel)); - this.container.appendChild(diagramPanel); - - if (Editor.styles != null) - { - diagramPanel.style.display = 'none'; - label.style.width = (this.showCloseButton) ? '106px' : '50%'; - label.style.cursor = 'pointer'; - label.style.backgroundColor = this.inactiveTabBackgroundColor; - - var label2 = label.cloneNode(false); - label2.style.borderLeftWidth = '1px'; - label2.style.borderRightWidth = '1px'; - label2.style.backgroundColor = this.inactiveTabBackgroundColor; - - addClickHandler(label, diagramPanel, idx++); - - var stylePanel = div.cloneNode(false); - stylePanel.style.display = 'none'; - mxUtils.write(label2, mxResources.get('style')); - div.appendChild(label2); - this.panels.push(new DiagramStylePanel(this, ui, stylePanel)); - this.container.appendChild(stylePanel); - - addClickHandler(label2, stylePanel, idx++); - } - - // Adds button to hide the format panel since - // people don't seem to find the toolbar button - // and the menu item in the format menu - if (this.showCloseButton) - { - var label2 = label.cloneNode(false); - label2.style.borderLeftWidth = '1px'; - label2.style.borderRightWidth = '1px'; - label2.style.borderBottomWidth = '1px'; - label2.style.backgroundColor = this.inactiveTabBackgroundColor; - label2.style.position = 'absolute'; - label2.style.right = '0px'; - label2.style.top = '0px'; - label2.style.width = '25px'; - - var img = document.createElement('img'); - img.setAttribute('border', '0'); - img.setAttribute('src', Dialog.prototype.closeImage); - img.setAttribute('title', mxResources.get('hide')); - img.style.position = 'absolute'; - img.style.display = 'block'; - img.style.right = '0px'; - img.style.top = '8px'; - img.style.cursor = 'pointer'; - img.style.marginTop = '1px'; - img.style.marginRight = '6px'; - img.style.border = '1px solid transparent'; - img.style.padding = '1px'; - img.style.opacity = 0.5; - label2.appendChild(img) - - mxEvent.addListener(img, 'click', function() - { - ui.actions.get('formatPanel').funct(); - }); - - div.appendChild(label2); - } - } - else if (graph.isEditing()) - { - mxUtils.write(label, mxResources.get('text')); - div.appendChild(label); - this.panels.push(new TextFormatPanel(this, ui, div)); - } - else - { - label.style.backgroundColor = this.inactiveTabBackgroundColor; - label.style.borderLeftWidth = '1px'; - label.style.cursor = 'pointer'; - label.style.width = (containsLabel) ? '50%' : '33.3%'; - var label2 = label.cloneNode(false); - var label3 = label2.cloneNode(false); - - // Workaround for ignored background in IE - label2.style.backgroundColor = this.inactiveTabBackgroundColor; - label3.style.backgroundColor = this.inactiveTabBackgroundColor; - - // Style - if (containsLabel) - { - label2.style.borderLeftWidth = '0px'; - } - else - { - label.style.borderLeftWidth = '0px'; - mxUtils.write(label, mxResources.get('style')); - div.appendChild(label); - - var stylePanel = div.cloneNode(false); - stylePanel.style.display = 'none'; - this.panels.push(new StyleFormatPanel(this, ui, stylePanel)); - this.container.appendChild(stylePanel); - - addClickHandler(label, stylePanel, idx++); - } - - // Text - mxUtils.write(label2, mxResources.get('text')); - div.appendChild(label2); - - var textPanel = div.cloneNode(false); - textPanel.style.display = 'none'; - this.panels.push(new TextFormatPanel(this, ui, textPanel)); - this.container.appendChild(textPanel); - - // Arrange - mxUtils.write(label3, mxResources.get('arrange')); - div.appendChild(label3); - - var arrangePanel = div.cloneNode(false); - arrangePanel.style.display = 'none'; - this.panels.push(new ArrangePanel(this, ui, arrangePanel)); - this.container.appendChild(arrangePanel); - - addClickHandler(label2, textPanel, idx++); - addClickHandler(label3, arrangePanel, idx++); - } -}; - -/** - * Base class for format panels. - */ -BaseFormatPanel = function(format, editorUi, container) -{ - this.format = format; - this.editorUi = editorUi; - this.container = container; - this.listeners = []; -}; - -/** - * - */ -BaseFormatPanel.prototype.buttonBackgroundColor = 'white'; - -/** - * Adds the given color option. - */ -BaseFormatPanel.prototype.getSelectionState = function() -{ - var graph = this.editorUi.editor.graph; - var cells = graph.getSelectionCells(); - var shape = null; - - for (var i = 0; i < cells.length; i++) - { - var state = graph.view.getState(cells[i]); - - if (state != null) - { - var tmp = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null); - - if (tmp != null) - { - if (shape == null) - { - shape = tmp; - } - else if (shape != tmp) - { - return null; - } - } - - } - } - - return shape; -}; - -/** - * Install input handler. - */ -BaseFormatPanel.prototype.installInputHandler = function(input, key, defaultValue, min, max, unit, textEditFallback, isFloat) -{ - unit = (unit != null) ? unit : ''; - isFloat = (isFloat != null) ? isFloat : false; - - var ui = this.editorUi; - var graph = ui.editor.graph; - - min = (min != null) ? min : 1; - max = (max != null) ? max : 999; - - var selState = null; - var updating = false; - - var update = mxUtils.bind(this, function(evt) - { - var value = (isFloat) ? parseFloat(input.value) : parseInt(input.value); - - // Special case: angle mod 360 - if (!isNaN(value) && key == mxConstants.STYLE_ROTATION) - { - // Workaround for decimal rounding errors in floats is to - // use integer and round all numbers to two decimal point - value = mxUtils.mod(Math.round(value * 100), 36000) / 100; - } - - value = Math.min(max, Math.max(min, (isNaN(value)) ? defaultValue : value)); - - if (graph.cellEditor.isContentEditing() && textEditFallback) - { - if (!updating) - { - updating = true; - - if (selState != null) - { - graph.cellEditor.restoreSelection(selState); - selState = null; - } - - textEditFallback(value); - input.value = value + unit; - - // Restore focus and selection in input - updating = false; - } - } - else if (value != mxUtils.getValue(this.format.getSelectionState().style, key, defaultValue)) - { - if (graph.isEditing()) - { - graph.stopEditing(true); - } - - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - graph.setCellStyles(key, value, cells); - - // Handles special case for fontSize where HTML labels are parsed and updated - if (key == mxConstants.STYLE_FONTSIZE) - { - graph.updateLabelElements(graph.getSelectionCells(), function(elt) - { - elt.style.fontSize = value + 'px'; - elt.removeAttribute('size'); - }); - } - - for (var i = 0; i < cells.length; i++) - { - if (graph.model.getChildCount(cells[i]) == 0) - { - graph.autoSizeCell(cells[i], false); - } - } - - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [key], - 'values', [value], 'cells', cells)); - } - finally - { - graph.getModel().endUpdate(); - } - } - - input.value = value + unit; - mxEvent.consume(evt); - }); - - if (textEditFallback && graph.cellEditor.isContentEditing()) - { - // KNOWN: Arrow up/down clear selection text in quirks/IE 8 - // Text size via arrow button limits to 16 in IE11. Why? - mxEvent.addListener(input, 'mousedown', function() - { - if (document.activeElement == graph.cellEditor.textarea) - { - selState = graph.cellEditor.saveSelection(); - } - }); - - mxEvent.addListener(input, 'touchstart', function() - { - if (document.activeElement == graph.cellEditor.textarea) - { - selState = graph.cellEditor.saveSelection(); - } - }); - } - - mxEvent.addListener(input, 'change', update); - mxEvent.addListener(input, 'blur', update); - - return update; -}; - -/** - * Adds the given option. - */ -BaseFormatPanel.prototype.createPanel = function() -{ - var div = document.createElement('div'); - div.className = 'geFormatSection'; - div.style.padding = '12px 0px 12px 18px'; - - return div; -}; - -/** - * Adds the given option. - */ -BaseFormatPanel.prototype.createTitle = function(title) -{ - var div = document.createElement('div'); - div.style.padding = '0px 0px 6px 0px'; - div.style.whiteSpace = 'nowrap'; - div.style.overflow = 'hidden'; - div.style.width = '200px'; - div.style.fontWeight = 'bold'; - mxUtils.write(div, title); - - return div; -}; - -/** - * - */ -BaseFormatPanel.prototype.createStepper = function(input, update, step, height, disableFocus, defaultValue, isFloat) -{ - step = (step != null) ? step : 1; - height = (height != null) ? height : 8; - - if (mxClient.IS_QUIRKS) - { - height = height - 2; - } - else if (mxClient.IS_MT || document.documentMode >= 8) - { - height = height + 1; - } - - var stepper = document.createElement('div'); - mxUtils.setPrefixedStyle(stepper.style, 'borderRadius', '3px'); - stepper.style.border = '1px solid rgb(192, 192, 192)'; - stepper.style.position = 'absolute'; - - var up = document.createElement('div'); - up.style.borderBottom = '1px solid rgb(192, 192, 192)'; - up.style.position = 'relative'; - up.style.height = height + 'px'; - up.style.width = '10px'; - up.className = 'geBtnUp'; - stepper.appendChild(up); - - var down = up.cloneNode(false); - down.style.border = 'none'; - down.style.height = height + 'px'; - down.className = 'geBtnDown'; - stepper.appendChild(down); - - mxEvent.addListener(down, 'click', function(evt) - { - if (input.value == '') - { - input.value = defaultValue || '2'; - } - - var val = isFloat? parseFloat(input.value) : parseInt(input.value); - - if (!isNaN(val)) - { - input.value = val - step; - - if (update != null) - { - update(evt); - } - } - - mxEvent.consume(evt); - }); - - mxEvent.addListener(up, 'click', function(evt) - { - if (input.value == '') - { - input.value = defaultValue || '0'; - } - - var val = isFloat? parseFloat(input.value) : parseInt(input.value); - - if (!isNaN(val)) - { - input.value = val + step; - - if (update != null) - { - update(evt); - } - } - - mxEvent.consume(evt); - }); - - // Disables transfer of focus to DIV but also :active CSS - // so it's only used for fontSize where the focus should - // stay on the selected text, but not for any other input. - if (disableFocus) - { - var currentSelection = null; - - mxEvent.addGestureListeners(stepper, - function(evt) - { - // Workaround for lost current selection in page because of focus in IE - if (mxClient.IS_QUIRKS || document.documentMode == 8) - { - currentSelection = document.selection.createRange(); - } - - mxEvent.consume(evt); - }, - null, - function(evt) - { - // Workaround for lost current selection in page because of focus in IE - if (currentSelection != null) - { - try - { - currentSelection.select(); - } - catch (e) - { - // ignore - } - - currentSelection = null; - mxEvent.consume(evt); - } - } - ); - } - - return stepper; -}; - -/** - * Adds the given option. - */ -BaseFormatPanel.prototype.createOption = function(label, isCheckedFn, setCheckedFn, listener, fn) -{ - var div = document.createElement('div'); - div.style.padding = '6px 0px 1px 0px'; - div.style.whiteSpace = 'nowrap'; - div.style.overflow = 'hidden'; - div.style.width = '200px'; - div.style.height = (mxClient.IS_QUIRKS) ? '27px' : '18px'; - - var cb = document.createElement('input'); - cb.setAttribute('type', 'checkbox'); - cb.style.margin = '0px 6px 0px 0px'; - div.appendChild(cb); - - var span = document.createElement('span'); - mxUtils.write(span, label); - div.appendChild(span); - - var applying = false; - var value = isCheckedFn(); - - var apply = function(newValue) - { - if (!applying) - { - applying = true; - - if (newValue) - { - cb.setAttribute('checked', 'checked'); - cb.defaultChecked = true; - cb.checked = true; - } - else - { - cb.removeAttribute('checked'); - cb.defaultChecked = false; - cb.checked = false; - } - - if (value != newValue) - { - value = newValue; - - // Checks if the color value needs to be updated in the model - if (isCheckedFn() != value) - { - setCheckedFn(value); - } - } - - applying = false; - } - }; - - mxEvent.addListener(div, 'click', function(evt) - { - if (cb.getAttribute('disabled') != 'disabled') - { - // Toggles checkbox state for click on label - var source = mxEvent.getSource(evt); - - if (source == div || source == span) - { - cb.checked = !cb.checked; - } - - apply(cb.checked); - } - }); - - apply(value); - - if (listener != null) - { - listener.install(apply); - this.listeners.push(listener); - } - - if (fn != null) - { - fn(div); - } - - return div; -}; - -/** - * The string 'null' means use null in values. - */ -BaseFormatPanel.prototype.createCellOption = function(label, key, defaultValue, enabledValue, disabledValue, fn, action, stopEditing) -{ - enabledValue = (enabledValue != null) ? ((enabledValue == 'null') ? null : enabledValue) : '1'; - disabledValue = (disabledValue != null) ? ((disabledValue == 'null') ? null : disabledValue) : '0'; - - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - return this.createOption(label, function() - { - // Seems to be null sometimes, not sure why... - var state = graph.view.getState(graph.getSelectionCell()); - - if (state != null) - { - return mxUtils.getValue(state.style, key, defaultValue) != disabledValue; - } - - return null; - }, function(checked) - { - if (stopEditing) - { - graph.stopEditing(); - } - - if (action != null) - { - action.funct(); - } - else - { - graph.getModel().beginUpdate(); - try - { - var value = (checked) ? enabledValue : disabledValue; - graph.setCellStyles(key, value, graph.getSelectionCells()); - - if (fn != null) - { - fn(graph.getSelectionCells(), value); - } - - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [key], - 'values', [value], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - } - }, - { - install: function(apply) - { - this.listener = function() - { - // Seems to be null sometimes, not sure why... - var state = graph.view.getState(graph.getSelectionCell()); - - if (state != null) - { - apply(mxUtils.getValue(state.style, key, defaultValue) != disabledValue); - } - }; - - graph.getModel().addListener(mxEvent.CHANGE, this.listener); - }, - destroy: function() - { - graph.getModel().removeListener(this.listener); - } - }); -}; - -/** - * Adds the given color option. - */ -BaseFormatPanel.prototype.createColorOption = function(label, getColorFn, setColorFn, defaultColor, listener, callbackFn, hideCheckbox) -{ - var div = document.createElement('div'); - div.style.padding = '6px 0px 1px 0px'; - div.style.whiteSpace = 'nowrap'; - div.style.overflow = 'hidden'; - div.style.width = '200px'; - div.style.height = (mxClient.IS_QUIRKS) ? '27px' : '18px'; - - var cb = document.createElement('input'); - cb.setAttribute('type', 'checkbox'); - cb.style.margin = '0px 6px 0px 0px'; - - if (!hideCheckbox) - { - div.appendChild(cb); - } - - var span = document.createElement('span'); - mxUtils.write(span, label); - div.appendChild(span); - - var value = getColorFn(); - var applying = false; - var btn = null; - - var apply = function(color, disableUpdate, forceUpdate) - { - if (!applying) - { - applying = true; - color = (/(^#?[a-zA-Z0-9]*$)/.test(color)) ? color : defaultColor; - btn.innerHTML = '
'; - - // Fine-tuning in Firefox, quirks mode and IE8 standards - if (mxClient.IS_QUIRKS || document.documentMode == 8) - { - btn.firstChild.style.margin = '0px'; - } - - if (color != null && color != mxConstants.NONE) - { - cb.setAttribute('checked', 'checked'); - cb.defaultChecked = true; - cb.checked = true; - } - else - { - cb.removeAttribute('checked'); - cb.defaultChecked = false; - cb.checked = false; - } - - btn.style.display = (cb.checked || hideCheckbox) ? '' : 'none'; - - if (callbackFn != null) - { - callbackFn(color); - } - - if (!disableUpdate) - { - value = color; - - // Checks if the color value needs to be updated in the model - if (forceUpdate || hideCheckbox || getColorFn() != value) - { - setColorFn(value); - } - } - - applying = false; - } - }; - - btn = mxUtils.button('', mxUtils.bind(this, function(evt) - { - this.editorUi.pickColor(value, function(color) - { - apply(color, null, true); - }); - mxEvent.consume(evt); - })); - - btn.style.position = 'absolute'; - btn.style.marginTop = '-4px'; - btn.style.right = (mxClient.IS_QUIRKS) ? '0px' : '20px'; - btn.style.height = '22px'; - btn.className = 'geColorBtn'; - btn.style.display = (cb.checked || hideCheckbox) ? '' : 'none'; - div.appendChild(btn); - - mxEvent.addListener(div, 'click', function(evt) - { - var source = mxEvent.getSource(evt); - - if (source == cb || source.nodeName != 'INPUT') - { - // Toggles checkbox state for click on label - if (source != cb) - { - cb.checked = !cb.checked; - } - - // Overrides default value with current value to make it easier - // to restore previous value if the checkbox is clicked twice - if (!cb.checked && value != null && value != mxConstants.NONE && - defaultColor != mxConstants.NONE) - { - defaultColor = value; - } - - apply((cb.checked) ? defaultColor : mxConstants.NONE); - } - }); - - apply(value, true); - - if (listener != null) - { - listener.install(apply); - this.listeners.push(listener); - } - - return div; -}; - -/** - * - */ -BaseFormatPanel.prototype.createCellColorOption = function(label, colorKey, defaultColor, callbackFn, setStyleFn) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - return this.createColorOption(label, function() - { - // Seems to be null sometimes, not sure why... - var state = graph.view.getState(graph.getSelectionCell()); - - if (state != null) - { - return mxUtils.getValue(state.style, colorKey, null); - } - - return null; - }, function(color) - { - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles(colorKey, color, graph.getSelectionCells()); - - if (setStyleFn != null) - { - setStyleFn(color); - } - - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [colorKey], - 'values', [color], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - }, defaultColor || mxConstants.NONE, - { - install: function(apply) - { - this.listener = function() - { - // Seems to be null sometimes, not sure why... - var state = graph.view.getState(graph.getSelectionCell()); - - if (state != null) - { - apply(mxUtils.getValue(state.style, colorKey, null)); - } - }; - - graph.getModel().addListener(mxEvent.CHANGE, this.listener); - }, - destroy: function() - { - graph.getModel().removeListener(this.listener); - } - }, callbackFn); -}; - -/** - * - */ -BaseFormatPanel.prototype.addArrow = function(elt, height) -{ - height = (height != null) ? height : 10; - - var arrow = document.createElement('div'); - arrow.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block'; - arrow.style.padding = '6px'; - arrow.style.paddingRight = '4px'; - - var m = (10 - height); - - if (m == 2) - { - arrow.style.paddingTop = 6 + 'px'; - } - else if (m > 0) - { - arrow.style.paddingTop = (6 - m) + 'px'; - } - else - { - arrow.style.marginTop = '-2px'; - } - - arrow.style.height = height + 'px'; - arrow.style.borderLeft = '1px solid #a0a0a0'; - arrow.innerHTML = ''; - mxUtils.setOpacity(arrow, 70); - - var symbol = elt.getElementsByTagName('div')[0]; - - if (symbol != null) - { - symbol.style.paddingRight = '6px'; - symbol.style.marginLeft = '4px'; - symbol.style.marginTop = '-1px'; - symbol.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block'; - mxUtils.setOpacity(symbol, 60); - } - - mxUtils.setOpacity(elt, 100); - elt.style.border = '1px solid #a0a0a0'; - elt.style.backgroundColor = this.buttonBackgroundColor; - elt.style.backgroundImage = 'none'; - elt.style.width = 'auto'; - elt.className += ' geColorBtn'; - mxUtils.setPrefixedStyle(elt.style, 'borderRadius', '3px'); - - elt.appendChild(arrow); - - return symbol; -}; - -/** - * - */ -BaseFormatPanel.prototype.addUnitInput = function(container, unit, right, width, update, step, marginTop, disableFocus, isFloat) -{ - marginTop = (marginTop != null) ? marginTop : 0; - - var input = document.createElement('input'); - input.style.position = 'absolute'; - input.style.textAlign = 'right'; - input.style.marginTop = '-2px'; - input.style.right = (right + 12) + 'px'; - input.style.width = width + 'px'; - container.appendChild(input); - - var stepper = this.createStepper(input, update, step, null, disableFocus, null, isFloat); - stepper.style.marginTop = (marginTop - 2) + 'px'; - stepper.style.right = right + 'px'; - container.appendChild(stepper); - - return input; -}; - -/** - * - */ -BaseFormatPanel.prototype.createRelativeOption = function(label, key, width, handler, init) -{ - width = (width != null) ? width : 44; - - var graph = this.editorUi.editor.graph; - var div = this.createPanel(); - div.style.paddingTop = '10px'; - div.style.paddingBottom = '10px'; - mxUtils.write(div, label); - div.style.fontWeight = 'bold'; - - var update = mxUtils.bind(this, function(evt) - { - if (handler != null) - { - handler(input); - } - else - { - var value = parseInt(input.value); - value = Math.min(100, Math.max(0, (isNaN(value)) ? 100 : value)); - var state = graph.view.getState(graph.getSelectionCell()); - - if (state != null && value != mxUtils.getValue(state.style, key, 100)) - { - // Removes entry in style (assumes 100 is default for relative values) - if (value == 100) - { - value = null; - } - - graph.setCellStyles(key, value, graph.getSelectionCells()); - this.editorUi.fireEvent(new mxEventObject('styleChanged', 'keys', [key], - 'values', [value], 'cells', graph.getSelectionCells())); - } - - input.value = ((value != null) ? value : '100') + ' %'; - } - - mxEvent.consume(evt); - }); - - var input = this.addUnitInput(div, '%', 20, width, update, 10, -15, handler != null); - - if (key != null) - { - var listener = mxUtils.bind(this, function(sender, evt, force) - { - if (force || input != document.activeElement) - { - var ss = this.format.getSelectionState(); - var tmp = parseInt(mxUtils.getValue(ss.style, key, 100)); - input.value = (isNaN(tmp)) ? '' : tmp + ' %'; - } - }); - - mxEvent.addListener(input, 'keydown', function(e) - { - if (e.keyCode == 13) - { - graph.container.focus(); - mxEvent.consume(e); - } - else if (e.keyCode == 27) - { - listener(null, null, true); - graph.container.focus(); - mxEvent.consume(e); - } - }); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); - } - - mxEvent.addListener(input, 'blur', update); - mxEvent.addListener(input, 'change', update); - - if (init != null) - { - init(input); - } - - return div; -}; - -/** - * - */ -BaseFormatPanel.prototype.addLabel = function(div, title, right, width) -{ - width = (width != null) ? width : 61; - - var label = document.createElement('div'); - mxUtils.write(label, title); - label.style.position = 'absolute'; - label.style.right = right + 'px'; - label.style.width = width + 'px'; - label.style.marginTop = '6px'; - label.style.textAlign = 'center'; - div.appendChild(label); -}; - -/** - * - */ -BaseFormatPanel.prototype.addKeyHandler = function(input, listener) -{ - mxEvent.addListener(input, 'keydown', mxUtils.bind(this, function(e) - { - if (e.keyCode == 13) - { - this.editorUi.editor.graph.container.focus(); - mxEvent.consume(e); - } - else if (e.keyCode == 27) - { - if (listener != null) - { - listener(null, null, true); - } - - this.editorUi.editor.graph.container.focus(); - mxEvent.consume(e); - } - })); -}; - -/** - * - */ -BaseFormatPanel.prototype.styleButtons = function(elts) -{ - for (var i = 0; i < elts.length; i++) - { - mxUtils.setPrefixedStyle(elts[i].style, 'borderRadius', '3px'); - mxUtils.setOpacity(elts[i], 100); - elts[i].style.border = '1px solid #a0a0a0'; - elts[i].style.padding = '4px'; - elts[i].style.paddingTop = '3px'; - elts[i].style.paddingRight = '1px'; - elts[i].style.margin = '1px'; - elts[i].style.width = '24px'; - elts[i].style.height = '20px'; - elts[i].className += ' geColorBtn'; - } -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -BaseFormatPanel.prototype.destroy = function() -{ - if (this.listeners != null) - { - for (var i = 0; i < this.listeners.length; i++) - { - this.listeners[i].destroy(); - } - - this.listeners = null; - } -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -ArrangePanel = function(format, editorUi, container) -{ - BaseFormatPanel.call(this, format, editorUi, container); - this.init(); -}; - -mxUtils.extend(ArrangePanel, BaseFormatPanel); - -/** - * Adds the label menu items to the given menu and parent. - */ -ArrangePanel.prototype.init = function() -{ - var graph = this.editorUi.editor.graph; - var ss = this.format.getSelectionState(); - - this.container.appendChild(this.addLayerOps(this.createPanel())); - // Special case that adds two panels - this.addGeometry(this.container); - this.addEdgeGeometry(this.container); - - if (!ss.containsLabel || ss.edges.length == 0) - { - this.container.appendChild(this.addAngle(this.createPanel())); - } - - if (!ss.containsLabel && ss.edges.length == 0 && - ss.style.shape != 'rectangle' && - ss.style.shape != 'label') - { - this.container.appendChild(this.addFlip(this.createPanel())); - } - - if (ss.vertices.length > 1) - { - this.container.appendChild(this.addAlign(this.createPanel())); - this.container.appendChild(this.addDistribute(this.createPanel())); - } - - if (graph.isTable(ss.vertices[0]) || - graph.isTableRow(ss.vertices[0]) || - graph.isTableCell(ss.vertices[0])) - { - this.container.appendChild(this.addTable(this.createPanel())); - } - - this.container.appendChild(this.addGroupOps(this.createPanel())); - - if (ss.containsLabel) - { - // Adds functions from hidden style format panel - var span = document.createElement('div'); - span.style.width = '100%'; - span.style.marginTop = '0px'; - span.style.fontWeight = 'bold'; - span.style.padding = '10px 0 0 18px'; - mxUtils.write(span, mxResources.get('style')); - this.container.appendChild(span); - - new StyleFormatPanel(this.format, this.editorUi, this.container); - } -}; - -/** - * - */ -ArrangePanel.prototype.addTable = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - var ss = this.format.getSelectionState(); - div.style.paddingTop = '6px'; - div.style.paddingBottom = '10px'; - - var span = document.createElement('div'); - span.style.marginTop = '2px'; - span.style.marginBottom = '8px'; - span.style.fontWeight = 'bold'; - mxUtils.write(span, mxResources.get('table')); - div.appendChild(span); - - var panel = document.createElement('div'); - panel.style.position = 'relative'; - panel.style.paddingLeft = '0px'; - panel.style.borderWidth = '0px'; - panel.className = 'geToolbarContainer'; - - var btns = [ - ui.toolbar.addButton('geSprite-insertcolumnbefore', mxResources.get('insertColumnBefore'), - mxUtils.bind(this, function() - { - try - { - graph.insertTableColumn(ss.vertices[0], true); - } - catch (e) - { - ui.handleError(e); - } - }), panel), - ui.toolbar.addButton('geSprite-insertcolumnafter', mxResources.get('insertColumnAfter'), - mxUtils.bind(this, function() - { - try - { - graph.insertTableColumn(ss.vertices[0], false); - } - catch (e) - { - ui.handleError(e); - } - }), panel), - ui.toolbar.addButton('geSprite-deletecolumn', mxResources.get('deleteColumn'), - mxUtils.bind(this, function() - { - try - { - graph.deleteTableColumn(ss.vertices[0]); - } - catch (e) - { - ui.handleError(e); - } - }), panel), - ui.toolbar.addButton('geSprite-insertrowbefore', mxResources.get('insertRowBefore'), - mxUtils.bind(this, function() - { - try - { - graph.insertTableRow(ss.vertices[0], true); - } - catch (e) - { - ui.handleError(e); - } - }), panel), - ui.toolbar.addButton('geSprite-insertrowafter', mxResources.get('insertRowAfter'), - mxUtils.bind(this, function() - { - try - { - graph.insertTableRow(ss.vertices[0], false); - } - catch (e) - { - ui.handleError(e); - } - }), panel), - ui.toolbar.addButton('geSprite-deleterow', mxResources.get('deleteRow'), - mxUtils.bind(this, function() - { - try - { - graph.deleteTableRow(ss.vertices[0]); - } - catch (e) - { - ui.handleError(e); - } - }), panel)]; - this.styleButtons(btns); - div.appendChild(panel); - btns[2].style.marginRight = '9px'; - - return div; -}; - -/** - * - */ -ArrangePanel.prototype.addLayerOps = function(div) -{ - var ui = this.editorUi; - - var btn = mxUtils.button(mxResources.get('toFront'), function(evt) - { - ui.actions.get('toFront').funct(); - }) - - btn.setAttribute('title', mxResources.get('toFront') + ' (' + this.editorUi.actions.get('toFront').shortcut + ')'); - btn.style.width = '100px'; - btn.style.marginRight = '2px'; - div.appendChild(btn); - - var btn = mxUtils.button(mxResources.get('toBack'), function(evt) - { - ui.actions.get('toBack').funct(); - }) - - btn.setAttribute('title', mxResources.get('toBack') + ' (' + this.editorUi.actions.get('toBack').shortcut + ')'); - btn.style.width = '100px'; - div.appendChild(btn); - - return div; -}; - -/** - * - */ -ArrangePanel.prototype.addGroupOps = function(div) -{ - var ui = this.editorUi; - var graph = ui.editor.graph; - var cell = graph.getSelectionCell(); - var ss = this.format.getSelectionState(); - var count = 0; - var btn = null; - - div.style.paddingTop = '8px'; - div.style.paddingBottom = '6px'; - - if (graph.getSelectionCount() > 1) - { - btn = mxUtils.button(mxResources.get('group'), function(evt) - { - ui.actions.get('group').funct(); - }) - - btn.setAttribute('title', mxResources.get('group') + ' (' + this.editorUi.actions.get('group').shortcut + ')'); - btn.style.width = '202px'; - btn.style.marginBottom = '2px'; - div.appendChild(btn); - count++; - } - else if (graph.getSelectionCount() == 1 && !graph.getModel().isEdge(cell) && !graph.isSwimlane(cell) && - !graph.isTable(cell) && !ss.row && !ss.cell && graph.getModel().getChildCount(cell) > 0) - { - btn = mxUtils.button(mxResources.get('ungroup'), function(evt) - { - ui.actions.get('ungroup').funct(); - }) - - btn.setAttribute('title', mxResources.get('ungroup') + ' (' + - this.editorUi.actions.get('ungroup').shortcut + ')'); - btn.style.width = '202px'; - btn.style.marginBottom = '2px'; - div.appendChild(btn); - count++; - } - - if (ss.vertices.length > 0) - { - if (count > 0) - { - mxUtils.br(div); - count = 0; - } - - var btn = mxUtils.button(mxResources.get('copySize'), function(evt) - { - ui.actions.get('copySize').funct(); - }); - - btn.setAttribute('title', mxResources.get('copySize') + ' (' + - this.editorUi.actions.get('copySize').shortcut + ')'); - btn.style.width = '202px'; - btn.style.marginBottom = '2px'; - - div.appendChild(btn); - count++; - - if (ui.copiedSize != null) - { - var btn2 = mxUtils.button(mxResources.get('pasteSize'), function(evt) - { - ui.actions.get('pasteSize').funct(); - }); - - btn2.setAttribute('title', mxResources.get('pasteSize') + ' (' + - this.editorUi.actions.get('pasteSize').shortcut + ')'); - - div.appendChild(btn2); - count++; - - btn.style.width = '100px'; - btn.style.marginBottom = '2px'; - btn2.style.width = '100px'; - btn2.style.marginBottom = '2px'; - } - } - - if (graph.getSelectionCount() == 1 && graph.getModel().isVertex(cell) && !ss.row && - !ss.cell && graph.getModel().isVertex(graph.getModel().getParent(cell))) - { - if (count > 0) - { - mxUtils.br(div); - } - - btn = mxUtils.button(mxResources.get('removeFromGroup'), function(evt) - { - ui.actions.get('removeFromGroup').funct(); - }) - - btn.setAttribute('title', mxResources.get('removeFromGroup')); - btn.style.width = '202px'; - btn.style.marginBottom = '2px'; - div.appendChild(btn); - count++; - } - else if (graph.getSelectionCount() > 0) - { - if (count > 0) - { - mxUtils.br(div); - } - - btn = mxUtils.button(mxResources.get('clearWaypoints'), mxUtils.bind(this, function(evt) - { - this.editorUi.actions.get('clearWaypoints').funct(); - })); - - btn.setAttribute('title', mxResources.get('clearWaypoints') + ' (' + this.editorUi.actions.get('clearWaypoints').shortcut + ')'); - btn.style.width = '202px'; - btn.style.marginBottom = '2px'; - div.appendChild(btn); - - count++; - } - - if (graph.getSelectionCount() == 1) - { - if (count > 0) - { - mxUtils.br(div); - } - - btn = mxUtils.button(mxResources.get('editData'), mxUtils.bind(this, function(evt) - { - this.editorUi.actions.get('editData').funct(); - })); - - btn.setAttribute('title', mxResources.get('editData') + ' (' + this.editorUi.actions.get('editData').shortcut + ')'); - btn.style.width = '100px'; - btn.style.marginBottom = '2px'; - div.appendChild(btn); - count++; - - btn = mxUtils.button(mxResources.get('editLink'), mxUtils.bind(this, function(evt) - { - this.editorUi.actions.get('editLink').funct(); - })); - - btn.setAttribute('title', mxResources.get('editLink')); - btn.style.width = '100px'; - btn.style.marginLeft = '2px'; - btn.style.marginBottom = '2px'; - div.appendChild(btn); - count++; - } - - if (count == 0) - { - div.style.display = 'none'; - } - - return div; -}; - -/** - * - */ -ArrangePanel.prototype.addAlign = function(div) -{ - var graph = this.editorUi.editor.graph; - div.style.paddingTop = '6px'; - div.style.paddingBottom = '12px'; - div.appendChild(this.createTitle(mxResources.get('align'))); - - var stylePanel = document.createElement('div'); - stylePanel.style.position = 'relative'; - stylePanel.style.paddingLeft = '0px'; - stylePanel.style.borderWidth = '0px'; - stylePanel.className = 'geToolbarContainer'; - - if (mxClient.IS_QUIRKS) - { - div.style.height = '60px'; - } - - var left = this.editorUi.toolbar.addButton('geSprite-alignleft', mxResources.get('left'), - function() { graph.alignCells(mxConstants.ALIGN_LEFT); }, stylePanel); - var center = this.editorUi.toolbar.addButton('geSprite-aligncenter', mxResources.get('center'), - function() { graph.alignCells(mxConstants.ALIGN_CENTER); }, stylePanel); - var right = this.editorUi.toolbar.addButton('geSprite-alignright', mxResources.get('right'), - function() { graph.alignCells(mxConstants.ALIGN_RIGHT); }, stylePanel); - - var top = this.editorUi.toolbar.addButton('geSprite-aligntop', mxResources.get('top'), - function() { graph.alignCells(mxConstants.ALIGN_TOP); }, stylePanel); - var middle = this.editorUi.toolbar.addButton('geSprite-alignmiddle', mxResources.get('middle'), - function() { graph.alignCells(mxConstants.ALIGN_MIDDLE); }, stylePanel); - var bottom = this.editorUi.toolbar.addButton('geSprite-alignbottom', mxResources.get('bottom'), - function() { graph.alignCells(mxConstants.ALIGN_BOTTOM); }, stylePanel); - - this.styleButtons([left, center, right, top, middle, bottom]); - right.style.marginRight = '6px'; - div.appendChild(stylePanel); - - return div; -}; - -/** - * - */ -ArrangePanel.prototype.addFlip = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - div.style.paddingTop = '6px'; - div.style.paddingBottom = '10px'; - - var span = document.createElement('div'); - span.style.marginTop = '2px'; - span.style.marginBottom = '8px'; - span.style.fontWeight = 'bold'; - mxUtils.write(span, mxResources.get('flip')); - div.appendChild(span); - - var btn = mxUtils.button(mxResources.get('horizontal'), function(evt) - { - graph.toggleCellStyles(mxConstants.STYLE_FLIPH, false); - }) - - btn.setAttribute('title', mxResources.get('horizontal')); - btn.style.width = '100px'; - btn.style.marginRight = '2px'; - div.appendChild(btn); - - var btn = mxUtils.button(mxResources.get('vertical'), function(evt) - { - graph.toggleCellStyles(mxConstants.STYLE_FLIPV, false); - }) - - btn.setAttribute('title', mxResources.get('vertical')); - btn.style.width = '100px'; - div.appendChild(btn); - - return div; -}; - -/** - * - */ -ArrangePanel.prototype.addDistribute = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - div.style.paddingTop = '6px'; - div.style.paddingBottom = '12px'; - - div.appendChild(this.createTitle(mxResources.get('distribute'))); - - var btn = mxUtils.button(mxResources.get('horizontal'), function(evt) - { - graph.distributeCells(true); - }) - - btn.setAttribute('title', mxResources.get('horizontal')); - btn.style.width = '100px'; - btn.style.marginRight = '2px'; - div.appendChild(btn); - - var btn = mxUtils.button(mxResources.get('vertical'), function(evt) - { - graph.distributeCells(false); - }) - - btn.setAttribute('title', mxResources.get('vertical')); - btn.style.width = '100px'; - div.appendChild(btn); - - return div; -}; - -/** - * - */ -ArrangePanel.prototype.addAngle = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - var ss = this.format.getSelectionState(); - - div.style.paddingBottom = '8px'; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.width = '70px'; - span.style.marginTop = '0px'; - span.style.fontWeight = 'bold'; - - var input = null; - var update = null; - var btn = null; - - if (ss.rotatable && !ss.table && !ss.row && !ss.cell) - { - mxUtils.write(span, mxResources.get('angle')); - div.appendChild(span); - - input = this.addUnitInput(div, '°', 20, 44, function() - { - update.apply(this, arguments); - }); - - mxUtils.br(div); - div.style.paddingTop = '10px'; - } - else - { - div.style.paddingTop = '8px'; - } - - if (!ss.containsLabel) - { - var label = mxResources.get('reverse'); - - if (ss.vertices.length > 0 && ss.edges.length > 0) - { - label = mxResources.get('turn') + ' / ' + label; - } - else if (ss.vertices.length > 0) - { - label = mxResources.get('turn'); - } - - btn = mxUtils.button(label, function(evt) - { - ui.actions.get('turn').funct(evt); - }) - - btn.setAttribute('title', label + ' (' + this.editorUi.actions.get('turn').shortcut + ')'); - btn.style.width = '202px'; - div.appendChild(btn); - - if (input != null) - { - btn.style.marginTop = '8px'; - } - } - - if (input != null) - { - var listener = mxUtils.bind(this, function(sender, evt, force) - { - if (force || document.activeElement != input) - { - ss = this.format.getSelectionState(); - var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_ROTATION, 0)); - input.value = (isNaN(tmp)) ? '' : tmp + '°'; - } - }); - - update = this.installInputHandler(input, mxConstants.STYLE_ROTATION, 0, 0, 360, '°', null, true); - this.addKeyHandler(input, listener); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); - } - - return div; -}; - -BaseFormatPanel.prototype.getUnit = function() -{ - var unit = this.editorUi.editor.graph.view.unit; - - switch(unit) - { - case mxConstants.POINTS: - return 'pt'; - case mxConstants.INCHES: - return '"'; - case mxConstants.MILLIMETERS: - return 'mm'; - } -}; - -BaseFormatPanel.prototype.inUnit = function(pixels) -{ - return this.editorUi.editor.graph.view.formatUnitText(pixels); -}; - -BaseFormatPanel.prototype.fromUnit = function(value) -{ - var unit = this.editorUi.editor.graph.view.unit; - - switch(unit) - { - case mxConstants.POINTS: - return value; - case mxConstants.INCHES: - return value * mxConstants.PIXELS_PER_INCH; - case mxConstants.MILLIMETERS: - return value * mxConstants.PIXELS_PER_MM; - } -}; - -BaseFormatPanel.prototype.isFloatUnit = function() -{ - return this.editorUi.editor.graph.view.unit != mxConstants.POINTS; -}; - -BaseFormatPanel.prototype.getUnitStep = function() -{ - var unit = this.editorUi.editor.graph.view.unit; - - switch(unit) - { - case mxConstants.POINTS: - return 1; - case mxConstants.INCHES: - return 0.1; - case mxConstants.MILLIMETERS: - return 0.5; - } -}; - -/** - * - */ -ArrangePanel.prototype.addGeometry = function(container) -{ - var panel = this; - var ui = this.editorUi; - var graph = ui.editor.graph; - var rect = this.format.getSelectionState(); - - var div = this.createPanel(); - div.style.paddingBottom = '8px'; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.width = '50px'; - span.style.marginTop = '0px'; - span.style.fontWeight = 'bold'; - mxUtils.write(span, mxResources.get('size')); - div.appendChild(span); - - var widthUpdate, heightUpdate, leftUpdate, topUpdate; - var width = this.addUnitInput(div, this.getUnit(), 84, 44, function() - { - widthUpdate.apply(this, arguments); - }, this.getUnitStep(), null, null, this.isFloatUnit()); - var height = this.addUnitInput(div, this.getUnit(), 20, 44, function() - { - heightUpdate.apply(this, arguments); - }, this.getUnitStep(), null, null, this.isFloatUnit()); - - var autosizeBtn = document.createElement('div'); - autosizeBtn.className = 'geSprite geSprite-fit'; - autosizeBtn.setAttribute('title', mxResources.get('autosize') + ' (' + this.editorUi.actions.get('autosize').shortcut + ')'); - autosizeBtn.style.position = 'relative'; - autosizeBtn.style.cursor = 'pointer'; - autosizeBtn.style.marginTop = '-3px'; - autosizeBtn.style.border = '0px'; - autosizeBtn.style.left = '42px'; - mxUtils.setOpacity(autosizeBtn, 50); - - mxEvent.addListener(autosizeBtn, 'mouseenter', function() - { - mxUtils.setOpacity(autosizeBtn, 100); - }); - - mxEvent.addListener(autosizeBtn, 'mouseleave', function() - { - mxUtils.setOpacity(autosizeBtn, 50); - }); - - mxEvent.addListener(autosizeBtn, 'click', function() - { - ui.actions.get('autosize').funct(); - }); - - div.appendChild(autosizeBtn); - - if (rect.row) - { - width.style.visibility = 'hidden'; - width.nextSibling.style.visibility = 'hidden'; - } - else - { - this.addLabel(div, mxResources.get('width'), 84); - } - - this.addLabel(div, mxResources.get('height'), 20); - mxUtils.br(div); - - var wrapper = document.createElement('div'); - wrapper.style.paddingTop = '8px'; - wrapper.style.paddingRight = '20px'; - wrapper.style.whiteSpace = 'nowrap'; - wrapper.style.textAlign = 'right'; - var opt = this.createCellOption(mxResources.get('constrainProportions'), - mxConstants.STYLE_ASPECT, null, 'fixed', 'null'); - opt.style.width = '100%'; - wrapper.appendChild(opt); - - if (!rect.cell && !rect.row) - { - div.appendChild(wrapper); - } - else - { - autosizeBtn.style.visibility = 'hidden'; - } - - var constrainCheckbox = opt.getElementsByTagName('input')[0]; - this.addKeyHandler(width, listener); - this.addKeyHandler(height, listener); - - widthUpdate = this.addGeometryHandler(width, function(geo, value, cell) - { - if (graph.isTableCell(cell)) - { - graph.setTableColumnWidth(cell, value - geo.width, true); - - // Blocks processing in caller - return true; - } - else if (geo.width > 0) - { - var value = Math.max(1, panel.fromUnit(value)); - - if (constrainCheckbox.checked) - { - geo.height = Math.round((geo.height * value * 100) / geo.width) / 100; - } - - geo.width = value; - } - }); - heightUpdate = this.addGeometryHandler(height, function(geo, value, cell) - { - if (graph.isTableCell(cell)) - { - cell = graph.model.getParent(cell); - } - - if (graph.isTableRow(cell)) - { - graph.setTableRowHeight(cell, value - geo.height); - - // Blocks processing in caller - return true; - } - else if (geo.height > 0) - { - var value = Math.max(1, panel.fromUnit(value)); - - if (constrainCheckbox.checked) - { - geo.width = Math.round((geo.width * value * 100) / geo.height) / 100; - } - - geo.height = value; - } - }); - - if (rect.resizable || rect.row || rect.cell) - { - container.appendChild(div); - } - - var div2 = this.createPanel(); - div2.style.paddingBottom = '30px'; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.width = '70px'; - span.style.marginTop = '0px'; - span.style.fontWeight = 'bold'; - mxUtils.write(span, mxResources.get('position')); - div2.appendChild(span); - - var left = this.addUnitInput(div2, this.getUnit(), 84, 44, function() - { - leftUpdate.apply(this, arguments); - }, this.getUnitStep(), null, null, this.isFloatUnit()); - var top = this.addUnitInput(div2, this.getUnit(), 20, 44, function() - { - topUpdate.apply(this, arguments); - }, this.getUnitStep(), null, null, this.isFloatUnit()); - - mxUtils.br(div2); - - this.addLabel(div2, mxResources.get('left'), 84); - this.addLabel(div2, mxResources.get('top'), 20); - - var listener = mxUtils.bind(this, function(sender, evt, force) - { - rect = this.format.getSelectionState(); - - if (!rect.containsLabel && rect.vertices.length == graph.getSelectionCount() && - rect.width != null && rect.height != null) - { - div.style.display = ''; - - if (force || document.activeElement != width) - { - width.value = this.inUnit(rect.width) + ((rect.width == '') ? '' : ' ' + this.getUnit()); - } - - if (force || document.activeElement != height) - { - height.value = this.inUnit(rect.height) + ((rect.height == '') ? '' : ' ' + this.getUnit()); - } - } - else - { - div.style.display = 'none'; - } - - if (rect.vertices.length == graph.getSelectionCount() && - rect.x != null && rect.y != null) - { - div2.style.display = ''; - - if (force || document.activeElement != left) - { - left.value = this.inUnit(rect.x) + ((rect.x == '') ? '' : ' ' + this.getUnit()); - } - - if (force || document.activeElement != top) - { - top.value = this.inUnit(rect.y) + ((rect.y == '') ? '' : ' ' + this.getUnit()); - } - } - else - { - div2.style.display = 'none'; - } - }); - - this.addKeyHandler(left, listener); - this.addKeyHandler(top, listener); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); - - leftUpdate = this.addGeometryHandler(left, function(geo, value) - { - value = panel.fromUnit(value); - - if (geo.relative) - { - geo.offset.x = value; - } - else - { - geo.x = value; - } - }); - topUpdate = this.addGeometryHandler(top, function(geo, value) - { - value = panel.fromUnit(value); - - if (geo.relative) - { - geo.offset.y = value; - } - else - { - geo.y = value; - } - }); - - if (rect.movable) - { - container.appendChild(div2); - } -}; - -/** - * - */ -ArrangePanel.prototype.addGeometryHandler = function(input, fn) -{ - var ui = this.editorUi; - var graph = ui.editor.graph; - var initialValue = null; - var panel = this; - - function update(evt) - { - if (input.value != '') - { - var value = parseFloat(input.value); - - if (isNaN(value)) - { - input.value = initialValue + ' ' + panel.getUnit(); - } - else if (value != initialValue) - { - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - - for (var i = 0; i < cells.length; i++) - { - if (graph.getModel().isVertex(cells[i])) - { - var geo = graph.getCellGeometry(cells[i]); - - if (geo != null) - { - geo = geo.clone(); - - if (!fn(geo, value, cells[i])) - { - var state = graph.view.getState(cells[i]); - - if (state != null && graph.isRecursiveVertexResize(state)) - { - graph.resizeChildCells(cells[i], geo); - } - - graph.getModel().setGeometry(cells[i], geo); - graph.constrainChildCells(cells[i]); - } - } - } - } - } - finally - { - graph.getModel().endUpdate(); - } - - initialValue = value; - input.value = value + ' ' + panel.getUnit(); - } - } - - mxEvent.consume(evt); - }; - - mxEvent.addListener(input, 'blur', update); - mxEvent.addListener(input, 'change', update); - mxEvent.addListener(input, 'focus', function() - { - initialValue = input.value; - }); - - return update; -}; - -ArrangePanel.prototype.addEdgeGeometryHandler = function(input, fn) -{ - var ui = this.editorUi; - var graph = ui.editor.graph; - var initialValue = null; - - function update(evt) - { - if (input.value != '') - { - var value = parseFloat(input.value); - - if (isNaN(value)) - { - input.value = initialValue + ' pt'; - } - else if (value != initialValue) - { - graph.getModel().beginUpdate(); - try - { - var cells = graph.getSelectionCells(); - - for (var i = 0; i < cells.length; i++) - { - if (graph.getModel().isEdge(cells[i])) - { - var geo = graph.getCellGeometry(cells[i]); - - if (geo != null) - { - geo = geo.clone(); - fn(geo, value); - - graph.getModel().setGeometry(cells[i], geo); - } - } - } - } - finally - { - graph.getModel().endUpdate(); - } - - initialValue = value; - input.value = value + ' pt'; - } - } - - mxEvent.consume(evt); - }; - - mxEvent.addListener(input, 'blur', update); - mxEvent.addListener(input, 'change', update); - mxEvent.addListener(input, 'focus', function() - { - initialValue = input.value; - }); - - return update; -}; - -/** - * - */ -ArrangePanel.prototype.addEdgeGeometry = function(container) -{ - var ui = this.editorUi; - var graph = ui.editor.graph; - var rect = this.format.getSelectionState(); - - var div = this.createPanel(); - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.width = '70px'; - span.style.marginTop = '0px'; - span.style.fontWeight = 'bold'; - mxUtils.write(span, mxResources.get('width')); - div.appendChild(span); - - var widthUpdate, xtUpdate, ytUpdate, xsUpdate, ysUpdate; - var width = this.addUnitInput(div, 'pt', 20, 44, function() - { - widthUpdate.apply(this, arguments); - }); - - mxUtils.br(div); - this.addKeyHandler(width, listener); - - function widthUpdate(evt) - { - // Maximum stroke width is 999 - var value = parseInt(width.value); - value = Math.min(999, Math.max(1, (isNaN(value)) ? 1 : value)); - - if (value != mxUtils.getValue(rect.style, 'width', mxCellRenderer.defaultShapes['flexArrow'].prototype.defaultWidth)) - { - graph.setCellStyles('width', value, graph.getSelectionCells()); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', ['width'], - 'values', [value], 'cells', graph.getSelectionCells())); - } - - width.value = value + ' pt'; - mxEvent.consume(evt); - }; - - mxEvent.addListener(width, 'blur', widthUpdate); - mxEvent.addListener(width, 'change', widthUpdate); - - container.appendChild(div); - - var divs = this.createPanel(); - divs.style.paddingBottom = '30px'; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.width = '70px'; - span.style.marginTop = '0px'; - span.style.fontWeight = 'bold'; - mxUtils.write(span, 'Start'); - divs.appendChild(span); - - var xs = this.addUnitInput(divs, 'pt', 84, 44, function() - { - xsUpdate.apply(this, arguments); - }); - var ys = this.addUnitInput(divs, 'pt', 20, 44, function() - { - ysUpdate.apply(this, arguments); - }); - - mxUtils.br(divs); - this.addLabel(divs, mxResources.get('left'), 84); - this.addLabel(divs, mxResources.get('top'), 20); - container.appendChild(divs); - this.addKeyHandler(xs, listener); - this.addKeyHandler(ys, listener); - - var divt = this.createPanel(); - divt.style.paddingBottom = '30px'; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.width = '70px'; - span.style.marginTop = '0px'; - span.style.fontWeight = 'bold'; - mxUtils.write(span, 'End'); - divt.appendChild(span); - - var xt = this.addUnitInput(divt, 'pt', 84, 44, function() - { - xtUpdate.apply(this, arguments); - }); - var yt = this.addUnitInput(divt, 'pt', 20, 44, function() - { - ytUpdate.apply(this, arguments); - }); - - mxUtils.br(divt); - this.addLabel(divt, mxResources.get('left'), 84); - this.addLabel(divt, mxResources.get('top'), 20); - container.appendChild(divt); - this.addKeyHandler(xt, listener); - this.addKeyHandler(yt, listener); - - var listener = mxUtils.bind(this, function(sender, evt, force) - { - rect = this.format.getSelectionState(); - var cell = graph.getSelectionCell(); - - if (rect.style.shape == 'link' || rect.style.shape == 'flexArrow') - { - div.style.display = ''; - - if (force || document.activeElement != width) - { - var value = mxUtils.getValue(rect.style, 'width', - mxCellRenderer.defaultShapes['flexArrow'].prototype.defaultWidth); - width.value = value + ' pt'; - } - } - else - { - div.style.display = 'none'; - } - - if (graph.getSelectionCount() == 1 && graph.model.isEdge(cell)) - { - var geo = graph.model.getGeometry(cell); - - if (geo.sourcePoint != null && graph.model.getTerminal(cell, true) == null) - { - xs.value = geo.sourcePoint.x; - ys.value = geo.sourcePoint.y; - } - else - { - divs.style.display = 'none'; - } - - if (geo.targetPoint != null && graph.model.getTerminal(cell, false) == null) - { - xt.value = geo.targetPoint.x; - yt.value = geo.targetPoint.y; - } - else - { - divt.style.display = 'none'; - } - } - else - { - divs.style.display = 'none'; - divt.style.display = 'none'; - } - }); - - xsUpdate = this.addEdgeGeometryHandler(xs, function(geo, value) - { - geo.sourcePoint.x = value; - }); - - ysUpdate = this.addEdgeGeometryHandler(ys, function(geo, value) - { - geo.sourcePoint.y = value; - }); - - xtUpdate = this.addEdgeGeometryHandler(xt, function(geo, value) - { - geo.targetPoint.x = value; - }); - - ytUpdate = this.addEdgeGeometryHandler(yt, function(geo, value) - { - geo.targetPoint.y = value; - }); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -TextFormatPanel = function(format, editorUi, container) -{ - BaseFormatPanel.call(this, format, editorUi, container); - this.init(); -}; - -mxUtils.extend(TextFormatPanel, BaseFormatPanel); - -/** - * Adds the label menu items to the given menu and parent. - */ -TextFormatPanel.prototype.init = function() -{ - this.container.style.borderBottom = 'none'; - this.addFont(this.container); -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -TextFormatPanel.prototype.addFont = function(container) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - var ss = this.format.getSelectionState(); - - var title = this.createTitle(mxResources.get('font')); - title.style.paddingLeft = '18px'; - title.style.paddingTop = '10px'; - title.style.paddingBottom = '6px'; - container.appendChild(title); - - var stylePanel = this.createPanel(); - stylePanel.style.paddingTop = '2px'; - stylePanel.style.paddingBottom = '2px'; - stylePanel.style.position = 'relative'; - stylePanel.style.marginLeft = '-2px'; - stylePanel.style.borderWidth = '0px'; - stylePanel.className = 'geToolbarContainer'; - - if (mxClient.IS_QUIRKS) - { - stylePanel.style.display = 'block'; - } - - if (graph.cellEditor.isContentEditing()) - { - var cssPanel = stylePanel.cloneNode(); - - var cssMenu = this.editorUi.toolbar.addMenu(mxResources.get('style'), - mxResources.get('style'), true, 'formatBlock', cssPanel, null, true); - cssMenu.style.color = 'rgb(112, 112, 112)'; - cssMenu.style.whiteSpace = 'nowrap'; - cssMenu.style.overflow = 'hidden'; - cssMenu.style.margin = '0px'; - this.addArrow(cssMenu); - cssMenu.style.width = '192px'; - cssMenu.style.height = '15px'; - - var arrow = cssMenu.getElementsByTagName('div')[0]; - arrow.style.cssFloat = 'right'; - container.appendChild(cssPanel); - } - - container.appendChild(stylePanel); - - var colorPanel = this.createPanel(); - colorPanel.style.marginTop = '8px'; - colorPanel.style.borderTop = '1px solid #c0c0c0'; - colorPanel.style.paddingTop = '6px'; - colorPanel.style.paddingBottom = '6px'; - - var fontMenu = this.editorUi.toolbar.addMenu('Helvetica', mxResources.get('fontFamily'), - true, 'fontFamily', stylePanel, null, true); - fontMenu.style.color = 'rgb(112, 112, 112)'; - fontMenu.style.whiteSpace = 'nowrap'; - fontMenu.style.overflow = 'hidden'; - fontMenu.style.margin = '0px'; - - this.addArrow(fontMenu); - fontMenu.style.width = '192px'; - fontMenu.style.height = '15px'; - - var stylePanel2 = stylePanel.cloneNode(false); - stylePanel2.style.marginLeft = '-3px'; - var fontStyleItems = this.editorUi.toolbar.addItems(['bold', 'italic', 'underline'], stylePanel2, true); - fontStyleItems[0].setAttribute('title', mxResources.get('bold') + ' (' + this.editorUi.actions.get('bold').shortcut + ')'); - fontStyleItems[1].setAttribute('title', mxResources.get('italic') + ' (' + this.editorUi.actions.get('italic').shortcut + ')'); - fontStyleItems[2].setAttribute('title', mxResources.get('underline') + ' (' + this.editorUi.actions.get('underline').shortcut + ')'); - - var verticalItem = this.editorUi.toolbar.addItems(['vertical'], stylePanel2, true)[0]; - - if (mxClient.IS_QUIRKS) - { - mxUtils.br(container); - } - - container.appendChild(stylePanel2); - - this.styleButtons(fontStyleItems); - this.styleButtons([verticalItem]); - - var stylePanel3 = stylePanel.cloneNode(false); - stylePanel3.style.marginLeft = '-3px'; - stylePanel3.style.paddingBottom = '0px'; - - // Helper function to return a wrapper function does not pass any arguments - var callFn = function(fn) - { - return function() - { - return fn(); - }; - }; - - var left = this.editorUi.toolbar.addButton('geSprite-left', mxResources.get('left'), - (graph.cellEditor.isContentEditing()) ? - function(evt) - { - graph.cellEditor.alignText(mxConstants.ALIGN_LEFT, evt); - } : callFn(this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_LEFT])), stylePanel3); - var center = this.editorUi.toolbar.addButton('geSprite-center', mxResources.get('center'), - (graph.cellEditor.isContentEditing()) ? - function(evt) - { - graph.cellEditor.alignText(mxConstants.ALIGN_CENTER, evt); - } : callFn(this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_CENTER])), stylePanel3); - var right = this.editorUi.toolbar.addButton('geSprite-right', mxResources.get('right'), - (graph.cellEditor.isContentEditing()) ? - function(evt) - { - graph.cellEditor.alignText(mxConstants.ALIGN_RIGHT, evt); - } : callFn(this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_ALIGN], [mxConstants.ALIGN_RIGHT])), stylePanel3); - - this.styleButtons([left, center, right]); - - // Quick hack for strikethrough - // TODO: Add translations and toggle state - if (graph.cellEditor.isContentEditing()) - { - var strike = this.editorUi.toolbar.addButton('geSprite-removeformat', mxResources.get('strikethrough'), - function() - { - document.execCommand('strikeThrough', false, null); - }, stylePanel2); - this.styleButtons([strike]); - - strike.firstChild.style.background = 'url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PGRlZnM+PHBhdGggaWQ9ImEiIGQ9Ik0wIDBoMjR2MjRIMFYweiIvPjwvZGVmcz48Y2xpcFBhdGggaWQ9ImIiPjx1c2UgeGxpbms6aHJlZj0iI2EiIG92ZXJmbG93PSJ2aXNpYmxlIi8+PC9jbGlwUGF0aD48cGF0aCBjbGlwLXBhdGg9InVybCgjYikiIGZpbGw9IiMwMTAxMDEiIGQ9Ik03LjI0IDguNzVjLS4yNi0uNDgtLjM5LTEuMDMtLjM5LTEuNjcgMC0uNjEuMTMtMS4xNi40LTEuNjcuMjYtLjUuNjMtLjkzIDEuMTEtMS4yOS40OC0uMzUgMS4wNS0uNjMgMS43LS44My42Ni0uMTkgMS4zOS0uMjkgMi4xOC0uMjkuODEgMCAxLjU0LjExIDIuMjEuMzQuNjYuMjIgMS4yMy41NCAxLjY5Ljk0LjQ3LjQuODMuODggMS4wOCAxLjQzLjI1LjU1LjM4IDEuMTUuMzggMS44MWgtMy4wMWMwLS4zMS0uMDUtLjU5LS4xNS0uODUtLjA5LS4yNy0uMjQtLjQ5LS40NC0uNjgtLjItLjE5LS40NS0uMzMtLjc1LS40NC0uMy0uMS0uNjYtLjE2LTEuMDYtLjE2LS4zOSAwLS43NC4wNC0xLjAzLjEzLS4yOS4wOS0uNTMuMjEtLjcyLjM2LS4xOS4xNi0uMzQuMzQtLjQ0LjU1LS4xLjIxLS4xNS40My0uMTUuNjYgMCAuNDguMjUuODguNzQgMS4yMS4zOC4yNS43Ny40OCAxLjQxLjdINy4zOWMtLjA1LS4wOC0uMTEtLjE3LS4xNS0uMjV6TTIxIDEydi0ySDN2Mmg5LjYyYy4xOC4wNy40LjE0LjU1LjIuMzcuMTcuNjYuMzQuODcuNTEuMjEuMTcuMzUuMzYuNDMuNTcuMDcuMi4xMS40My4xMS42OSAwIC4yMy0uMDUuNDUtLjE0LjY2LS4wOS4yLS4yMy4zOC0uNDIuNTMtLjE5LjE1LS40Mi4yNi0uNzEuMzUtLjI5LjA4LS42My4xMy0xLjAxLjEzLS40MyAwLS44My0uMDQtMS4xOC0uMTNzLS42Ni0uMjMtLjkxLS40MmMtLjI1LS4xOS0uNDUtLjQ0LS41OS0uNzUtLjE0LS4zMS0uMjUtLjc2LS4yNS0xLjIxSDYuNGMwIC41NS4wOCAxLjEzLjI0IDEuNTguMTYuNDUuMzcuODUuNjUgMS4yMS4yOC4zNS42LjY2Ljk4LjkyLjM3LjI2Ljc4LjQ4IDEuMjIuNjUuNDQuMTcuOS4zIDEuMzguMzkuNDguMDguOTYuMTMgMS40NC4xMy44IDAgMS41My0uMDkgMi4xOC0uMjhzMS4yMS0uNDUgMS42Ny0uNzljLjQ2LS4zNC44Mi0uNzcgMS4wNy0xLjI3cy4zOC0xLjA3LjM4LTEuNzFjMC0uNi0uMS0xLjE0LS4zMS0xLjYxLS4wNS0uMTEtLjExLS4yMy0uMTctLjMzSDIxeiIvPjwvc3ZnPg==)'; - strike.firstChild.style.backgroundPosition = '2px 2px'; - strike.firstChild.style.backgroundSize = '18px 18px'; - - this.styleButtons([strike]); - } - - var top = this.editorUi.toolbar.addButton('geSprite-top', mxResources.get('top'), - callFn(this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_TOP])), stylePanel3); - var middle = this.editorUi.toolbar.addButton('geSprite-middle', mxResources.get('middle'), - callFn(this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_MIDDLE])), stylePanel3); - var bottom = this.editorUi.toolbar.addButton('geSprite-bottom', mxResources.get('bottom'), - callFn(this.editorUi.menus.createStyleChangeFunction([mxConstants.STYLE_VERTICAL_ALIGN], [mxConstants.ALIGN_BOTTOM])), stylePanel3); - - this.styleButtons([top, middle, bottom]); - - if (mxClient.IS_QUIRKS) - { - mxUtils.br(container); - } - - container.appendChild(stylePanel3); - - // Hack for updating UI state below based on current text selection - // currentTable is the current selected DOM table updated below - var sub, sup, full, tableWrapper, currentTable, tableCell, tableRow; - - if (graph.cellEditor.isContentEditing()) - { - top.style.display = 'none'; - middle.style.display = 'none'; - bottom.style.display = 'none'; - verticalItem.style.display = 'none'; - - full = this.editorUi.toolbar.addButton('geSprite-justifyfull', mxResources.get('block'), - function() - { - if (full.style.opacity == 1) - { - document.execCommand('justifyfull', false, null); - } - }, stylePanel3); - full.style.marginRight = '9px'; - full.style.opacity = 1; - - this.styleButtons([full, - sub = this.editorUi.toolbar.addButton('geSprite-subscript', - mxResources.get('subscript') + ' (' + Editor.ctrlKey + '+,)', - function() - { - document.execCommand('subscript', false, null); - }, stylePanel3), sup = this.editorUi.toolbar.addButton('geSprite-superscript', - mxResources.get('superscript') + ' (' + Editor.ctrlKey + '+.)', - function() - { - document.execCommand('superscript', false, null); - }, stylePanel3)]); - sub.style.marginLeft = '9px'; - - var tmp = stylePanel3.cloneNode(false); - tmp.style.paddingTop = '4px'; - var btns = [this.editorUi.toolbar.addButton('geSprite-orderedlist', mxResources.get('numberedList'), - function() - { - document.execCommand('insertorderedlist', false, null); - }, tmp), - this.editorUi.toolbar.addButton('geSprite-unorderedlist', mxResources.get('bulletedList'), - function() - { - document.execCommand('insertunorderedlist', false, null); - }, tmp), - this.editorUi.toolbar.addButton('geSprite-outdent', mxResources.get('decreaseIndent'), - function() - { - document.execCommand('outdent', false, null); - }, tmp), - this.editorUi.toolbar.addButton('geSprite-indent', mxResources.get('increaseIndent'), - function() - { - document.execCommand('indent', false, null); - }, tmp), - this.editorUi.toolbar.addButton('geSprite-removeformat', mxResources.get('removeFormat'), - function() - { - document.execCommand('removeformat', false, null); - }, tmp), - this.editorUi.toolbar.addButton('geSprite-code', mxResources.get('html'), - function() - { - graph.cellEditor.toggleViewMode(); - }, tmp)]; - this.styleButtons(btns); - btns[btns.length - 2].style.marginLeft = '9px'; - - if (mxClient.IS_QUIRKS) - { - mxUtils.br(container); - tmp.style.height = '40'; - } - - container.appendChild(tmp); - } - else - { - fontStyleItems[2].style.marginRight = '9px'; - right.style.marginRight = '9px'; - } - - // Label position - var stylePanel4 = stylePanel.cloneNode(false); - stylePanel4.style.marginLeft = '0px'; - stylePanel4.style.paddingTop = '8px'; - stylePanel4.style.paddingBottom = '4px'; - stylePanel4.style.fontWeight = 'normal'; - - mxUtils.write(stylePanel4, mxResources.get('position')); - - // Adds label position options - var positionSelect = document.createElement('select'); - positionSelect.style.position = 'absolute'; - positionSelect.style.right = '20px'; - positionSelect.style.width = '97px'; - positionSelect.style.marginTop = '-2px'; - - var directions = ['topLeft', 'top', 'topRight', 'left', 'center', 'right', 'bottomLeft', 'bottom', 'bottomRight']; - var lset = {'topLeft': [mxConstants.ALIGN_LEFT, mxConstants.ALIGN_TOP, mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_BOTTOM], - 'top': [mxConstants.ALIGN_CENTER, mxConstants.ALIGN_TOP, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_BOTTOM], - 'topRight': [mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_TOP, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_BOTTOM], - 'left': [mxConstants.ALIGN_LEFT, mxConstants.ALIGN_MIDDLE, mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_MIDDLE], - 'center': [mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE], - 'right': [mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_MIDDLE, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_MIDDLE], - 'bottomLeft': [mxConstants.ALIGN_LEFT, mxConstants.ALIGN_BOTTOM, mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_TOP], - 'bottom': [mxConstants.ALIGN_CENTER, mxConstants.ALIGN_BOTTOM, mxConstants.ALIGN_CENTER, mxConstants.ALIGN_TOP], - 'bottomRight': [mxConstants.ALIGN_RIGHT, mxConstants.ALIGN_BOTTOM, mxConstants.ALIGN_LEFT, mxConstants.ALIGN_TOP]}; - - for (var i = 0; i < directions.length; i++) - { - var positionOption = document.createElement('option'); - positionOption.setAttribute('value', directions[i]); - mxUtils.write(positionOption, mxResources.get(directions[i])); - positionSelect.appendChild(positionOption); - } - - stylePanel4.appendChild(positionSelect); - - // Writing direction - var stylePanel5 = stylePanel.cloneNode(false); - stylePanel5.style.marginLeft = '0px'; - stylePanel5.style.paddingTop = '4px'; - stylePanel5.style.paddingBottom = '4px'; - stylePanel5.style.fontWeight = 'normal'; - - mxUtils.write(stylePanel5, mxResources.get('writingDirection')); - - // Adds writing direction options - // LATER: Handle reselect of same option in all selects (change event - // is not fired for same option so have opened state on click) and - // handle multiple different styles for current selection - var dirSelect = document.createElement('select'); - dirSelect.style.position = 'absolute'; - dirSelect.style.right = '20px'; - dirSelect.style.width = '97px'; - dirSelect.style.marginTop = '-2px'; - - // NOTE: For automatic we use the value null since automatic - // requires the text to be non formatted and non-wrapped - var dirs = ['automatic', 'leftToRight', 'rightToLeft']; - var dirSet = {'automatic': null, - 'leftToRight': mxConstants.TEXT_DIRECTION_LTR, - 'rightToLeft': mxConstants.TEXT_DIRECTION_RTL}; - - for (var i = 0; i < dirs.length; i++) - { - var dirOption = document.createElement('option'); - dirOption.setAttribute('value', dirs[i]); - mxUtils.write(dirOption, mxResources.get(dirs[i])); - dirSelect.appendChild(dirOption); - } - - stylePanel5.appendChild(dirSelect); - - if (!graph.isEditing()) - { - container.appendChild(stylePanel4); - - mxEvent.addListener(positionSelect, 'change', function(evt) - { - graph.getModel().beginUpdate(); - try - { - var vals = lset[positionSelect.value]; - - if (vals != null) - { - graph.setCellStyles(mxConstants.STYLE_LABEL_POSITION, vals[0], graph.getSelectionCells()); - graph.setCellStyles(mxConstants.STYLE_VERTICAL_LABEL_POSITION, vals[1], graph.getSelectionCells()); - graph.setCellStyles(mxConstants.STYLE_ALIGN, vals[2], graph.getSelectionCells()); - graph.setCellStyles(mxConstants.STYLE_VERTICAL_ALIGN, vals[3], graph.getSelectionCells()); - } - } - finally - { - graph.getModel().endUpdate(); - } - - mxEvent.consume(evt); - }); - - // LATER: Update dir in text editor while editing and update style with label - // NOTE: The tricky part is handling and passing on the auto value - container.appendChild(stylePanel5); - - mxEvent.addListener(dirSelect, 'change', function(evt) - { - graph.setCellStyles(mxConstants.STYLE_TEXT_DIRECTION, dirSet[dirSelect.value], graph.getSelectionCells()); - mxEvent.consume(evt); - }); - } - - // Font size - var input = document.createElement('input'); - input.style.textAlign = 'right'; - input.style.marginTop = '4px'; - - if (!mxClient.IS_QUIRKS) - { - input.style.position = 'absolute'; - input.style.right = '32px'; - } - - input.style.width = '40px'; - input.style.height = (mxClient.IS_QUIRKS) ? '21px' : '17px'; - stylePanel2.appendChild(input); - - // Workaround for font size 4 if no text is selected is update font size below - // after first character was entered (as the font element is lazy created) - var pendingFontSize = null; - - var inputUpdate = this.installInputHandler(input, mxConstants.STYLE_FONTSIZE, Menus.prototype.defaultFontSize, 1, 999, ' pt', - function(fontSize) - { - // IE does not support containsNode - // KNOWN: Fixes font size issues but bypasses undo - if (window.getSelection && !mxClient.IS_IE && !mxClient.IS_IE11) - { - var selection = window.getSelection(); - var container = (selection.rangeCount > 0) ? selection.getRangeAt(0).commonAncestorContainer : - graph.cellEditor.textarea; - - function updateSize(elt, ignoreContains) - { - if (graph.cellEditor.textarea != null && elt != graph.cellEditor.textarea && - graph.cellEditor.textarea.contains(elt) && - (ignoreContains || selection.containsNode(elt, true))) - { - if (elt.nodeName == 'FONT') - { - elt.removeAttribute('size'); - elt.style.fontSize = fontSize + 'px'; - } - else - { - var css = mxUtils.getCurrentStyle(elt); - - if (css.fontSize != fontSize + 'px') - { - if (mxUtils.getCurrentStyle(elt.parentNode).fontSize != fontSize + 'px') - { - elt.style.fontSize = fontSize + 'px'; - } - else - { - elt.style.fontSize = ''; - } - } - } - } - }; - - // Wraps text node or mixed selection with leading text in a font element - if (container == graph.cellEditor.textarea || - container.nodeType != mxConstants.NODETYPE_ELEMENT) - { - document.execCommand('fontSize', false, '1'); - } - - if (container != graph.cellEditor.textarea) - { - container = container.parentNode; - } - - if (container != null && container.nodeType == mxConstants.NODETYPE_ELEMENT) - { - var elts = container.getElementsByTagName('*'); - updateSize(container); - - for (var i = 0; i < elts.length; i++) - { - updateSize(elts[i]); - } - } - - input.value = fontSize + ' pt'; - } - else if (window.getSelection || document.selection) - { - // Checks selection - var par = null; - - if (document.selection) - { - par = document.selection.createRange().parentElement(); - } - else - { - var selection = window.getSelection(); - - if (selection.rangeCount > 0) - { - par = selection.getRangeAt(0).commonAncestorContainer; - } - } - - // Node.contains does not work for text nodes in IE11 - function isOrContains(container, node) - { - while (node != null) - { - if (node === container) - { - return true; - } - - node = node.parentNode; - } - - return false; - }; - - if (par != null && isOrContains(graph.cellEditor.textarea, par)) - { - pendingFontSize = fontSize; - - // Workaround for can't set font size in px is to change font size afterwards - document.execCommand('fontSize', false, '4'); - var elts = graph.cellEditor.textarea.getElementsByTagName('font'); - - for (var i = 0; i < elts.length; i++) - { - if (elts[i].getAttribute('size') == '4') - { - elts[i].removeAttribute('size'); - elts[i].style.fontSize = pendingFontSize + 'px'; - - // Overrides fontSize in input with the one just assigned as a workaround - // for potential fontSize values of parent elements that don't match - window.setTimeout(function() - { - input.value = pendingFontSize + ' pt'; - pendingFontSize = null; - }, 0); - - break; - } - } - } - } - }, true); - - var stepper = this.createStepper(input, inputUpdate, 1, 10, true, Menus.prototype.defaultFontSize); - stepper.style.display = input.style.display; - stepper.style.marginTop = '4px'; - - if (!mxClient.IS_QUIRKS) - { - stepper.style.right = '20px'; - } - - stylePanel2.appendChild(stepper); - - var arrow = fontMenu.getElementsByTagName('div')[0]; - arrow.style.cssFloat = 'right'; - - var bgColorApply = null; - var currentBgColor = '#ffffff'; - - var fontColorApply = null; - var currentFontColor = '#000000'; - - var bgPanel = (graph.cellEditor.isContentEditing()) ? this.createColorOption(mxResources.get('backgroundColor'), function() - { - return currentBgColor; - }, function(color) - { - document.execCommand('backcolor', false, (color != mxConstants.NONE) ? color : 'transparent'); - }, '#ffffff', - { - install: function(apply) { bgColorApply = apply; }, - destroy: function() { bgColorApply = null; } - }, null, true) : this.createCellColorOption(mxResources.get('backgroundColor'), mxConstants.STYLE_LABEL_BACKGROUNDCOLOR, '#ffffff', null, function(color) - { - graph.updateLabelElements(graph.getSelectionCells(), function(elt) - { - elt.style.backgroundColor = null; - }); - }); - bgPanel.style.fontWeight = 'bold'; - - var borderPanel = this.createCellColorOption(mxResources.get('borderColor'), mxConstants.STYLE_LABEL_BORDERCOLOR, '#000000'); - borderPanel.style.fontWeight = 'bold'; - - var defs = (ss.vertices.length >= 1) ? graph.stylesheet.getDefaultVertexStyle() : graph.stylesheet.getDefaultEdgeStyle(); - var panel = (graph.cellEditor.isContentEditing()) ? this.createColorOption(mxResources.get('fontColor'), function() - { - return currentFontColor; - }, function(color) - { - if (mxClient.IS_FF) - { - // Workaround for Firefox that adds the font element around - // anchor elements which ignore inherited colors is to move - // the font element inside anchor elements - var tmp = graph.cellEditor.textarea.getElementsByTagName('font'); - var oldFonts = []; - - for (var i = 0; i < tmp.length; i++) - { - oldFonts.push( - { - node: tmp[i], - color: tmp[i].getAttribute('color') - }); - } - - document.execCommand('forecolor', false, (color != mxConstants.NONE) ? - color : 'transparent'); - - // Finds the new or changed font element - var newFonts = graph.cellEditor.textarea.getElementsByTagName('font'); - - for (var i = 0; i < newFonts.length; i++) - { - if (i >= oldFonts.length || newFonts[i] != oldFonts[i].node || - (newFonts[i] == oldFonts[i].node && - newFonts[i].getAttribute('color') != oldFonts[i].color)) - { - var child = newFonts[i].firstChild; - - // Moves the font element to inside the anchor element and adopts all children - if (child != null && child.nodeName == 'A' && child.nextSibling == - null && - child.firstChild != null) - { - var parent = newFonts[i].parentNode; - parent.insertBefore(child, newFonts[i]); - var tmp = child.firstChild; - - while (tmp != null) - { - var next = tmp.nextSibling; - newFonts[i].appendChild(tmp); - tmp = next; - } - - child.appendChild(newFonts[i]); - } - - break; - } - } - } - else - { - document.execCommand('forecolor', false, (color != mxConstants.NONE) ? - color : 'transparent'); - } - }, (defs[mxConstants.STYLE_FONTCOLOR] != null) ? defs[mxConstants.STYLE_FONTCOLOR] : '#000000', - { - install: function(apply) { fontColorApply = apply; }, - destroy: function() { fontColorApply = null; } - }, null, true) : this.createCellColorOption(mxResources.get('fontColor'), mxConstants.STYLE_FONTCOLOR, - (defs[mxConstants.STYLE_FONTCOLOR] != null) ? defs[mxConstants.STYLE_FONTCOLOR] : '#000000', function(color) - { - if (color == mxConstants.NONE) - { - bgPanel.style.display = 'none'; - } - else - { - bgPanel.style.display = ''; - } - - borderPanel.style.display = bgPanel.style.display; - }, function(color) - { - if (color == mxConstants.NONE) - { - graph.setCellStyles(mxConstants.STYLE_NOLABEL, '1', graph.getSelectionCells()); - } - else - { - graph.setCellStyles(mxConstants.STYLE_NOLABEL, null, graph.getSelectionCells()); - } - - graph.updateCellStyles(mxConstants.STYLE_FONTCOLOR, color, graph.getSelectionCells()); - - graph.updateLabelElements(graph.getSelectionCells(), function(elt) - { - elt.removeAttribute('color'); - elt.style.color = null; - }); - }); - panel.style.fontWeight = 'bold'; - - colorPanel.appendChild(panel); - colorPanel.appendChild(bgPanel); - - if (!graph.cellEditor.isContentEditing()) - { - colorPanel.appendChild(borderPanel); - } - - container.appendChild(colorPanel); - - var extraPanel = this.createPanel(); - extraPanel.style.paddingTop = '2px'; - extraPanel.style.paddingBottom = '4px'; - - // LATER: Fix toggle using '' instead of 'null' - var wwOpt = this.createCellOption(mxResources.get('wordWrap'), mxConstants.STYLE_WHITE_SPACE, null, 'wrap', 'null', null, null, true); - wwOpt.style.fontWeight = 'bold'; - - // Word wrap in edge labels only supported via labelWidth style - if (!ss.containsLabel && !ss.autoSize && ss.edges.length == 0) - { - extraPanel.appendChild(wwOpt); - } - - // Delegates switch of style to formattedText action as it also convertes newlines - var htmlOpt = this.createCellOption(mxResources.get('formattedText'), 'html', '0', - null, null, null, ui.actions.get('formattedText')); - htmlOpt.style.fontWeight = 'bold'; - extraPanel.appendChild(htmlOpt); - - var spacingPanel = this.createPanel(); - spacingPanel.style.paddingTop = '10px'; - spacingPanel.style.paddingBottom = '28px'; - spacingPanel.style.fontWeight = 'normal'; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.width = '70px'; - span.style.marginTop = '0px'; - span.style.fontWeight = 'bold'; - mxUtils.write(span, mxResources.get('spacing')); - spacingPanel.appendChild(span); - - var topUpdate, globalUpdate, leftUpdate, bottomUpdate, rightUpdate; - var topSpacing = this.addUnitInput(spacingPanel, 'pt', 91, 44, function() - { - topUpdate.apply(this, arguments); - }); - var globalSpacing = this.addUnitInput(spacingPanel, 'pt', 20, 44, function() - { - globalUpdate.apply(this, arguments); - }); - - mxUtils.br(spacingPanel); - this.addLabel(spacingPanel, mxResources.get('top'), 91); - this.addLabel(spacingPanel, mxResources.get('global'), 20); - mxUtils.br(spacingPanel); - mxUtils.br(spacingPanel); - - var leftSpacing = this.addUnitInput(spacingPanel, 'pt', 162, 44, function() - { - leftUpdate.apply(this, arguments); - }); - var bottomSpacing = this.addUnitInput(spacingPanel, 'pt', 91, 44, function() - { - bottomUpdate.apply(this, arguments); - }); - var rightSpacing = this.addUnitInput(spacingPanel, 'pt', 20, 44, function() - { - rightUpdate.apply(this, arguments); - }); - - mxUtils.br(spacingPanel); - this.addLabel(spacingPanel, mxResources.get('left'), 162); - this.addLabel(spacingPanel, mxResources.get('bottom'), 91); - this.addLabel(spacingPanel, mxResources.get('right'), 20); - - if (!graph.cellEditor.isContentEditing()) - { - container.appendChild(extraPanel); - container.appendChild(this.createRelativeOption(mxResources.get('opacity'), mxConstants.STYLE_TEXT_OPACITY)); - container.appendChild(spacingPanel); - } - else - { - var selState = null; - var lineHeightInput = null; - - container.appendChild(this.createRelativeOption(mxResources.get('lineheight'), null, null, function(input) - { - var value = (input.value == '') ? 120 : parseInt(input.value); - value = Math.max(0, (isNaN(value)) ? 120 : value); - - if (selState != null) - { - graph.cellEditor.restoreSelection(selState); - selState = null; - } - - var selectedElement = graph.getSelectedElement(); - var node = selectedElement; - - while (node != null && node.nodeType != mxConstants.NODETYPE_ELEMENT) - { - node = node.parentNode; - } - - if (node != null && node == graph.cellEditor.textarea && graph.cellEditor.textarea.firstChild != null) - { - if (graph.cellEditor.textarea.firstChild.nodeName != 'P') - { - graph.cellEditor.textarea.innerHTML = '

' + graph.cellEditor.textarea.innerHTML + '

'; - } - - node = graph.cellEditor.textarea.firstChild; - } - - if (node != null && graph.cellEditor.textarea != null && node != graph.cellEditor.textarea && - graph.cellEditor.textarea.contains(node)) - { - node.style.lineHeight = value + '%'; - } - - input.value = value + ' %'; - }, function(input) - { - // Used in CSS handler to update current value - lineHeightInput = input; - - // KNOWN: Arrow up/down clear selection text in quirks/IE 8 - // Text size via arrow button limits to 16 in IE11. Why? - mxEvent.addListener(input, 'mousedown', function() - { - if (document.activeElement == graph.cellEditor.textarea) - { - selState = graph.cellEditor.saveSelection(); - } - }); - - mxEvent.addListener(input, 'touchstart', function() - { - if (document.activeElement == graph.cellEditor.textarea) - { - selState = graph.cellEditor.saveSelection(); - } - }); - - input.value = '120 %'; - })); - - var insertPanel = stylePanel.cloneNode(false); - insertPanel.style.paddingLeft = '0px'; - var insertBtns = this.editorUi.toolbar.addItems(['link', 'image'], insertPanel, true); - - var btns = [ - this.editorUi.toolbar.addButton('geSprite-horizontalrule', mxResources.get('insertHorizontalRule'), - function() - { - document.execCommand('inserthorizontalrule', false); - }, insertPanel), - this.editorUi.toolbar.addMenuFunctionInContainer(insertPanel, 'geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function(menu) - { - this.editorUi.menus.addInsertTableItem(menu); - }))]; - this.styleButtons(insertBtns); - this.styleButtons(btns); - - var wrapper2 = this.createPanel(); - wrapper2.style.paddingTop = '10px'; - wrapper2.style.paddingBottom = '10px'; - wrapper2.appendChild(this.createTitle(mxResources.get('insert'))); - wrapper2.appendChild(insertPanel); - container.appendChild(wrapper2); - - if (mxClient.IS_QUIRKS) - { - wrapper2.style.height = '70'; - } - - var tablePanel = stylePanel.cloneNode(false); - tablePanel.style.paddingLeft = '0px'; - - var btns = [ - this.editorUi.toolbar.addButton('geSprite-insertcolumnbefore', mxResources.get('insertColumnBefore'), - mxUtils.bind(this, function() - { - try - { - if (currentTable != null) - { - graph.insertColumn(currentTable, (tableCell != null) ? tableCell.cellIndex : 0); - } - } - catch (e) - { - this.editorUi.handleError(e); - } - }), tablePanel), - this.editorUi.toolbar.addButton('geSprite-insertcolumnafter', mxResources.get('insertColumnAfter'), - mxUtils.bind(this, function() - { - try - { - if (currentTable != null) - { - graph.insertColumn(currentTable, (tableCell != null) ? tableCell.cellIndex + 1 : -1); - } - } - catch (e) - { - this.editorUi.handleError(e); - } - }), tablePanel), - this.editorUi.toolbar.addButton('geSprite-deletecolumn', mxResources.get('deleteColumn'), - mxUtils.bind(this, function() - { - try - { - if (currentTable != null && tableCell != null) - { - graph.deleteColumn(currentTable, tableCell.cellIndex); - } - } - catch (e) - { - this.editorUi.handleError(e); - } - }), tablePanel), - this.editorUi.toolbar.addButton('geSprite-insertrowbefore', mxResources.get('insertRowBefore'), - mxUtils.bind(this, function() - { - try - { - if (currentTable != null && tableRow != null) - { - graph.insertRow(currentTable, tableRow.sectionRowIndex); - } - } - catch (e) - { - this.editorUi.handleError(e); - } - }), tablePanel), - this.editorUi.toolbar.addButton('geSprite-insertrowafter', mxResources.get('insertRowAfter'), - mxUtils.bind(this, function() - { - try - { - if (currentTable != null && tableRow != null) - { - graph.insertRow(currentTable, tableRow.sectionRowIndex + 1); - } - } - catch (e) - { - this.editorUi.handleError(e); - } - }), tablePanel), - this.editorUi.toolbar.addButton('geSprite-deleterow', mxResources.get('deleteRow'), - mxUtils.bind(this, function() - { - try - { - if (currentTable != null && tableRow != null) - { - graph.deleteRow(currentTable, tableRow.sectionRowIndex); - } - } - catch (e) - { - this.editorUi.handleError(e); - } - }), tablePanel)]; - this.styleButtons(btns); - btns[2].style.marginRight = '9px'; - - var wrapper3 = this.createPanel(); - wrapper3.style.paddingTop = '10px'; - wrapper3.style.paddingBottom = '10px'; - wrapper3.appendChild(this.createTitle(mxResources.get('table'))); - wrapper3.appendChild(tablePanel); - - if (mxClient.IS_QUIRKS) - { - mxUtils.br(container); - wrapper3.style.height = '70'; - } - - var tablePanel2 = stylePanel.cloneNode(false); - tablePanel2.style.paddingLeft = '0px'; - - var btns = [ - this.editorUi.toolbar.addButton('geSprite-strokecolor', mxResources.get('borderColor'), - mxUtils.bind(this, function(evt) - { - if (currentTable != null) - { - // Converts rgb(r,g,b) values - var color = currentTable.style.borderColor.replace( - /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g, - function($0, $1, $2, $3) { - return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2); - }); - this.editorUi.pickColor(color, function(newColor) - { - var targetElt = (tableCell != null && (evt == null || !mxEvent.isShiftDown(evt))) ? tableCell : currentTable; - - graph.processElements(targetElt, function(elt) - { - elt.style.border = null; - }); - - if (newColor == null || newColor == mxConstants.NONE) - { - targetElt.removeAttribute('border'); - targetElt.style.border = ''; - targetElt.style.borderCollapse = ''; - } - else - { - targetElt.setAttribute('border', '1'); - targetElt.style.border = '1px solid ' + newColor; - targetElt.style.borderCollapse = 'collapse'; - } - }); - } - }), tablePanel2), - this.editorUi.toolbar.addButton('geSprite-fillcolor', mxResources.get('backgroundColor'), - mxUtils.bind(this, function(evt) - { - // Converts rgb(r,g,b) values - if (currentTable != null) - { - var color = currentTable.style.backgroundColor.replace( - /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g, - function($0, $1, $2, $3) { - return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2); - }); - this.editorUi.pickColor(color, function(newColor) - { - var targetElt = (tableCell != null && (evt == null || !mxEvent.isShiftDown(evt))) ? tableCell : currentTable; - - graph.processElements(targetElt, function(elt) - { - elt.style.backgroundColor = null; - }); - - if (newColor == null || newColor == mxConstants.NONE) - { - targetElt.style.backgroundColor = ''; - } - else - { - targetElt.style.backgroundColor = newColor; - } - }); - } - }), tablePanel2), - this.editorUi.toolbar.addButton('geSprite-fit', mxResources.get('spacing'), - function() - { - if (currentTable != null) - { - var value = currentTable.getAttribute('cellPadding') || 0; - - var dlg = new FilenameDialog(ui, value, mxResources.get('apply'), mxUtils.bind(this, function(newValue) - { - if (newValue != null && newValue.length > 0) - { - currentTable.setAttribute('cellPadding', newValue); - } - else - { - currentTable.removeAttribute('cellPadding'); - } - }), mxResources.get('spacing')); - ui.showDialog(dlg.container, 300, 80, true, true); - dlg.init(); - } - }, tablePanel2), - this.editorUi.toolbar.addButton('geSprite-left', mxResources.get('left'), - function() - { - if (currentTable != null) - { - currentTable.setAttribute('align', 'left'); - } - }, tablePanel2), - this.editorUi.toolbar.addButton('geSprite-center', mxResources.get('center'), - function() - { - if (currentTable != null) - { - currentTable.setAttribute('align', 'center'); - } - }, tablePanel2), - this.editorUi.toolbar.addButton('geSprite-right', mxResources.get('right'), - function() - { - if (currentTable != null) - { - currentTable.setAttribute('align', 'right'); - } - }, tablePanel2)]; - this.styleButtons(btns); - btns[2].style.marginRight = '9px'; - - if (mxClient.IS_QUIRKS) - { - mxUtils.br(wrapper3); - mxUtils.br(wrapper3); - } - - wrapper3.appendChild(tablePanel2); - container.appendChild(wrapper3); - - tableWrapper = wrapper3; - } - - function setSelected(elt, selected) - { - if (mxClient.IS_IE && (mxClient.IS_QUIRKS || document.documentMode < 10)) - { - elt.style.filter = (selected) ? 'progid:DXImageTransform.Microsoft.Gradient('+ - 'StartColorStr=\'#c5ecff\', EndColorStr=\'#87d4fb\', GradientType=0)' : ''; - } - else - { - elt.style.backgroundImage = (selected) ? 'linear-gradient(#c5ecff 0px,#87d4fb 100%)' : ''; - } - }; - - var listener = mxUtils.bind(this, function(sender, evt, force) - { - ss = this.format.getSelectionState(); - var fontStyle = mxUtils.getValue(ss.style, mxConstants.STYLE_FONTSTYLE, 0); - setSelected(fontStyleItems[0], (fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD); - setSelected(fontStyleItems[1], (fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC); - setSelected(fontStyleItems[2], (fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE); - fontMenu.firstChild.nodeValue = mxUtils.getValue(ss.style, mxConstants.STYLE_FONTFAMILY, Menus.prototype.defaultFont); - - setSelected(verticalItem, mxUtils.getValue(ss.style, mxConstants.STYLE_HORIZONTAL, '1') == '0'); - - if (force || document.activeElement != input) - { - var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_FONTSIZE, Menus.prototype.defaultFontSize)); - input.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - var align = mxUtils.getValue(ss.style, mxConstants.STYLE_ALIGN, mxConstants.ALIGN_CENTER); - setSelected(left, align == mxConstants.ALIGN_LEFT); - setSelected(center, align == mxConstants.ALIGN_CENTER); - setSelected(right, align == mxConstants.ALIGN_RIGHT); - - var valign = mxUtils.getValue(ss.style, mxConstants.STYLE_VERTICAL_ALIGN, mxConstants.ALIGN_MIDDLE); - setSelected(top, valign == mxConstants.ALIGN_TOP); - setSelected(middle, valign == mxConstants.ALIGN_MIDDLE); - setSelected(bottom, valign == mxConstants.ALIGN_BOTTOM); - - var pos = mxUtils.getValue(ss.style, mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER); - var vpos = mxUtils.getValue(ss.style, mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_MIDDLE); - - if (pos == mxConstants.ALIGN_LEFT && vpos == mxConstants.ALIGN_TOP) - { - positionSelect.value = 'topLeft'; - } - else if (pos == mxConstants.ALIGN_CENTER && vpos == mxConstants.ALIGN_TOP) - { - positionSelect.value = 'top'; - } - else if (pos == mxConstants.ALIGN_RIGHT && vpos == mxConstants.ALIGN_TOP) - { - positionSelect.value = 'topRight'; - } - else if (pos == mxConstants.ALIGN_LEFT && vpos == mxConstants.ALIGN_BOTTOM) - { - positionSelect.value = 'bottomLeft'; - } - else if (pos == mxConstants.ALIGN_CENTER && vpos == mxConstants.ALIGN_BOTTOM) - { - positionSelect.value = 'bottom'; - } - else if (pos == mxConstants.ALIGN_RIGHT && vpos == mxConstants.ALIGN_BOTTOM) - { - positionSelect.value = 'bottomRight'; - } - else if (pos == mxConstants.ALIGN_LEFT) - { - positionSelect.value = 'left'; - } - else if (pos == mxConstants.ALIGN_RIGHT) - { - positionSelect.value = 'right'; - } - else - { - positionSelect.value = 'center'; - } - - var dir = mxUtils.getValue(ss.style, mxConstants.STYLE_TEXT_DIRECTION, mxConstants.DEFAULT_TEXT_DIRECTION); - - if (dir == mxConstants.TEXT_DIRECTION_RTL) - { - dirSelect.value = 'rightToLeft'; - } - else if (dir == mxConstants.TEXT_DIRECTION_LTR) - { - dirSelect.value = 'leftToRight'; - } - else if (dir == mxConstants.TEXT_DIRECTION_AUTO) - { - dirSelect.value = 'automatic'; - } - - if (force || document.activeElement != globalSpacing) - { - var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING, 2)); - globalSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != topSpacing) - { - var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_TOP, 0)); - topSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != rightSpacing) - { - var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_RIGHT, 0)); - rightSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != bottomSpacing) - { - var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_BOTTOM, 0)); - bottomSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != leftSpacing) - { - var tmp = parseFloat(mxUtils.getValue(ss.style, mxConstants.STYLE_SPACING_LEFT, 0)); - leftSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - }); - - globalUpdate = this.installInputHandler(globalSpacing, mxConstants.STYLE_SPACING, 2, -999, 999, ' pt'); - topUpdate = this.installInputHandler(topSpacing, mxConstants.STYLE_SPACING_TOP, 0, -999, 999, ' pt'); - rightUpdate = this.installInputHandler(rightSpacing, mxConstants.STYLE_SPACING_RIGHT, 0, -999, 999, ' pt'); - bottomUpdate = this.installInputHandler(bottomSpacing, mxConstants.STYLE_SPACING_BOTTOM, 0, -999, 999, ' pt'); - leftUpdate = this.installInputHandler(leftSpacing, mxConstants.STYLE_SPACING_LEFT, 0, -999, 999, ' pt'); - - this.addKeyHandler(input, listener); - this.addKeyHandler(globalSpacing, listener); - this.addKeyHandler(topSpacing, listener); - this.addKeyHandler(rightSpacing, listener); - this.addKeyHandler(bottomSpacing, listener); - this.addKeyHandler(leftSpacing, listener); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); - - if (graph.cellEditor.isContentEditing()) - { - var updating = false; - - var updateCssHandler = function() - { - if (!updating) - { - updating = true; - - window.setTimeout(function() - { - var node = graph.getSelectedEditingElement(); - - if (node != null) - { - function getRelativeLineHeight(fontSize, css, elt) - { - if (elt.style != null && css != null) - { - var lineHeight = css.lineHeight - - if (elt.style.lineHeight != null && elt.style.lineHeight.substring(elt.style.lineHeight.length - 1) == '%') - { - return parseInt(elt.style.lineHeight) / 100; - } - else - { - return (lineHeight.substring(lineHeight.length - 2) == 'px') ? - parseFloat(lineHeight) / fontSize : parseInt(lineHeight); - } - } - else - { - return ''; - } - }; - - function getAbsoluteFontSize(css) - { - var fontSize = (css != null) ? css.fontSize : null; - - if (fontSize != null && fontSize.substring(fontSize.length - 2) == 'px') - { - return parseFloat(fontSize); - } - else - { - return mxConstants.DEFAULT_FONTSIZE; - } - }; - - var css = mxUtils.getCurrentStyle(node); - var fontSize = getAbsoluteFontSize(css); - var lineHeight = getRelativeLineHeight(fontSize, css, node); - - // Finds common font size - var elts = node.getElementsByTagName('*'); - - // IE does not support containsNode - if (elts.length > 0 && window.getSelection && !mxClient.IS_IE && !mxClient.IS_IE11) - { - var selection = window.getSelection(); - - for (var i = 0; i < elts.length; i++) - { - if (selection.containsNode(elts[i], true)) - { - temp = mxUtils.getCurrentStyle(elts[i]); - fontSize = Math.max(getAbsoluteFontSize(temp), fontSize); - var lh = getRelativeLineHeight(fontSize, temp, elts[i]); - - if (lh != lineHeight || isNaN(lh)) - { - lineHeight = ''; - } - } - } - } - - function hasParentOrOnlyChild(name) - { - if (graph.getParentByName(node, name, graph.cellEditor.textarea) != null) - { - return true; - } - else - { - var child = node; - - while (child != null && child.childNodes.length == 1) - { - child = child.childNodes[0]; - - if (child.nodeName == name) - { - return true; - } - } - } - - return false; - }; - - function isEqualOrPrefixed(str, value) - { - if (str != null && value != null) - { - if (str == value) - { - return true; - } - else if (str.length > value.length + 1) - { - return str.substring(str.length - value.length - 1, str.length) == '-' + value; - } - } - - return false; - }; - - if (css != null) - { - setSelected(fontStyleItems[0], css.fontWeight == 'bold' || - css.fontWeight > 400 || hasParentOrOnlyChild('B') || - hasParentOrOnlyChild('STRONG')); - setSelected(fontStyleItems[1], css.fontStyle == 'italic' || - hasParentOrOnlyChild('I') || hasParentOrOnlyChild('EM')); - setSelected(fontStyleItems[2], hasParentOrOnlyChild('U')); - setSelected(sup, hasParentOrOnlyChild('SUP')); - setSelected(sub, hasParentOrOnlyChild('SUB')); - - if (!graph.cellEditor.isTableSelected()) - { - var align = graph.cellEditor.align || mxUtils.getValue(ss.style, mxConstants.STYLE_ALIGN, mxConstants.ALIGN_CENTER); - - if (isEqualOrPrefixed(css.textAlign, 'justify')) - { - setSelected(full, isEqualOrPrefixed(css.textAlign, 'justify')); - setSelected(left, false); - setSelected(center, false); - setSelected(right, false); - } - else - { - setSelected(full, false); - setSelected(left, align == mxConstants.ALIGN_LEFT); - setSelected(center, align == mxConstants.ALIGN_CENTER); - setSelected(right, align == mxConstants.ALIGN_RIGHT); - } - } - else - { - setSelected(full, isEqualOrPrefixed(css.textAlign, 'justify')); - setSelected(left, isEqualOrPrefixed(css.textAlign, 'left')); - setSelected(center, isEqualOrPrefixed(css.textAlign, 'center')); - setSelected(right, isEqualOrPrefixed(css.textAlign, 'right')); - } - - currentTable = graph.getParentByName(node, 'TABLE', graph.cellEditor.textarea); - tableRow = (currentTable == null) ? null : graph.getParentByName(node, 'TR', currentTable); - tableCell = (currentTable == null) ? null : graph.getParentByNames(node, ['TD', 'TH'], currentTable); - tableWrapper.style.display = (currentTable != null) ? '' : 'none'; - - if (document.activeElement != input) - { - if (node.nodeName == 'FONT' && node.getAttribute('size') == '4' && - pendingFontSize != null) - { - node.removeAttribute('size'); - node.style.fontSize = pendingFontSize + ' pt'; - pendingFontSize = null; - } - else - { - input.value = (isNaN(fontSize)) ? '' : fontSize + ' pt'; - } - - var lh = parseFloat(lineHeight); - - if (!isNaN(lh)) - { - lineHeightInput.value = Math.round(lh * 100) + ' %'; - } - else - { - lineHeightInput.value = '100 %'; - } - } - - // Converts rgb(r,g,b) values - var color = css.color.replace( - /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g, - function($0, $1, $2, $3) { - return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2); - }); - var color2 = css.backgroundColor.replace( - /\brgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g, - function($0, $1, $2, $3) { - return "#" + ("0"+Number($1).toString(16)).substr(-2) + ("0"+Number($2).toString(16)).substr(-2) + ("0"+Number($3).toString(16)).substr(-2); - }); - - // Updates the color picker for the current font - if (fontColorApply != null) - { - if (color.charAt(0) == '#') - { - currentFontColor = color; - } - else - { - currentFontColor = '#000000'; - } - - fontColorApply(currentFontColor, true); - } - - if (bgColorApply != null) - { - if (color2.charAt(0) == '#') - { - currentBgColor = color2; - } - else - { - currentBgColor = null; - } - - bgColorApply(currentBgColor, true); - } - - // Workaround for firstChild is null or not an object - // in the log which seems to be IE8- only / 29.01.15 - if (fontMenu.firstChild != null) - { - fontMenu.firstChild.nodeValue = Graph.stripQuotes(css.fontFamily); - } - } - } - - updating = false; - }, 0); - } - }; - - if (mxClient.IS_FF || mxClient.IS_EDGE || mxClient.IS_IE || mxClient.IS_IE11) - { - mxEvent.addListener(graph.cellEditor.textarea, 'DOMSubtreeModified', updateCssHandler); - } - - mxEvent.addListener(graph.cellEditor.textarea, 'input', updateCssHandler); - mxEvent.addListener(graph.cellEditor.textarea, 'touchend', updateCssHandler); - mxEvent.addListener(graph.cellEditor.textarea, 'mouseup', updateCssHandler); - mxEvent.addListener(graph.cellEditor.textarea, 'keyup', updateCssHandler); - this.listeners.push({destroy: function() - { - // No need to remove listener since textarea is destroyed after edit - }}); - updateCssHandler(); - } - - return container; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel = function(format, editorUi, container) -{ - BaseFormatPanel.call(this, format, editorUi, container); - this.init(); -}; - -mxUtils.extend(StyleFormatPanel, BaseFormatPanel); - -/** - * - */ -StyleFormatPanel.prototype.defaultStrokeColor = 'black'; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.init = function() -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - var ss = this.format.getSelectionState(); - - if (!ss.containsLabel) - { - if (ss.containsImage && ss.vertices.length == 1 && ss.style.shape == 'image' && - ss.style.image != null && ss.style.image.substring(0, 19) == 'data:image/svg+xml;') - { - this.container.appendChild(this.addSvgStyles(this.createPanel())); - } - - if (!ss.containsImage || ss.style.shape == 'image') - { - this.container.appendChild(this.addFill(this.createPanel())); - } - - this.container.appendChild(this.addStroke(this.createPanel())); - this.container.appendChild(this.addLineJumps(this.createPanel())); - var opacityPanel = this.createRelativeOption(mxResources.get('opacity'), mxConstants.STYLE_OPACITY, 41); - opacityPanel.style.paddingTop = '8px'; - opacityPanel.style.paddingBottom = '8px'; - this.container.appendChild(opacityPanel); - this.container.appendChild(this.addEffects(this.createPanel())); - } - - var opsPanel = this.addEditOps(this.createPanel()); - - if (opsPanel.firstChild != null) - { - mxUtils.br(opsPanel); - } - - this.container.appendChild(this.addStyleOps(opsPanel)); -}; - -/** - * Use browser for parsing CSS. - */ -StyleFormatPanel.prototype.getCssRules = function(css) -{ - var doc = document.implementation.createHTMLDocument(''); - var styleElement = document.createElement('style'); - - mxUtils.setTextContent(styleElement, css); - doc.body.appendChild(styleElement); - - return styleElement.sheet.cssRules; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.addSvgStyles = function(container) -{ - var ui = this.editorUi; - var graph = ui.editor.graph; - var ss = this.format.getSelectionState(); - container.style.paddingTop = '6px'; - container.style.paddingBottom = '6px'; - container.style.fontWeight = 'bold'; - container.style.display = 'none'; - - try - { - var exp = ss.style.editableCssRules; - - if (exp != null) - { - var regex = new RegExp(exp); - - var data = ss.style.image.substring(ss.style.image.indexOf(',') + 1); - var xml = (window.atob) ? atob(data) : Base64.decode(data, true); - var svg = mxUtils.parseXml(xml); - - if (svg != null) - { - var styles = svg.getElementsByTagName('style'); - - for (var i = 0; i < styles.length; i++) - { - var rules = this.getCssRules(mxUtils.getTextContent(styles[i])); - - for (var j = 0; j < rules.length; j++) - { - this.addSvgRule(container, rules[j], svg, styles[i], rules, j, regex); - } - } - } - } - } - catch (e) - { - // ignore - } - - return container; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.addSvgRule = function(container, rule, svg, styleElem, rules, ruleIndex, regex) -{ - var ui = this.editorUi; - var graph = ui.editor.graph; - - if (regex.test(rule.selectorText)) - { - function rgb2hex(rgb) - { - rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); - - return (rgb && rgb.length === 4) ? "#" + - ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) + - ("0" + parseInt(rgb[2],10).toString(16)).slice(-2) + - ("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : ''; - }; - - var addStyleRule = mxUtils.bind(this, function(rule, key, label) - { - var value = mxUtils.trim(rule.style[key]); - - if (value != '' && value.substring(0, 4) != 'url(') - { - var option = this.createColorOption(label + ' ' + rule.selectorText, function() - { - return rgb2hex(value); - }, function(color) - { - rules[ruleIndex].style[key] = color; - var cssTxt = ''; - - for (var i = 0; i < rules.length; i++) - { - cssTxt += rules[i].cssText + ' '; - } - - styleElem.textContent = cssTxt; - var xml = mxUtils.getXml(svg.documentElement); - - graph.setCellStyles(mxConstants.STYLE_IMAGE, 'data:image/svg+xml,' + - ((window.btoa) ? btoa(xml) : Base64.encode(xml, true)), - graph.getSelectionCells()); - }, '#ffffff', - { - install: function(apply) - { - // ignore - }, - destroy: function() - { - // ignore - } - }); - - container.appendChild(option); - - // Shows container if rules are added - container.style.display = ''; - } - }); - - addStyleRule(rule, 'fill', mxResources.get('fill')); - addStyleRule(rule, 'stroke', mxResources.get('line')); - addStyleRule(rule, 'stop-color', mxResources.get('gradient')); - } -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.addEditOps = function(div) -{ - var ss = this.format.getSelectionState(); - var btn = null; - - if (this.editorUi.editor.graph.getSelectionCount() == 1) - { - btn = mxUtils.button(mxResources.get('editStyle'), mxUtils.bind(this, function(evt) - { - this.editorUi.actions.get('editStyle').funct(); - })); - - btn.setAttribute('title', mxResources.get('editStyle') + ' (' + this.editorUi.actions.get('editStyle').shortcut + ')'); - btn.style.width = '202px'; - btn.style.marginBottom = '2px'; - - div.appendChild(btn); - } - - if (ss.image) - { - var btn2 = mxUtils.button(mxResources.get('editImage'), mxUtils.bind(this, function(evt) - { - this.editorUi.actions.get('image').funct(); - })); - - btn2.setAttribute('title', mxResources.get('editImage')); - btn2.style.marginBottom = '2px'; - - if (btn == null) - { - btn2.style.width = '202px'; - } - else - { - btn.style.width = '100px'; - btn2.style.width = '100px'; - btn2.style.marginLeft = '2px'; - } - - div.appendChild(btn2); - } - - return div; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.addFill = function(container) -{ - var ui = this.editorUi; - var graph = ui.editor.graph; - var ss = this.format.getSelectionState(); - container.style.paddingTop = '6px'; - container.style.paddingBottom = '6px'; - - // Adds gradient direction option - var gradientSelect = document.createElement('select'); - gradientSelect.style.position = 'absolute'; - gradientSelect.style.marginTop = '-2px'; - gradientSelect.style.right = (mxClient.IS_QUIRKS) ? '52px' : '72px'; - gradientSelect.style.width = '70px'; - - var fillStyleSelect = gradientSelect.cloneNode(false); - - // Stops events from bubbling to color option event handler - mxEvent.addListener(gradientSelect, 'click', function(evt) - { - mxEvent.consume(evt); - }); - mxEvent.addListener(fillStyleSelect, 'click', function(evt) - { - mxEvent.consume(evt); - }); - - var defs = (ss.vertices.length >= 1) ? graph.stylesheet.getDefaultVertexStyle() : graph.stylesheet.getDefaultEdgeStyle(); - var gradientPanel = this.createCellColorOption(mxResources.get('gradient'), mxConstants.STYLE_GRADIENTCOLOR, - (defs[mxConstants.STYLE_GRADIENTCOLOR] != null) ? defs[mxConstants.STYLE_GRADIENTCOLOR] : '#ffffff', function(color) - { - if (color == null || color == mxConstants.NONE) - { - gradientSelect.style.display = 'none'; - } - else - { - gradientSelect.style.display = ''; - } - }, function(color) - { - graph.updateCellStyles(mxConstants.STYLE_GRADIENTCOLOR, color, graph.getSelectionCells()); - }); - - var fillKey = (ss.style.shape == 'image') ? mxConstants.STYLE_IMAGE_BACKGROUND : mxConstants.STYLE_FILLCOLOR; - var label = (ss.style.shape == 'image') ? mxResources.get('background') : mxResources.get('fill'); - - var defs = (ss.vertices.length >= 1) ? graph.stylesheet.getDefaultVertexStyle() : graph.stylesheet.getDefaultEdgeStyle(); - var fillPanel = this.createCellColorOption(label, fillKey, (defs[fillKey] != null) ? defs[fillKey] : '#ffffff', null, mxUtils.bind(this, function(color) - { - graph.updateCellStyles(fillKey, color, graph.getSelectionCells()); - })); - fillPanel.style.fontWeight = 'bold'; - - var tmpColor = mxUtils.getValue(ss.style, fillKey, null); - gradientPanel.style.display = (tmpColor != null && tmpColor != mxConstants.NONE && - ss.fill && ss.style.shape != 'image') ? '' : 'none'; - - var directions = [mxConstants.DIRECTION_NORTH, mxConstants.DIRECTION_EAST, - mxConstants.DIRECTION_SOUTH, mxConstants.DIRECTION_WEST]; - - for (var i = 0; i < directions.length; i++) - { - var gradientOption = document.createElement('option'); - gradientOption.setAttribute('value', directions[i]); - mxUtils.write(gradientOption, mxResources.get(directions[i])); - gradientSelect.appendChild(gradientOption); - } - - gradientPanel.appendChild(gradientSelect); - - for (var i = 0; i < Editor.roughFillStyles.length; i++) - { - var fillStyleOption = document.createElement('option'); - fillStyleOption.setAttribute('value', Editor.roughFillStyles[i].val); - mxUtils.write(fillStyleOption, Editor.roughFillStyles[i].dispName); - fillStyleSelect.appendChild(fillStyleOption); - } - - fillPanel.appendChild(fillStyleSelect); - - var listener = mxUtils.bind(this, function() - { - ss = this.format.getSelectionState(); - var value = mxUtils.getValue(ss.style, mxConstants.STYLE_GRADIENT_DIRECTION, mxConstants.DIRECTION_SOUTH); - var fillStyle = mxUtils.getValue(ss.style, 'fillStyle', 'auto'); - - // Handles empty string which is not allowed as a value - if (value == '') - { - value = mxConstants.DIRECTION_SOUTH; - } - - gradientSelect.value = value; - fillStyleSelect.value = fillStyle; - container.style.display = (ss.fill) ? '' : 'none'; - - var fillColor = mxUtils.getValue(ss.style, mxConstants.STYLE_FILLCOLOR, null); - - if (!ss.fill || ss.containsImage || fillColor == null || fillColor == mxConstants.NONE || ss.style.shape == 'filledEdge') - { - fillStyleSelect.style.display = 'none'; - gradientPanel.style.display = 'none'; - } - else - { - fillStyleSelect.style.display = (ss.style.sketch == '1') ? '' : 'none'; - gradientPanel.style.display = (ss.style.sketch != '1' || fillStyle == 'solid' || fillStyle == 'auto') ? '' : 'none'; - } - }); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); - - mxEvent.addListener(gradientSelect, 'change', function(evt) - { - graph.setCellStyles(mxConstants.STYLE_GRADIENT_DIRECTION, gradientSelect.value, graph.getSelectionCells()); - mxEvent.consume(evt); - }); - - mxEvent.addListener(fillStyleSelect, 'change', function(evt) - { - graph.setCellStyles('fillStyle', fillStyleSelect.value, graph.getSelectionCells()); - mxEvent.consume(evt); - }); - - container.appendChild(fillPanel); - container.appendChild(gradientPanel); - - // Adds custom colors - var custom = this.getCustomColors(); - - for (var i = 0; i < custom.length; i++) - { - container.appendChild(this.createCellColorOption(custom[i].title, custom[i].key, custom[i].defaultValue)); - } - - return container; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.getCustomColors = function() -{ - var ss = this.format.getSelectionState(); - var result = []; - - if (ss.style.shape == 'swimlane' || ss.style.shape == 'table') - { - result.push({title: mxResources.get('laneColor'), key: 'swimlaneFillColor', defaultValue: '#ffffff'}); - } - - return result; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.addStroke = function(container) -{ - var ui = this.editorUi; - var graph = ui.editor.graph; - var ss = this.format.getSelectionState(); - - container.style.paddingTop = '4px'; - container.style.paddingBottom = '4px'; - container.style.whiteSpace = 'normal'; - - var colorPanel = document.createElement('div'); - colorPanel.style.fontWeight = 'bold'; - - if (!ss.stroke) - { - colorPanel.style.display = 'none'; - } - - // Adds gradient direction option - var styleSelect = document.createElement('select'); - styleSelect.style.position = 'absolute'; - styleSelect.style.marginTop = '-2px'; - styleSelect.style.right = '72px'; - styleSelect.style.width = '80px'; - - var styles = ['sharp', 'rounded', 'curved']; - - for (var i = 0; i < styles.length; i++) - { - var styleOption = document.createElement('option'); - styleOption.setAttribute('value', styles[i]); - mxUtils.write(styleOption, mxResources.get(styles[i])); - styleSelect.appendChild(styleOption); - } - - mxEvent.addListener(styleSelect, 'change', function(evt) - { - graph.getModel().beginUpdate(); - try - { - var keys = [mxConstants.STYLE_ROUNDED, mxConstants.STYLE_CURVED]; - // Default for rounded is 1 - var values = ['0', null]; - - if (styleSelect.value == 'rounded') - { - values = ['1', null]; - } - else if (styleSelect.value == 'curved') - { - values = [null, '1']; - } - - for (var i = 0; i < keys.length; i++) - { - graph.setCellStyles(keys[i], values[i], graph.getSelectionCells()); - } - - ui.fireEvent(new mxEventObject('styleChanged', 'keys', keys, - 'values', values, 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - - mxEvent.consume(evt); - }); - - // Stops events from bubbling to color option event handler - mxEvent.addListener(styleSelect, 'click', function(evt) - { - mxEvent.consume(evt); - }); - - var strokeKey = (ss.style.shape == 'image') ? mxConstants.STYLE_IMAGE_BORDER : mxConstants.STYLE_STROKECOLOR; - var label = (ss.style.shape == 'image') ? mxResources.get('border') : mxResources.get('line'); - - var defs = (ss.vertices.length >= 1) ? graph.stylesheet.getDefaultVertexStyle() : graph.stylesheet.getDefaultEdgeStyle(); - var lineColor = this.createCellColorOption(label, strokeKey, (defs[strokeKey] != null) ? defs[strokeKey] : '#000000', null, mxUtils.bind(this, function(color) - { - graph.updateCellStyles(strokeKey, color, graph.getSelectionCells()); - })); - - lineColor.appendChild(styleSelect); - colorPanel.appendChild(lineColor); - - // Used if only edges selected - var stylePanel = colorPanel.cloneNode(false); - stylePanel.style.fontWeight = 'normal'; - stylePanel.style.whiteSpace = 'nowrap'; - stylePanel.style.position = 'relative'; - stylePanel.style.paddingLeft = '16px' - stylePanel.style.marginBottom = '2px'; - stylePanel.style.marginTop = '2px'; - stylePanel.className = 'geToolbarContainer'; - - var addItem = mxUtils.bind(this, function(menu, width, cssName, keys, values) - { - var item = this.editorUi.menus.styleChange(menu, '', keys, values, 'geIcon', null); - - var pat = document.createElement('div'); - pat.style.width = width + 'px'; - pat.style.height = '1px'; - pat.style.borderBottom = '1px ' + cssName + ' ' + this.defaultStrokeColor; - pat.style.paddingTop = '6px'; - - item.firstChild.firstChild.style.padding = '0px 4px 0px 4px'; - item.firstChild.firstChild.style.width = width + 'px'; - item.firstChild.firstChild.appendChild(pat); - - return item; - }); - - var pattern = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel, 'geSprite-orthogonal', mxResources.get('pattern'), false, mxUtils.bind(this, function(menu) - { - addItem(menu, 75, 'solid', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], [null, null]).setAttribute('title', mxResources.get('solid')); - addItem(menu, 75, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', null]).setAttribute('title', mxResources.get('dashed')); - addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 1']).setAttribute('title', mxResources.get('dotted') + ' (1)'); - addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 2']).setAttribute('title', mxResources.get('dotted') + ' (2)'); - addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 4']).setAttribute('title', mxResources.get('dotted') + ' (3)'); - })); - - // Used for mixed selection (vertices and edges) - var altStylePanel = stylePanel.cloneNode(false); - - var edgeShape = this.editorUi.toolbar.addMenuFunctionInContainer(altStylePanel, 'geSprite-connection', mxResources.get('connection'), false, mxUtils.bind(this, function(menu) - { - this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_SHAPE, mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, 'width'], [null, null, null, null], 'geIcon geSprite geSprite-connection', null, true).setAttribute('title', mxResources.get('line')); - this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_SHAPE, mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, 'width'], ['link', null, null, null], 'geIcon geSprite geSprite-linkedge', null, true).setAttribute('title', mxResources.get('link')); - this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_SHAPE, mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, 'width'], ['flexArrow', null, null, null], 'geIcon geSprite geSprite-arrow', null, true).setAttribute('title', mxResources.get('arrow')); - this.editorUi.menus.styleChange(menu, '', [mxConstants.STYLE_SHAPE, mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE, 'width'], ['arrow', null, null, null], 'geIcon geSprite geSprite-simplearrow', null, true).setAttribute('title', mxResources.get('simpleArrow')); - })); - - var altPattern = this.editorUi.toolbar.addMenuFunctionInContainer(altStylePanel, 'geSprite-orthogonal', mxResources.get('pattern'), false, mxUtils.bind(this, function(menu) - { - addItem(menu, 33, 'solid', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], [null, null]).setAttribute('title', mxResources.get('solid')); - addItem(menu, 33, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', null]).setAttribute('title', mxResources.get('dashed')); - addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 1']).setAttribute('title', mxResources.get('dotted') + ' (1)'); - addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 2']).setAttribute('title', mxResources.get('dotted') + ' (2)'); - addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 4']).setAttribute('title', mxResources.get('dotted') + ' (3)'); - })); - - var stylePanel2 = stylePanel.cloneNode(false); - - // Stroke width - var input = document.createElement('input'); - input.style.textAlign = 'right'; - input.style.marginTop = '2px'; - input.style.width = '41px'; - input.setAttribute('title', mxResources.get('linewidth')); - - stylePanel.appendChild(input); - - var altInput = input.cloneNode(true); - altStylePanel.appendChild(altInput); - - function update(evt) - { - // Maximum stroke width is 999 - var value = parseInt(input.value); - value = Math.min(999, Math.max(1, (isNaN(value)) ? 1 : value)); - - if (value != mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1)) - { - graph.setCellStyles(mxConstants.STYLE_STROKEWIDTH, value, graph.getSelectionCells()); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_STROKEWIDTH], - 'values', [value], 'cells', graph.getSelectionCells())); - } - - input.value = value + ' pt'; - mxEvent.consume(evt); - }; - - function altUpdate(evt) - { - // Maximum stroke width is 999 - var value = parseInt(altInput.value); - value = Math.min(999, Math.max(1, (isNaN(value)) ? 1 : value)); - - if (value != mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1)) - { - graph.setCellStyles(mxConstants.STYLE_STROKEWIDTH, value, graph.getSelectionCells()); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', [mxConstants.STYLE_STROKEWIDTH], - 'values', [value], 'cells', graph.getSelectionCells())); - } - - altInput.value = value + ' pt'; - mxEvent.consume(evt); - }; - - var stepper = this.createStepper(input, update, 1, 9); - stepper.style.display = input.style.display; - stepper.style.marginTop = '2px'; - stylePanel.appendChild(stepper); - - var altStepper = this.createStepper(altInput, altUpdate, 1, 9); - altStepper.style.display = altInput.style.display; - altStepper.style.marginTop = '2px'; - altStylePanel.appendChild(altStepper); - - if (!mxClient.IS_QUIRKS) - { - input.style.position = 'absolute'; - input.style.height = '15px'; - input.style.left = '141px'; - stepper.style.left = '190px'; - - altInput.style.position = 'absolute'; - altInput.style.left = '141px'; - altInput.style.height = '15px'; - altStepper.style.left = '190px'; - } - else - { - input.style.height = '17px'; - altInput.style.height = '17px'; - } - - mxEvent.addListener(input, 'blur', update); - mxEvent.addListener(input, 'change', update); - - mxEvent.addListener(altInput, 'blur', altUpdate); - mxEvent.addListener(altInput, 'change', altUpdate); - - if (mxClient.IS_QUIRKS) - { - mxUtils.br(stylePanel2); - mxUtils.br(stylePanel2); - } - - var edgeStyle = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel2, 'geSprite-orthogonal', mxResources.get('waypoints'), false, mxUtils.bind(this, function(menu) - { - if (ss.style.shape != 'arrow') - { - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], [null, null, null], 'geIcon geSprite geSprite-straight', null, true).setAttribute('title', mxResources.get('straight')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['orthogonalEdgeStyle', null, null], 'geIcon geSprite geSprite-orthogonal', null, true).setAttribute('title', mxResources.get('orthogonal')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['elbowEdgeStyle', null, null, null], 'geIcon geSprite geSprite-horizontalelbow', null, true).setAttribute('title', mxResources.get('simple')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['elbowEdgeStyle', 'vertical', null, null], 'geIcon geSprite geSprite-verticalelbow', null, true).setAttribute('title', mxResources.get('simple')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['isometricEdgeStyle', null, null, null], 'geIcon geSprite geSprite-horizontalisometric', null, true).setAttribute('title', mxResources.get('isometric')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_ELBOW, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['isometricEdgeStyle', 'vertical', null, null], 'geIcon geSprite geSprite-verticalisometric', null, true).setAttribute('title', mxResources.get('isometric')); - - if (ss.style.shape == 'connector') - { - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['orthogonalEdgeStyle', '1', null], 'geIcon geSprite geSprite-curved', null, true).setAttribute('title', mxResources.get('curved')); - } - - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_EDGE, mxConstants.STYLE_CURVED, mxConstants.STYLE_NOEDGESTYLE], ['entityRelationEdgeStyle', null, null], 'geIcon geSprite geSprite-entity', null, true).setAttribute('title', mxResources.get('entityRelation')); - } - })); - - var lineStart = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel2, 'geSprite-startclassic', mxResources.get('linestart'), false, mxUtils.bind(this, function(menu) - { - if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow' || ss.style.shape == 'filledEdge') - { - var item = this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.NONE, 0], 'geIcon', null, false); - item.setAttribute('title', mxResources.get('none')); - item.firstChild.firstChild.innerHTML = '' + mxUtils.htmlEntities(mxResources.get('none')) + ''; - - if (ss.style.shape == 'connector' || ss.style.shape == 'filledEdge') - { - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC, 1], 'geIcon geSprite geSprite-startclassic', null, false).setAttribute('title', mxResources.get('classic')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC_THIN, 1], 'geIcon geSprite geSprite-startclassicthin', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OPEN, 0], 'geIcon geSprite geSprite-startopen', null, false).setAttribute('title', mxResources.get('openArrow')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OPEN_THIN, 0], 'geIcon geSprite geSprite-startopenthin', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['openAsync', 0], 'geIcon geSprite geSprite-startopenasync', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK, 1], 'geIcon geSprite geSprite-startblock', null, false).setAttribute('title', mxResources.get('block')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK_THIN, 1], 'geIcon geSprite geSprite-startblockthin', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['async', 1], 'geIcon geSprite geSprite-startasync', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OVAL, 1], 'geIcon geSprite geSprite-startoval', null, false).setAttribute('title', mxResources.get('oval')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND, 1], 'geIcon geSprite geSprite-startdiamond', null, false).setAttribute('title', mxResources.get('diamond')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND_THIN, 1], 'geIcon geSprite geSprite-startthindiamond', null, false).setAttribute('title', mxResources.get('diamondThin')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC, 0], 'geIcon geSprite geSprite-startclassictrans', null, false).setAttribute('title', mxResources.get('classic')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC_THIN, 0], 'geIcon geSprite geSprite-startclassicthintrans', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK, 0], 'geIcon geSprite geSprite-startblocktrans', null, false).setAttribute('title', mxResources.get('block')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_BLOCK_THIN, 0], 'geIcon geSprite geSprite-startblockthintrans', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['async', 0], 'geIcon geSprite geSprite-startasynctrans', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_OVAL, 0], 'geIcon geSprite geSprite-startovaltrans', null, false).setAttribute('title', mxResources.get('oval')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND, 0], 'geIcon geSprite geSprite-startdiamondtrans', null, false).setAttribute('title', mxResources.get('diamond')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_DIAMOND_THIN, 0], 'geIcon geSprite geSprite-startthindiamondtrans', null, false).setAttribute('title', mxResources.get('diamondThin')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['box', 0], 'geIcon geSprite geSvgSprite geSprite-box', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['halfCircle', 0], 'geIcon geSprite geSvgSprite geSprite-halfCircle', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['dash', 0], 'geIcon geSprite geSprite-startdash', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['cross', 0], 'geIcon geSprite geSprite-startcross', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['circlePlus', 0], 'geIcon geSprite geSprite-startcircleplus', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['circle', 1], 'geIcon geSprite geSprite-startcircle', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERone', 0], 'geIcon geSprite geSprite-starterone', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERmandOne', 0], 'geIcon geSprite geSprite-starteronetoone', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERmany', 0], 'geIcon geSprite geSprite-startermany', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERoneToMany', 0], 'geIcon geSprite geSprite-starteronetomany', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERzeroToOne', 1], 'geIcon geSprite geSprite-starteroneopt', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], ['ERzeroToMany', 1], 'geIcon geSprite geSprite-startermanyopt', null, false); - } - else - { - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW], [mxConstants.ARROW_BLOCK], 'geIcon geSprite geSprite-startblocktrans', null, false).setAttribute('title', mxResources.get('block')); - } - } - })); - - var lineEnd = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel2, 'geSprite-endclassic', mxResources.get('lineend'), false, mxUtils.bind(this, function(menu) - { - if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow' || ss.style.shape == 'filledEdge') - { - var item = this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.NONE, 0], 'geIcon', null, false); - item.setAttribute('title', mxResources.get('none')); - item.firstChild.firstChild.innerHTML = '' + mxUtils.htmlEntities(mxResources.get('none')) + ''; - - if (ss.style.shape == 'connector' || ss.style.shape == 'filledEdge') - { - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC, 1], 'geIcon geSprite geSprite-endclassic', null, false).setAttribute('title', mxResources.get('classic')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC_THIN, 1], 'geIcon geSprite geSprite-endclassicthin', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OPEN, 0], 'geIcon geSprite geSprite-endopen', null, false).setAttribute('title', mxResources.get('openArrow')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OPEN_THIN, 0], 'geIcon geSprite geSprite-endopenthin', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['openAsync', 0], 'geIcon geSprite geSprite-endopenasync', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK, 1], 'geIcon geSprite geSprite-endblock', null, false).setAttribute('title', mxResources.get('block')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK_THIN, 1], 'geIcon geSprite geSprite-endblockthin', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['async', 1], 'geIcon geSprite geSprite-endasync', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OVAL, 1], 'geIcon geSprite geSprite-endoval', null, false).setAttribute('title', mxResources.get('oval')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND, 1], 'geIcon geSprite geSprite-enddiamond', null, false).setAttribute('title', mxResources.get('diamond')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND_THIN, 1], 'geIcon geSprite geSprite-endthindiamond', null, false).setAttribute('title', mxResources.get('diamondThin')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC, 0], 'geIcon geSprite geSprite-endclassictrans', null, false).setAttribute('title', mxResources.get('classic')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC_THIN, 0], 'geIcon geSprite geSprite-endclassicthintrans', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK, 0], 'geIcon geSprite geSprite-endblocktrans', null, false).setAttribute('title', mxResources.get('block')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_BLOCK_THIN, 0], 'geIcon geSprite geSprite-endblockthintrans', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['async', 0], 'geIcon geSprite geSprite-endasynctrans', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_OVAL, 0], 'geIcon geSprite geSprite-endovaltrans', null, false).setAttribute('title', mxResources.get('oval')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND, 0], 'geIcon geSprite geSprite-enddiamondtrans', null, false).setAttribute('title', mxResources.get('diamond')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_DIAMOND_THIN, 0], 'geIcon geSprite geSprite-endthindiamondtrans', null, false).setAttribute('title', mxResources.get('diamondThin')); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['box', 0], 'geIcon geSprite geSvgSprite geFlipSprite geSprite-box', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['halfCircle', 0], 'geIcon geSprite geSvgSprite geFlipSprite geSprite-halfCircle', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['dash', 0], 'geIcon geSprite geSprite-enddash', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['cross', 0], 'geIcon geSprite geSprite-endcross', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['circlePlus', 0], 'geIcon geSprite geSprite-endcircleplus', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['circle', 1], 'geIcon geSprite geSprite-endcircle', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERone', 0], 'geIcon geSprite geSprite-enderone', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERmandOne', 0], 'geIcon geSprite geSprite-enderonetoone', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERmany', 0], 'geIcon geSprite geSprite-endermany', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERoneToMany', 0], 'geIcon geSprite geSprite-enderonetomany', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERzeroToOne', 1], 'geIcon geSprite geSprite-enderoneopt', null, false); - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], ['ERzeroToMany', 1], 'geIcon geSprite geSprite-endermanyopt', null, false); - } - else - { - this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW], [mxConstants.ARROW_BLOCK], 'geIcon geSprite geSprite-endblocktrans', null, false).setAttribute('title', mxResources.get('block')); - } - } - })); - - this.addArrow(edgeShape, 8); - this.addArrow(edgeStyle); - this.addArrow(lineStart); - this.addArrow(lineEnd); - - var symbol = this.addArrow(pattern, 9); - symbol.className = 'geIcon'; - symbol.style.width = 'auto'; - - var altSymbol = this.addArrow(altPattern, 9); - altSymbol.className = 'geIcon'; - altSymbol.style.width = '22px'; - - var solid = document.createElement('div'); - solid.style.width = '85px'; - solid.style.height = '1px'; - solid.style.borderBottom = '1px solid ' + this.defaultStrokeColor; - solid.style.marginBottom = '9px'; - symbol.appendChild(solid); - - var altSolid = document.createElement('div'); - altSolid.style.width = '23px'; - altSolid.style.height = '1px'; - altSolid.style.borderBottom = '1px solid ' + this.defaultStrokeColor; - altSolid.style.marginBottom = '9px'; - altSymbol.appendChild(altSolid); - - pattern.style.height = '15px'; - altPattern.style.height = '15px'; - edgeShape.style.height = '15px'; - edgeStyle.style.height = '17px'; - lineStart.style.marginLeft = '3px'; - lineStart.style.height = '17px'; - lineEnd.style.marginLeft = '3px'; - lineEnd.style.height = '17px'; - - container.appendChild(colorPanel); - container.appendChild(altStylePanel); - container.appendChild(stylePanel); - - var arrowPanel = stylePanel.cloneNode(false); - arrowPanel.style.paddingBottom = '6px'; - arrowPanel.style.paddingTop = '4px'; - arrowPanel.style.fontWeight = 'normal'; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.marginLeft = '3px'; - span.style.marginBottom = '12px'; - span.style.marginTop = '2px'; - span.style.fontWeight = 'normal'; - span.style.width = '76px'; - - mxUtils.write(span, mxResources.get('lineend')); - arrowPanel.appendChild(span); - - var endSpacingUpdate, endSizeUpdate; - var endSpacing = this.addUnitInput(arrowPanel, 'pt', 74, 33, function() - { - endSpacingUpdate.apply(this, arguments); - }); - var endSize = this.addUnitInput(arrowPanel, 'pt', 20, 33, function() - { - endSizeUpdate.apply(this, arguments); - }); - - mxUtils.br(arrowPanel); - - var spacer = document.createElement('div'); - spacer.style.height = '8px'; - arrowPanel.appendChild(spacer); - - span = span.cloneNode(false); - mxUtils.write(span, mxResources.get('linestart')); - arrowPanel.appendChild(span); - - var startSpacingUpdate, startSizeUpdate; - var startSpacing = this.addUnitInput(arrowPanel, 'pt', 74, 33, function() - { - startSpacingUpdate.apply(this, arguments); - }); - var startSize = this.addUnitInput(arrowPanel, 'pt', 20, 33, function() - { - startSizeUpdate.apply(this, arguments); - }); - - mxUtils.br(arrowPanel); - this.addLabel(arrowPanel, mxResources.get('spacing'), 74, 50); - this.addLabel(arrowPanel, mxResources.get('size'), 20, 50); - mxUtils.br(arrowPanel); - - var perimeterPanel = colorPanel.cloneNode(false); - perimeterPanel.style.fontWeight = 'normal'; - perimeterPanel.style.position = 'relative'; - perimeterPanel.style.paddingLeft = '16px' - perimeterPanel.style.marginBottom = '2px'; - perimeterPanel.style.marginTop = '6px'; - perimeterPanel.style.borderWidth = '0px'; - perimeterPanel.style.paddingBottom = '18px'; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.marginLeft = '3px'; - span.style.marginBottom = '12px'; - span.style.marginTop = '1px'; - span.style.fontWeight = 'normal'; - span.style.width = '120px'; - mxUtils.write(span, mxResources.get('perimeter')); - perimeterPanel.appendChild(span); - - var perimeterUpdate; - var perimeterSpacing = this.addUnitInput(perimeterPanel, 'pt', 20, 41, function() - { - perimeterUpdate.apply(this, arguments); - }); - - if (ss.edges.length == graph.getSelectionCount()) - { - container.appendChild(stylePanel2); - - if (mxClient.IS_QUIRKS) - { - mxUtils.br(container); - mxUtils.br(container); - } - - container.appendChild(arrowPanel); - } - else if (ss.vertices.length == graph.getSelectionCount()) - { - if (mxClient.IS_QUIRKS) - { - mxUtils.br(container); - } - - container.appendChild(perimeterPanel); - } - - var listener = mxUtils.bind(this, function(sender, evt, force) - { - ss = this.format.getSelectionState(); - var color = mxUtils.getValue(ss.style, strokeKey, null); - - if (force || document.activeElement != input) - { - var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1)); - input.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != altInput) - { - var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_STROKEWIDTH, 1)); - altInput.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - styleSelect.style.visibility = (ss.style.shape == 'connector' || ss.style.shape == 'filledEdge') ? '' : 'hidden'; - - if (mxUtils.getValue(ss.style, mxConstants.STYLE_CURVED, null) == '1') - { - styleSelect.value = 'curved'; - } - else if (mxUtils.getValue(ss.style, mxConstants.STYLE_ROUNDED, null) == '1') - { - styleSelect.value = 'rounded'; - } - - if (mxUtils.getValue(ss.style, mxConstants.STYLE_DASHED, null) == '1') - { - if (mxUtils.getValue(ss.style, mxConstants.STYLE_DASH_PATTERN, null) == null) - { - solid.style.borderBottom = '1px dashed ' + this.defaultStrokeColor; - } - else - { - solid.style.borderBottom = '1px dotted ' + this.defaultStrokeColor; - } - } - else - { - solid.style.borderBottom = '1px solid ' + this.defaultStrokeColor; - } - - altSolid.style.borderBottom = solid.style.borderBottom; - - // Updates toolbar icon for edge style - var edgeStyleDiv = edgeStyle.getElementsByTagName('div')[0]; - - if (edgeStyleDiv != null) - { - var es = mxUtils.getValue(ss.style, mxConstants.STYLE_EDGE, null); - - if (mxUtils.getValue(ss.style, mxConstants.STYLE_NOEDGESTYLE, null) == '1') - { - es = null; - } - - if (es == 'orthogonalEdgeStyle' && mxUtils.getValue(ss.style, mxConstants.STYLE_CURVED, null) == '1') - { - edgeStyleDiv.className = 'geSprite geSprite-curved'; - } - else if (es == 'straight' || es == 'none' || es == null) - { - edgeStyleDiv.className = 'geSprite geSprite-straight'; - } - else if (es == 'entityRelationEdgeStyle') - { - edgeStyleDiv.className = 'geSprite geSprite-entity'; - } - else if (es == 'elbowEdgeStyle') - { - edgeStyleDiv.className = 'geSprite ' + ((mxUtils.getValue(ss.style, - mxConstants.STYLE_ELBOW, null) == 'vertical') ? - 'geSprite-verticalelbow' : 'geSprite-horizontalelbow'); - } - else if (es == 'isometricEdgeStyle') - { - edgeStyleDiv.className = 'geSprite ' + ((mxUtils.getValue(ss.style, - mxConstants.STYLE_ELBOW, null) == 'vertical') ? - 'geSprite-verticalisometric' : 'geSprite-horizontalisometric'); - } - else - { - edgeStyleDiv.className = 'geSprite geSprite-orthogonal'; - } - } - - // Updates icon for edge shape - var edgeShapeDiv = edgeShape.getElementsByTagName('div')[0]; - - if (edgeShapeDiv != null) - { - if (ss.style.shape == 'link') - { - edgeShapeDiv.className = 'geSprite geSprite-linkedge'; - } - else if (ss.style.shape == 'flexArrow') - { - edgeShapeDiv.className = 'geSprite geSprite-arrow'; - } - else if (ss.style.shape == 'arrow') - { - edgeShapeDiv.className = 'geSprite geSprite-simplearrow'; - } - else - { - edgeShapeDiv.className = 'geSprite geSprite-connection'; - } - } - - if (ss.edges.length == graph.getSelectionCount()) - { - altStylePanel.style.display = ''; - stylePanel.style.display = 'none'; - } - else - { - altStylePanel.style.display = 'none'; - stylePanel.style.display = ''; - } - - function updateArrow(marker, fill, elt, prefix) - { - var markerDiv = elt.getElementsByTagName('div')[0]; - - if (markerDiv != null) - { - markerDiv.className = ui.getCssClassForMarker(prefix, ss.style.shape, marker, fill); - - if (markerDiv.className == 'geSprite geSprite-noarrow') - { - markerDiv.innerHTML = mxUtils.htmlEntities(mxResources.get('none')); - markerDiv.style.backgroundImage = 'none'; - markerDiv.style.verticalAlign = 'top'; - markerDiv.style.marginTop = '5px'; - markerDiv.style.fontSize = '10px'; - markerDiv.style.filter = 'none'; - markerDiv.style.color = this.defaultStrokeColor; - markerDiv.nextSibling.style.marginTop = '0px'; - } - } - - return markerDiv; - }; - - var sourceDiv = updateArrow(mxUtils.getValue(ss.style, mxConstants.STYLE_STARTARROW, null), - mxUtils.getValue(ss.style, 'startFill', '1'), lineStart, 'start'); - var targetDiv = updateArrow(mxUtils.getValue(ss.style, mxConstants.STYLE_ENDARROW, null), - mxUtils.getValue(ss.style, 'endFill', '1'), lineEnd, 'end'); - - // Special cases for markers - if (sourceDiv != null && targetDiv != null) - { - if (ss.style.shape == 'arrow') - { - sourceDiv.className = 'geSprite geSprite-noarrow'; - targetDiv.className = 'geSprite geSprite-endblocktrans'; - } - else if (ss.style.shape == 'link') - { - sourceDiv.className = 'geSprite geSprite-noarrow'; - targetDiv.className = 'geSprite geSprite-noarrow'; - } - } - - mxUtils.setOpacity(edgeStyle, (ss.style.shape == 'arrow') ? 30 : 100); - - if (ss.style.shape != 'connector' && ss.style.shape != 'flexArrow' && ss.style.shape != 'filledEdge') - { - mxUtils.setOpacity(lineStart, 30); - mxUtils.setOpacity(lineEnd, 30); - } - else - { - mxUtils.setOpacity(lineStart, 100); - mxUtils.setOpacity(lineEnd, 100); - } - - if (force || document.activeElement != startSize) - { - var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE)); - startSize.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != startSpacing) - { - var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_SOURCE_PERIMETER_SPACING, 0)); - startSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != endSize) - { - var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE)); - endSize.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != startSpacing) - { - var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_TARGET_PERIMETER_SPACING, 0)); - endSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - - if (force || document.activeElement != perimeterSpacing) - { - var tmp = parseInt(mxUtils.getValue(ss.style, mxConstants.STYLE_PERIMETER_SPACING, 0)); - perimeterSpacing.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - }); - - startSizeUpdate = this.installInputHandler(startSize, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_MARKERSIZE, 0, 999, ' pt'); - startSpacingUpdate = this.installInputHandler(startSpacing, mxConstants.STYLE_SOURCE_PERIMETER_SPACING, 0, -999, 999, ' pt'); - endSizeUpdate = this.installInputHandler(endSize, mxConstants.STYLE_ENDSIZE, mxConstants.DEFAULT_MARKERSIZE, 0, 999, ' pt'); - endSpacingUpdate = this.installInputHandler(endSpacing, mxConstants.STYLE_TARGET_PERIMETER_SPACING, 0, -999, 999, ' pt'); - perimeterUpdate = this.installInputHandler(perimeterSpacing, mxConstants.STYLE_PERIMETER_SPACING, 0, 0, 999, ' pt'); - - this.addKeyHandler(input, listener); - this.addKeyHandler(startSize, listener); - this.addKeyHandler(startSpacing, listener); - this.addKeyHandler(endSize, listener); - this.addKeyHandler(endSpacing, listener); - this.addKeyHandler(perimeterSpacing, listener); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); - - return container; -}; - -/** - * Adds UI for configuring line jumps. - */ -StyleFormatPanel.prototype.addLineJumps = function(container) -{ - var ss = this.format.getSelectionState(); - - if (Graph.lineJumpsEnabled && ss.edges.length > 0 && - ss.vertices.length == 0 && ss.lineJumps) - { - container.style.padding = '8px 0px 24px 18px'; - - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - var span = document.createElement('div'); - span.style.position = 'absolute'; - span.style.fontWeight = 'bold'; - span.style.width = '80px'; - - mxUtils.write(span, mxResources.get('lineJumps')); - container.appendChild(span); - - var styleSelect = document.createElement('select'); - styleSelect.style.position = 'absolute'; - styleSelect.style.marginTop = '-2px'; - styleSelect.style.right = '76px'; - styleSelect.style.width = '62px'; - - var styles = ['none', 'arc', 'gap', 'sharp']; - - for (var i = 0; i < styles.length; i++) - { - var styleOption = document.createElement('option'); - styleOption.setAttribute('value', styles[i]); - mxUtils.write(styleOption, mxResources.get(styles[i])); - styleSelect.appendChild(styleOption); - } - - mxEvent.addListener(styleSelect, 'change', function(evt) - { - graph.getModel().beginUpdate(); - try - { - graph.setCellStyles('jumpStyle', styleSelect.value, graph.getSelectionCells()); - ui.fireEvent(new mxEventObject('styleChanged', 'keys', ['jumpStyle'], - 'values', [styleSelect.value], 'cells', graph.getSelectionCells())); - } - finally - { - graph.getModel().endUpdate(); - } - - mxEvent.consume(evt); - }); - - // Stops events from bubbling to color option event handler - mxEvent.addListener(styleSelect, 'click', function(evt) - { - mxEvent.consume(evt); - }); - - container.appendChild(styleSelect); - - var jumpSizeUpdate; - - var jumpSize = this.addUnitInput(container, 'pt', 22, 33, function() - { - jumpSizeUpdate.apply(this, arguments); - }); - - jumpSizeUpdate = this.installInputHandler(jumpSize, 'jumpSize', - Graph.defaultJumpSize, 0, 999, ' pt'); - - var listener = mxUtils.bind(this, function(sender, evt, force) - { - ss = this.format.getSelectionState(); - styleSelect.value = mxUtils.getValue(ss.style, 'jumpStyle', 'none'); - - if (force || document.activeElement != jumpSize) - { - var tmp = parseInt(mxUtils.getValue(ss.style, 'jumpSize', Graph.defaultJumpSize)); - jumpSize.value = (isNaN(tmp)) ? '' : tmp + ' pt'; - } - }); - - this.addKeyHandler(jumpSize, listener); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); - } - else - { - container.style.display = 'none'; - } - - return container; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.addEffects = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - var ss = this.format.getSelectionState(); - - div.style.paddingTop = '0px'; - div.style.paddingBottom = '2px'; - - var table = document.createElement('table'); - - if (mxClient.IS_QUIRKS) - { - table.style.fontSize = '1em'; - } - - table.style.width = '100%'; - table.style.fontWeight = 'bold'; - table.style.paddingRight = '20px'; - var tbody = document.createElement('tbody'); - var row = document.createElement('tr'); - row.style.padding = '0px'; - var left = document.createElement('td'); - left.style.padding = '0px'; - left.style.width = '50%'; - left.setAttribute('valign', 'top'); - - var right = left.cloneNode(true); - right.style.paddingLeft = '8px'; - row.appendChild(left); - row.appendChild(right); - tbody.appendChild(row); - table.appendChild(tbody); - div.appendChild(table); - - var current = left; - var count = 0; - - var addOption = mxUtils.bind(this, function(label, key, defaultValue) - { - var opt = this.createCellOption(label, key, defaultValue); - opt.style.width = '100%'; - current.appendChild(opt); - current = (current == left) ? right : left; - count++; - }); - - var listener = mxUtils.bind(this, function(sender, evt, force) - { - ss = this.format.getSelectionState(); - - left.innerHTML = ''; - right.innerHTML = ''; - current = left; - - if (ss.rounded) - { - addOption(mxResources.get('rounded'), mxConstants.STYLE_ROUNDED, 0); - } - - if (ss.style.shape == 'swimlane') - { - addOption(mxResources.get('divider'), 'swimlaneLine', 1); - } - - if (!ss.containsImage) - { - addOption(mxResources.get('shadow'), mxConstants.STYLE_SHADOW, 0); - } - - if (ss.glass) - { - addOption(mxResources.get('glass'), mxConstants.STYLE_GLASS, 0); - } - - addOption(mxResources.get('sketch'), 'sketch', 0); - }); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - listener(); - - return div; -} - -/** - * Adds the label menu items to the given menu and parent. - */ -StyleFormatPanel.prototype.addStyleOps = function(div) -{ - div.style.paddingTop = '10px'; - div.style.paddingBottom = '10px'; - - var btn = mxUtils.button(mxResources.get('setAsDefaultStyle'), mxUtils.bind(this, function(evt) - { - this.editorUi.actions.get('setAsDefaultStyle').funct(); - })); - - btn.setAttribute('title', mxResources.get('setAsDefaultStyle') + ' (' + this.editorUi.actions.get('setAsDefaultStyle').shortcut + ')'); - btn.style.width = '202px'; - div.appendChild(btn); - - return div; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramStylePanel = function(format, editorUi, container) -{ - BaseFormatPanel.call(this, format, editorUi, container); - this.init(); -}; - -mxUtils.extend(DiagramStylePanel, BaseFormatPanel); - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramStylePanel.prototype.init = function() -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - this.container.appendChild(this.addView(this.createPanel())); -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramStylePanel.prototype.addView = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - var model = graph.getModel(); - - div.style.whiteSpace = 'normal'; - - var sketch = graph.currentVertexStyle['sketch'] == '1' && graph.currentEdgeStyle['sketch'] == '1'; - var rounded = graph.currentVertexStyle['rounded'] == '1'; - var curved = graph.currentEdgeStyle['curved'] == '1'; - - var opts = document.createElement('div'); - opts.style.paddingBottom = '12px'; - opts.style.marginRight = '16px'; - div.style.paddingTop = '8px'; - - var table = document.createElement('table'); - - if (mxClient.IS_QUIRKS) - { - table.style.fontSize = '1em'; - } - - table.style.width = '100%'; - table.style.fontWeight = 'bold'; - - var tbody = document.createElement('tbody'); - var row = document.createElement('tr'); - row.style.padding = '0px'; - - var left = document.createElement('td'); - left.style.padding = '0px'; - left.style.width = '50%'; - left.setAttribute('valign', 'middle'); - - var right = left.cloneNode(true); - right.style.paddingLeft = '8px'; - row.appendChild(left); - row.appendChild(right); - tbody.appendChild(row); - table.appendChild(tbody); - - // Sketch - left.appendChild(this.createOption(mxResources.get('sketch'), function() - { - return sketch; - }, function(checked) - { - sketch = checked; - - if (checked) - { - graph.currentEdgeStyle['sketch'] = '1'; - graph.currentVertexStyle['sketch'] = '1'; - } - else - { - delete graph.currentEdgeStyle['sketch']; - delete graph.currentVertexStyle['sketch']; - } - - graph.updateCellStyles('sketch', (checked) ? '1' : null, graph.getVerticesAndEdges()); - }, null, function(div) - { - div.style.width = 'auto'; - })); - - // Rounded - right.appendChild(this.createOption(mxResources.get('rounded'), function() - { - return rounded; - }, function(checked) - { - rounded = checked; - - if (checked) - { - graph.currentVertexStyle['rounded'] = '1'; - } - else - { - delete graph.currentVertexStyle['rounded']; - } - - graph.updateCellStyles('rounded', (checked) ? '1' : null, graph.getVerticesAndEdges(true, true)); - }, null, function(div) - { - div.style.width = 'auto'; - })); - - // Curved - left = left.cloneNode(false); - right = right.cloneNode(false); - row = row.cloneNode(false); - row.appendChild(left); - row.appendChild(right); - tbody.appendChild(row); - - left.appendChild(this.createOption(mxResources.get('curved'), function() - { - return curved; - }, function(checked) - { - curved = checked; - - if (checked) - { - graph.currentEdgeStyle['curved'] = '1'; - } - else - { - delete graph.currentEdgeStyle['curved']; - } - - graph.updateCellStyles('curved', (checked) ? '1' : null, graph.getVerticesAndEdges(false, true)); - }, null, function(div) - { - div.style.width = 'auto'; - })); - - opts.appendChild(table); - div.appendChild(opts); - - var defaultStyles = ['fillColor', 'strokeColor', 'fontColor', 'gradientColor']; - - var updateCells = mxUtils.bind(this, function(styles, graphStyle) - { - var cells = graph.getVerticesAndEdges(); - - model.beginUpdate(); - try - { - for (var i = 0; i < cells.length; i++) - { - var style = graph.getCellStyle(cells[i]); - - // Handles special label background color - if (style['labelBackgroundColor'] != null) - { - graph.updateCellStyles('labelBackgroundColor', (graphStyle != null) ? - graphStyle.background : null, [cells[i]]); - } - - var edge = model.isEdge(cells[i]); - var newStyle = model.getStyle(cells[i]); - var current = (edge) ? graph.currentEdgeStyle : graph.currentVertexStyle; - - for (var j = 0; j < styles.length; j++) - { - if ((style[styles[j]] != null && style[styles[j]] != mxConstants.NONE) || - (styles[j] != mxConstants.STYLE_FILLCOLOR && - styles[j] != mxConstants.STYLE_STROKECOLOR)) - { - newStyle = mxUtils.setStyle(newStyle, styles[j], current[styles[j]]); - } - } - - model.setStyle(cells[i], newStyle); - } - } - finally - { - model.endUpdate(); - } - }); - - var removeStyles = mxUtils.bind(this, function(style, styles, defaultStyle) - { - if (style != null) - { - for (var j = 0; j < styles.length; j++) - { - if (((style[styles[j]] != null && - style[styles[j]] != mxConstants.NONE) || - (styles[j] != mxConstants.STYLE_FILLCOLOR && - styles[j] != mxConstants.STYLE_STROKECOLOR))) - { - style[styles[j]] = defaultStyle[styles[j]]; - } - } - } - }); - - var applyStyle = mxUtils.bind(this, function(style, result, cell, graphStyle, theGraph) - { - if (style != null) - { - if (cell != null) - { - // Handles special label background color - if (result['labelBackgroundColor'] != null) - { - var bg = (graphStyle != null) ? graphStyle.background : null; - theGraph = (theGraph != null) ? theGraph : graph; - - if (bg == null) - { - bg = theGraph.background; - } - - if (bg == null) - { - bg = theGraph.defaultPageBackgroundColor; - } - - result['labelBackgroundColor'] = bg; - } - } - - for (var key in style) - { - if (cell == null || ((result[key] != null && - result[key] != mxConstants.NONE) || - (key != mxConstants.STYLE_FILLCOLOR && - key != mxConstants.STYLE_STROKECOLOR))) - { - result[key] = style[key]; - } - } - } - }); - - var btn = mxUtils.button(mxResources.get('reset'), mxUtils.bind(this, function(evt) - { - var all = graph.getVerticesAndEdges(true, true); - - if (all.length > 0) - { - model.beginUpdate(); - try - { - graph.updateCellStyles('sketch', null, all); - graph.updateCellStyles('rounded', null, all); - graph.updateCellStyles('curved', null, graph.getVerticesAndEdges(false, true)); - } - finally - { - model.endUpdate(); - } - } - - graph.defaultVertexStyle = mxUtils.clone(ui.initialDefaultVertexStyle); - graph.defaultEdgeStyle = mxUtils.clone(ui.initialDefaultEdgeStyle); - ui.clearDefaultStyle(); - })); - - btn.setAttribute('title', mxResources.get('reset')); - btn.style.textOverflow = 'ellipsis'; - btn.style.maxWidth = '90px'; - right.appendChild(btn); - - var createPreview = mxUtils.bind(this, function(commonStyle, vertexStyle, edgeStyle, graphStyle, container) - { - // Wrapper needed to catch events - var div = document.createElement('div'); - div.style.cssText = 'position:absolute;display:inline-block;width:100%;height:100%;overflow:hidden;pointer-events:none;'; - container.appendChild(div); - - var graph2 = new Graph(div, null, null, graph.getStylesheet()); - graph2.resetViewOnRootChange = false; - graph2.foldingEnabled = false; - graph2.gridEnabled = false; - graph2.autoScroll = false; - graph2.setTooltips(false); - graph2.setConnectable(false); - graph2.setPanning(false); - graph2.setEnabled(false); - - graph2.getCellStyle = function(cell) - { - var result = mxUtils.clone(Graph.prototype.getCellStyle.apply(this, arguments)); - var defaultStyle = graph.stylesheet.getDefaultVertexStyle(); - var appliedStyle = vertexStyle; - - if (model.isEdge(cell)) - { - defaultStyle = graph.stylesheet.getDefaultEdgeStyle(); - appliedStyle = edgeStyle; - } - - removeStyles(result, defaultStyles, defaultStyle); - applyStyle(commonStyle, result, cell, graphStyle, graph2); - applyStyle(appliedStyle, result, cell, graphStyle, graph2); - - return result; - }; - - // Avoid HTML labels to capture events in bubble phase - graph2.model.beginUpdate(); - try - { - var v1 = graph2.insertVertex(graph2.getDefaultParent(), null, 'Shape', 14, 8, 70, 40, 'strokeWidth=2;'); - var e1 = graph2.insertEdge(graph2.getDefaultParent(), null, 'Connector', v1, v1, - 'edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;endSize=5;strokeWidth=2;') - e1.geometry.points = [new mxPoint(32, 70)]; - e1.geometry.offset = new mxPoint(0, 8); - } - finally - { - graph2.model.endUpdate(); - } - }); - - // Entries - var entries = document.createElement('div'); - entries.style.position = 'relative'; - div.appendChild(entries); - - // Cached entries - if (this.format.cachedStyleEntries == null) - { - this.format.cachedStyleEntries = []; - } - - var addEntry = mxUtils.bind(this, function(commonStyle, vertexStyle, edgeStyle, graphStyle, index) - { - var panel = this.format.cachedStyleEntries[index]; - - if (panel == null) - { - panel = document.createElement('div'); - panel.style.cssText = 'display:inline-block;position:relative;width:96px;height:90px;' + - 'cursor:pointer;border:1px solid gray;margin:2px;overflow:hidden;'; - - if (graphStyle != null && graphStyle.background != null) - { - panel.style.backgroundColor = graphStyle.background; - } - - createPreview(commonStyle, vertexStyle, edgeStyle, graphStyle, panel); - - mxEvent.addGestureListeners(panel, mxUtils.bind(this, function(evt) - { - panel.style.opacity = 0.5; - }), null, mxUtils.bind(this, function(evt) - { - panel.style.opacity = 1; - graph.defaultVertexStyle = mxUtils.clone(ui.initialDefaultVertexStyle); - graph.defaultEdgeStyle = mxUtils.clone(ui.initialDefaultEdgeStyle); - - applyStyle(commonStyle, graph.defaultVertexStyle); - applyStyle(commonStyle, graph.defaultEdgeStyle); - applyStyle(vertexStyle, graph.defaultVertexStyle); - applyStyle(edgeStyle, graph.defaultEdgeStyle); - ui.clearDefaultStyle(); - - if (sketch) - { - graph.currentEdgeStyle['sketch'] = '1'; - graph.currentVertexStyle['sketch'] = '1'; - } - else - { - graph.currentEdgeStyle['sketch'] = '0'; - graph.currentVertexStyle['sketch'] = '0'; - } - - if (rounded) - { - graph.currentVertexStyle['rounded'] = '1'; - graph.currentEdgeStyle['rounded'] = '1'; - } - else - { - graph.currentVertexStyle['rounded'] = '0'; - graph.currentEdgeStyle['rounded'] = '1'; - } - - if (curved) - { - graph.currentEdgeStyle['curved'] = '1'; - } - else - { - graph.currentEdgeStyle['curved'] = '0'; - } - - model.beginUpdate(); - try - { - updateCells(defaultStyles, graphStyle); - - var change = new ChangePageSetup(ui, (graphStyle != null) ? graphStyle.background : null); - change.ignoreImage = true; - model.execute(change); - - model.execute(new ChangeGridColor(ui, (graphStyle != null && graphStyle.gridColor != null) ? - graphStyle.gridColor : graph.view.defaultGridColor)); - } - finally - { - model.endUpdate(); - } - })); - - mxEvent.addListener(panel, 'mouseenter', mxUtils.bind(this, function(evt) - { - var prev = graph.getCellStyle; - var prevBg = graph.background; - var prevGrid = graph.view.gridColor; - - graph.background = (graphStyle != null) ? graphStyle.background : null; - graph.view.gridColor = (graphStyle != null && graphStyle.gridColor != null) ? - graphStyle.gridColor : graph.view.defaultGridColor; - - graph.getCellStyle = function(cell) - { - var result = mxUtils.clone(prev.apply(this, arguments)); - - var defaultStyle = graph.stylesheet.getDefaultVertexStyle(); - var appliedStyle = vertexStyle; - - if (model.isEdge(cell)) - { - defaultStyle = graph.stylesheet.getDefaultEdgeStyle(); - appliedStyle = edgeStyle; - } - - removeStyles(result, defaultStyles, defaultStyle); - applyStyle(commonStyle, result, cell, graphStyle); - applyStyle(appliedStyle, result, cell, graphStyle); - - return result; - }; - - graph.refresh(); - graph.getCellStyle = prev; - graph.background = prevBg; - graph.view.gridColor = prevGrid; - })); - - mxEvent.addListener(panel, 'mouseleave', mxUtils.bind(this, function(evt) - { - graph.refresh(); - })); - - this.format.cachedStyleEntries[index] = panel; - } - - entries.appendChild(panel); - }); - - // Maximum palettes to switch the switcher - var maxEntries = 10; - var pageCount = Math.ceil(Editor.styles.length / maxEntries); - this.format.currentStylePage = (this.format.currentStylePage != null) ? this.format.currentStylePage : 0; - var dots = []; - - var addEntries = mxUtils.bind(this, function() - { - if (dots.length > 0) - { - dots[this.format.currentStylePage].style.background = '#84d7ff'; - } - - for (var i = this.format.currentStylePage * maxEntries; - i < Math.min((this.format.currentStylePage + 1) * maxEntries, - Editor.styles.length); i++) - { - var s = Editor.styles[i]; - addEntry(s.commonStyle, s.vertexStyle, s.edgeStyle, s.graph, i); - } - }); - - var selectPage = mxUtils.bind(this, function(index) - { - if (index >= 0 && index < pageCount) - { - dots[this.format.currentStylePage].style.background = 'transparent'; - entries.innerHTML = ''; - this.format.currentStylePage = index; - addEntries(); - } - }); - - if (pageCount > 1) - { - // Selector - var switcher = document.createElement('div'); - switcher.style.whiteSpace = 'nowrap'; - switcher.style.position = 'relative'; - switcher.style.textAlign = 'center'; - switcher.style.paddingTop = '4px'; - switcher.style.width = '210px'; - - div.style.paddingBottom = '8px'; - - for (var i = 0; i < pageCount; i++) - { - var dot = document.createElement('div'); - dot.style.display = 'inline-block'; - dot.style.width = '6px'; - dot.style.height = '6px'; - dot.style.marginLeft = '4px'; - dot.style.marginRight = '3px'; - dot.style.borderRadius = '3px'; - dot.style.cursor = 'pointer'; - dot.style.background = 'transparent'; - dot.style.border = '1px solid #b5b6b7'; - - (mxUtils.bind(this, function(index, elt) - { - mxEvent.addListener(dot, 'click', mxUtils.bind(this, function() - { - selectPage(index); - })); - }))(i, dot); - - switcher.appendChild(dot); - dots.push(dot); - } - - div.appendChild(switcher); - addEntries(); - - if (pageCount < 15) - { - var left = document.createElement('div'); - left.style.cssText = 'position:absolute;left:0px;top:4px;bottom:0px;width:20px;margin:0px;opacity:0.5;' + - 'background-repeat:no-repeat;background-position:center center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAQBAMAAADQT4M0AAAAIVBMVEUAAAB2dnZ4eHh3d3d1dXVxcXF2dnZ2dnZ2dnZxcXF2dnYmb3w1AAAACnRSTlMAfCTkhhvb7cQSPH2JPgAAADRJREFUCNdjwACMAmBKaiGYs2oJmLPKAZ3DabU8AMRTXpUKopislqFyVzCAuUZgikkBZjoAcMYLnp53P/UAAAAASUVORK5CYII=);'; - - mxEvent.addListener(left, 'click', mxUtils.bind(this, function() - { - selectPage(mxUtils.mod(this.format.currentStylePage - 1, pageCount)); - })); - - var right = document.createElement('div'); - right.style.cssText = 'position:absolute;right:2px;top:4px;bottom:0px;width:20px;margin:0px;opacity:0.5;' + - 'background-repeat:no-repeat;background-position:center center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAQBAMAAADQT4M0AAAAIVBMVEUAAAB2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnYBuwCcAAAACnRSTlMAfCTkhhvb7cQSPH2JPgAAADZJREFUCNdjQAOMAmBKaiGY8loF5rKswsZlrVo8AUiFrTICcbIWK8A5DF1gDoMymMPApIAwHwCS0Qx/U7qCBQAAAABJRU5ErkJggg==);'; - switcher.appendChild(left); - switcher.appendChild(right); - - mxEvent.addListener(right, 'click', mxUtils.bind(this, function() - { - selectPage(mxUtils.mod(this.format.currentStylePage + 1, pageCount)); - })); - - // Hover state - function addHoverState(elt) - { - mxEvent.addListener(elt, 'mouseenter', function() - { - elt.style.opacity = '1'; - }); - mxEvent.addListener(elt, 'mouseleave', function() - { - elt.style.opacity = '0.5'; - }); - }; - - addHoverState(left); - addHoverState(right); - } - } - else - { - addEntries(); - } - - return div; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramFormatPanel = function(format, editorUi, container) -{ - BaseFormatPanel.call(this, format, editorUi, container); - this.init(); -}; - -mxUtils.extend(DiagramFormatPanel, BaseFormatPanel); - -/** - * Switch to disable page view. - */ -DiagramFormatPanel.showPageView = true; - -/** - * Specifies if the background image option should be shown. Default is true. - */ -DiagramFormatPanel.prototype.showBackgroundImageOption = true; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramFormatPanel.prototype.init = function() -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - this.container.appendChild(this.addView(this.createPanel())); - - if (graph.isEnabled()) - { - this.container.appendChild(this.addOptions(this.createPanel())); - this.container.appendChild(this.addPaperSize(this.createPanel())); - this.container.appendChild(this.addStyleOps(this.createPanel())); - } -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramFormatPanel.prototype.addView = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - div.appendChild(this.createTitle(mxResources.get('view'))); - - // Grid - this.addGridOption(div); - - // Page View - if (DiagramFormatPanel.showPageView) - { - div.appendChild(this.createOption(mxResources.get('pageView'), function() - { - return graph.pageVisible; - }, function(checked) - { - ui.actions.get('pageView').funct(); - }, - { - install: function(apply) - { - this.listener = function() - { - apply(graph.pageVisible); - }; - - ui.addListener('pageViewChanged', this.listener); - }, - destroy: function() - { - ui.removeListener(this.listener); - } - })); - } - - if (graph.isEnabled()) - { - // Background - var bg = this.createColorOption(mxResources.get('background'), function() - { - return graph.background; - }, function(color) - { - var change = new ChangePageSetup(ui, color); - change.ignoreImage = true; - - graph.model.execute(change); - }, '#ffffff', - { - install: function(apply) - { - this.listener = function() - { - apply(graph.background); - }; - - ui.addListener('backgroundColorChanged', this.listener); - }, - destroy: function() - { - ui.removeListener(this.listener); - } - }); - - if (this.showBackgroundImageOption) - { - var btn = mxUtils.button(mxResources.get('image'), function(evt) - { - ui.showBackgroundImageDialog(null, ui.editor.graph.backgroundImage); - mxEvent.consume(evt); - }) - - btn.style.position = 'absolute'; - btn.className = 'geColorBtn'; - btn.style.marginTop = '-4px'; - btn.style.paddingBottom = (document.documentMode == 11 || mxClient.IS_MT) ? '0px' : '2px'; - btn.style.height = '22px'; - btn.style.right = (mxClient.IS_QUIRKS) ? '52px' : '72px'; - btn.style.width = '56px'; - - bg.appendChild(btn); - } - - div.appendChild(bg); - } - - return div; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramFormatPanel.prototype.addOptions = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - div.appendChild(this.createTitle(mxResources.get('options'))); - - if (graph.isEnabled()) - { - // Connection arrows - div.appendChild(this.createOption(mxResources.get('connectionArrows'), function() - { - return graph.connectionArrowsEnabled; - }, function(checked) - { - ui.actions.get('connectionArrows').funct(); - }, - { - install: function(apply) - { - this.listener = function() - { - apply(graph.connectionArrowsEnabled); - }; - - ui.addListener('connectionArrowsChanged', this.listener); - }, - destroy: function() - { - ui.removeListener(this.listener); - } - })); - - // Connection points - div.appendChild(this.createOption(mxResources.get('connectionPoints'), function() - { - return graph.connectionHandler.isEnabled(); - }, function(checked) - { - ui.actions.get('connectionPoints').funct(); - }, - { - install: function(apply) - { - this.listener = function() - { - apply(graph.connectionHandler.isEnabled()); - }; - - ui.addListener('connectionPointsChanged', this.listener); - }, - destroy: function() - { - ui.removeListener(this.listener); - } - })); - - // Guides - div.appendChild(this.createOption(mxResources.get('guides'), function() - { - return graph.graphHandler.guidesEnabled; - }, function(checked) - { - ui.actions.get('guides').funct(); - }, - { - install: function(apply) - { - this.listener = function() - { - apply(graph.graphHandler.guidesEnabled); - }; - - ui.addListener('guidesEnabledChanged', this.listener); - }, - destroy: function() - { - ui.removeListener(this.listener); - } - })); - } - - return div; -}; - -/** - * - */ -DiagramFormatPanel.prototype.addGridOption = function(container) -{ - var fPanel = this; - var ui = this.editorUi; - var graph = ui.editor.graph; - - var input = document.createElement('input'); - input.style.position = 'absolute'; - input.style.textAlign = 'right'; - input.style.width = '38px'; - input.value = this.inUnit(graph.getGridSize()) + ' ' + this.getUnit(); - - var stepper = this.createStepper(input, update, this.getUnitStep(), null, null, null, this.isFloatUnit()); - input.style.display = (graph.isGridEnabled()) ? '' : 'none'; - stepper.style.display = input.style.display; - - mxEvent.addListener(input, 'keydown', function(e) - { - if (e.keyCode == 13) - { - graph.container.focus(); - mxEvent.consume(e); - } - else if (e.keyCode == 27) - { - input.value = graph.getGridSize(); - graph.container.focus(); - mxEvent.consume(e); - } - }); - - function update(evt) - { - var value = fPanel.isFloatUnit()? parseFloat(input.value) : parseInt(input.value); - value = fPanel.fromUnit(Math.max(fPanel.inUnit(1), (isNaN(value)) ? fPanel.inUnit(10) : value)); - - if (value != graph.getGridSize()) - { - graph.setGridSize(value) - } - - input.value = fPanel.inUnit(value) + ' ' + fPanel.getUnit(); - mxEvent.consume(evt); - }; - - mxEvent.addListener(input, 'blur', update); - mxEvent.addListener(input, 'change', update); - - if (mxClient.IS_SVG) - { - input.style.marginTop = '-2px'; - input.style.right = '84px'; - stepper.style.marginTop = '-16px'; - stepper.style.right = '72px'; - - var panel = this.createColorOption(mxResources.get('grid'), function() - { - var color = graph.view.gridColor; - - return (graph.isGridEnabled()) ? color : null; - }, function(color) - { - var enabled = graph.isGridEnabled(); - - if (color == mxConstants.NONE) - { - graph.setGridEnabled(false); - } - else - { - graph.setGridEnabled(true); - ui.setGridColor(color); - } - - input.style.display = (graph.isGridEnabled()) ? '' : 'none'; - stepper.style.display = input.style.display; - - if (enabled != graph.isGridEnabled()) - { - ui.fireEvent(new mxEventObject('gridEnabledChanged')); - } - }, '#e0e0e0', - { - install: function(apply) - { - this.listener = function() - { - apply((graph.isGridEnabled()) ? graph.view.gridColor : null); - }; - - ui.addListener('gridColorChanged', this.listener); - ui.addListener('gridEnabledChanged', this.listener); - }, - destroy: function() - { - ui.removeListener(this.listener); - } - }); - - panel.appendChild(input); - panel.appendChild(stepper); - container.appendChild(panel); - } - else - { - input.style.marginTop = '2px'; - input.style.right = '32px'; - stepper.style.marginTop = '2px'; - stepper.style.right = '20px'; - - container.appendChild(input); - container.appendChild(stepper); - - container.appendChild(this.createOption(mxResources.get('grid'), function() - { - return graph.isGridEnabled(); - }, function(checked) - { - graph.setGridEnabled(checked); - - if (graph.isGridEnabled()) - { - graph.view.gridColor = '#e0e0e0'; - } - - ui.fireEvent(new mxEventObject('gridEnabledChanged')); - }, - { - install: function(apply) - { - this.listener = function() - { - input.style.display = (graph.isGridEnabled()) ? '' : 'none'; - stepper.style.display = input.style.display; - - apply(graph.isGridEnabled()); - }; - - ui.addListener('gridEnabledChanged', this.listener); - }, - destroy: function() - { - ui.removeListener(this.listener); - } - })); - } -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramFormatPanel.prototype.addDocumentProperties = function(div) -{ - // Hook for subclassers - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - div.appendChild(this.createTitle(mxResources.get('options'))); - - return div; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramFormatPanel.prototype.addPaperSize = function(div) -{ - var ui = this.editorUi; - var editor = ui.editor; - var graph = editor.graph; - - div.appendChild(this.createTitle(mxResources.get('paperSize'))); - - var accessor = PageSetupDialog.addPageFormatPanel(div, 'formatpanel', graph.pageFormat, function(pageFormat) - { - if (graph.pageFormat == null || graph.pageFormat.width != pageFormat.width || - graph.pageFormat.height != pageFormat.height) - { - var change = new ChangePageSetup(ui, null, null, pageFormat); - change.ignoreColor = true; - change.ignoreImage = true; - - graph.model.execute(change); - } - }); - - this.addKeyHandler(accessor.widthInput, function() - { - accessor.set(graph.pageFormat); - }); - this.addKeyHandler(accessor.heightInput, function() - { - accessor.set(graph.pageFormat); - }); - - var listener = function() - { - accessor.set(graph.pageFormat); - }; - - ui.addListener('pageFormatChanged', listener); - this.listeners.push({destroy: function() { ui.removeListener(listener); }}); - - graph.getModel().addListener(mxEvent.CHANGE, listener); - this.listeners.push({destroy: function() { graph.getModel().removeListener(listener); }}); - - return div; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramFormatPanel.prototype.addStyleOps = function(div) -{ - var btn = mxUtils.button(mxResources.get('editData'), mxUtils.bind(this, function(evt) - { - this.editorUi.actions.get('editData').funct(); - })); - - btn.setAttribute('title', mxResources.get('editData') + ' (' + this.editorUi.actions.get('editData').shortcut + ')'); - btn.style.width = '202px'; - btn.style.marginBottom = '2px'; - div.appendChild(btn); - - mxUtils.br(div); - - btn = mxUtils.button(mxResources.get('clearDefaultStyle'), mxUtils.bind(this, function(evt) - { - this.editorUi.actions.get('clearDefaultStyle').funct(); - })); - - btn.setAttribute('title', mxResources.get('clearDefaultStyle') + ' (' + this.editorUi.actions.get('clearDefaultStyle').shortcut + ')'); - btn.style.width = '202px'; - div.appendChild(btn); - - return div; -}; - -/** - * Adds the label menu items to the given menu and parent. - */ -DiagramFormatPanel.prototype.destroy = function() -{ - BaseFormatPanel.prototype.destroy.apply(this, arguments); - - if (this.gridEnabledListener) - { - this.editorUi.removeListener(this.gridEnabledListener); - this.gridEnabledListener = null; - } -}; diff --git a/src/main/webapp/js/mxgraph/Graph.js b/src/main/webapp/js/mxgraph/Graph.js deleted file mode 100644 index 43c8bfde..00000000 --- a/src/main/webapp/js/mxgraph/Graph.js +++ /dev/null @@ -1,11948 +0,0 @@ -/** - * Copyright (c) 2006-2012, JGraph Ltd - */ -// Workaround for allowing target="_blank" in HTML sanitizer -// see https://code.google.com/p/google-caja/issues/detail?can=2&q=&colspec=ID%20Type%20Status%20Priority%20Owner%20Summary&groupby=&sort=&id=1296 -if (typeof html4 !== 'undefined') -{ - html4.ATTRIBS['a::target'] = 0; - html4.ATTRIBS['source::src'] = 0; - html4.ATTRIBS['video::src'] = 0; - // Would be nice for tooltips but probably a security risk... - //html4.ATTRIBS['video::autoplay'] = 0; - //html4.ATTRIBS['video::autobuffer'] = 0; -} - -// Workaround for handling named HTML entities in mxUtils.parseXml -// LATER: How to configure DOMParser to just ignore all entities? -(function() -{ - var entities = [ - ['nbsp', '160'], - ['shy', '173'] - ]; - - var parseXml = mxUtils.parseXml; - - mxUtils.parseXml = function(text) - { - for (var i = 0; i < entities.length; i++) - { - text = text.replace(new RegExp( - '&' + entities[i][0] + ';', 'g'), - '&#' + entities[i][1] + ';'); - } - - return parseXml(text); - }; -})(); - -// Shim for missing toISOString in older versions of IE -// See https://stackoverflow.com/questions/12907862 -if (!Date.prototype.toISOString) -{ - (function() - { - function pad(number) - { - var r = String(number); - - if (r.length === 1) - { - r = '0' + r; - } - - return r; - }; - - Date.prototype.toISOString = function() - { - return this.getUTCFullYear() - + '-' + pad( this.getUTCMonth() + 1 ) - + '-' + pad( this.getUTCDate() ) - + 'T' + pad( this.getUTCHours() ) - + ':' + pad( this.getUTCMinutes() ) - + ':' + pad( this.getUTCSeconds() ) - + '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 ) - + 'Z'; - }; - }()); -} - -// Shim for Date.now() -if (!Date.now) -{ - Date.now = function() - { - return new Date().getTime(); - }; -} - -// Changes default colors -/** - * Measurements Units - */ -mxConstants.POINTS = 1; -mxConstants.MILLIMETERS = 2; -mxConstants.INCHES = 3; -/** - * This ratio is with page scale 1 - */ -mxConstants.PIXELS_PER_MM = 3.937; -mxConstants.PIXELS_PER_INCH = 100; - -mxConstants.SHADOW_OPACITY = 0.25; -mxConstants.SHADOWCOLOR = '#000000'; -mxConstants.VML_SHADOWCOLOR = '#d0d0d0'; -mxGraph.prototype.pageBreakColor = '#c0c0c0'; -mxGraph.prototype.pageScale = 1; - -// Letter page format is default in US, Canada and Mexico -(function() -{ - try - { - if (navigator != null && navigator.language != null) - { - var lang = navigator.language.toLowerCase(); - mxGraph.prototype.pageFormat = (lang === 'en-us' || lang === 'en-ca' || lang === 'es-mx') ? - mxConstants.PAGE_FORMAT_LETTER_PORTRAIT : mxConstants.PAGE_FORMAT_A4_PORTRAIT; - } - } - catch (e) - { - // ignore - } -})(); - -// Matches label positions of mxGraph 1.x -mxText.prototype.baseSpacingTop = 5; -mxText.prototype.baseSpacingBottom = 1; - -// Keeps edges between relative child cells inside parent -mxGraphModel.prototype.ignoreRelativeEdgeParent = false; - -// Defines grid properties -mxGraphView.prototype.gridImage = (mxClient.IS_SVG) ? 'data:image/gif;base64,R0lGODlhCgAKAJEAAAAAAP///8zMzP///yH5BAEAAAMALAAAAAAKAAoAAAIJ1I6py+0Po2wFADs=' : - IMAGE_PATH + '/grid.gif'; -mxGraphView.prototype.gridSteps = 4; -mxGraphView.prototype.minGridSize = 4; - -// UrlParams is null in embed mode -mxGraphView.prototype.defaultGridColor = '#d0d0d0'; -mxGraphView.prototype.gridColor = mxGraphView.prototype.defaultGridColor; - -//Units -mxGraphView.prototype.unit = mxConstants.POINTS; - -mxGraphView.prototype.setUnit = function(unit) -{ - if (this.unit != unit) - { - this.unit = unit; - - this.fireEvent(new mxEventObject('unitChanged', 'unit', unit)); - } -}; - -// Alternative text for unsupported foreignObjects -mxSvgCanvas2D.prototype.foAltText = '[Not supported by viewer]'; - -// Hook for custom constraints -mxShape.prototype.getConstraints = function(style, w, h) -{ - return null; -}; - -/** - * Constructs a new graph instance. Note that the constructor does not take a - * container because the graph instance is needed for creating the UI, which - * in turn will create the container for the graph. Hence, the container is - * assigned later in EditorUi. - */ -/** - * Defines graph class. - */ -Graph = function(container, model, renderHint, stylesheet, themes, standalone) -{ - mxGraph.call(this, container, model, renderHint, stylesheet); - - this.themes = themes || this.defaultThemes; - this.currentEdgeStyle = mxUtils.clone(this.defaultEdgeStyle); - this.currentVertexStyle = mxUtils.clone(this.defaultVertexStyle); - this.standalone = (standalone != null) ? standalone : false; - - // Sets the base domain URL and domain path URL for relative links. - var b = this.baseUrl; - var p = b.indexOf('//'); - this.domainUrl = ''; - this.domainPathUrl = ''; - - if (p > 0) - { - var d = b.indexOf('/', p + 2); - - if (d > 0) - { - this.domainUrl = b.substring(0, d); - } - - d = b.lastIndexOf('/'); - - if (d > 0) - { - this.domainPathUrl = b.substring(0, d + 1); - } - } - - // Adds support for HTML labels via style. Note: Currently, only the Java - // backend supports HTML labels but CSS support is limited to the following: - // http://docs.oracle.com/javase/6/docs/api/index.html?javax/swing/text/html/CSS.html - // TODO: Wrap should not affect isHtmlLabel output (should be handled later) - this.isHtmlLabel = function(cell) - { - var style = this.getCurrentCellStyle(cell); - - return (style != null) ? (style['html'] == '1' || style[mxConstants.STYLE_WHITE_SPACE] == 'wrap') : false; - }; - - // Implements a listener for hover and click handling on edges - if (this.edgeMode) - { - var start = { - point: null, - event: null, - state: null, - handle: null, - selected: false - }; - - // Uses this event to process mouseDown to check the selection state before it is changed - this.addListener(mxEvent.FIRE_MOUSE_EVENT, mxUtils.bind(this, function(sender, evt) - { - if (evt.getProperty('eventName') == 'mouseDown' && this.isEnabled()) - { - var me = evt.getProperty('event'); - var state = me.getState(); - - if (!mxEvent.isAltDown(me.getEvent()) && state != null) - { - // Checks if state was removed in call to stopEditing above - if (this.model.isEdge(state.cell)) - { - start.point = new mxPoint(me.getGraphX(), me.getGraphY()); - start.selected = this.isCellSelected(state.cell); - start.state = state; - start.event = me; - - if (state.text != null && state.text.boundingBox != null && - mxUtils.contains(state.text.boundingBox, me.getGraphX(), me.getGraphY())) - { - start.handle = mxEvent.LABEL_HANDLE; - } - else - { - var handler = this.selectionCellsHandler.getHandler(state.cell); - - if (handler != null && handler.bends != null && handler.bends.length > 0) - { - start.handle = handler.getHandleForEvent(me); - } - } - } - else if (!this.panningHandler.isActive() && !mxEvent.isControlDown(me.getEvent())) - { - var handler = this.selectionCellsHandler.getHandler(state.cell); - - // Cell handles have precedence over row and col resize - if (handler == null || handler.getHandleForEvent(me) == null) - { - var box = new mxRectangle(me.getGraphX() - 1, me.getGraphY() - 1); - box.grow(mxEvent.isTouchEvent(me.getEvent()) ? - mxShape.prototype.svgStrokeTolerance - 1 : - (mxShape.prototype.svgStrokeTolerance + 1) / 2); - - if (this.isTableCell(state.cell) && !this.isCellSelected(state.cell)) - { - var row = this.model.getParent(state.cell); - var table = this.model.getParent(row); - - if (!this.isCellSelected(table)) - { - if ((mxUtils.intersects(box, new mxRectangle(state.x, state.y - 2, state.width, 3)) && - this.model.getChildAt(table, 0) != row) || mxUtils.intersects(box, new mxRectangle( - state.x, state.y + state.height - 2, state.width, 3)) || - (mxUtils.intersects(box, new mxRectangle(state.x - 2, state.y, 2, state.height)) && - this.model.getChildAt(row, 0) != state.cell) || mxUtils.intersects(box, new mxRectangle( - state.x + state.width - 2, state.y, 2, state.height))) - { - var wasSelected = this.selectionCellsHandler.isHandled(table); - this.selectCellForEvent(table, me.getEvent()); - handler = this.selectionCellsHandler.getHandler(table); - - if (handler != null) - { - var handle = handler.getHandleForEvent(me); - - if (handle != null) - { - handler.start(me.getGraphX(), me.getGraphY(), handle); - handler.blockDelayedSelection = !wasSelected; - me.consume(); - } - } - } - } - } - - // Hover for swimlane start sizes inside tables - var current = state; - - while (!me.isConsumed() && current != null && (this.isTableCell(current.cell) || - this.isTableRow(current.cell) || this.isTable(current.cell))) - { - if (this.isSwimlane(current.cell)) - { - var offset = this.getActualStartSize(current.cell); - var s = this.view.scale; - - if (((offset.x > 0 || offset.width > 0) && mxUtils.intersects(box, new mxRectangle( - current.x + (offset.x - offset.width - 1) * s + ((offset.x == 0) ? current.width : 0), - current.y, 1, current.height))) || ((offset.y > 0 || offset.height > 0) && - mxUtils.intersects(box, new mxRectangle(current.x, current.y + (offset.y - - offset.height - 1) * s + ((offset.y == 0) ? current.height : 0), current.width, 1)))) - { - this.selectCellForEvent(current.cell, me.getEvent()); - handler = this.selectionCellsHandler.getHandler(current.cell); - - if (handler != null) - { - // Swimlane start size handle is last custom handle - var handle = mxEvent.CUSTOM_HANDLE - handler.customHandles.length + 1; - handler.start(me.getGraphX(), me.getGraphY(), handle); - me.consume(); - } - } - } - - current = this.view.getState(this.model.getParent(current.cell)); - } - } - } - } - } - })); - - var mouseDown = null; - - this.addMouseListener( - { - mouseDown: function(sender, me) {}, - mouseMove: mxUtils.bind(this, function(sender, me) - { - // Checks if any other handler is active - var handlerMap = this.selectionCellsHandler.handlers.map; - - for (var key in handlerMap) - { - if (handlerMap[key].index != null) - { - return; - } - } - - if (this.isEnabled() && !this.panningHandler.isActive() && !mxEvent.isAltDown(me.getEvent())) - { - var tol = this.tolerance; - - if (start.point != null && start.state != null && start.event != null) - { - var state = start.state; - - if (Math.abs(start.point.x - me.getGraphX()) > tol || - Math.abs(start.point.y - me.getGraphY()) > tol) - { - var handler = this.selectionCellsHandler.getHandler(state.cell); - - if (handler == null && this.model.isEdge(state.cell)) - { - handler = this.createHandler(state); - } - - if (handler != null && handler.bends != null && handler.bends.length > 0) - { - var handle = handler.getHandleForEvent(start.event); - var edgeStyle = this.view.getEdgeStyle(state); - var entity = edgeStyle == mxEdgeStyle.EntityRelation; - - // Handles special case where label was clicked on unselected edge in which - // case the label will be moved regardless of the handle that is returned - if (!start.selected && start.handle == mxEvent.LABEL_HANDLE) - { - handle = start.handle; - } - - if (!entity || handle == 0 || handle == handler.bends.length - 1 || handle == mxEvent.LABEL_HANDLE) - { - // Source or target handle or connected for direct handle access or orthogonal line - // with just two points where the central handle is moved regardless of mouse position - if (handle == mxEvent.LABEL_HANDLE || handle == 0 || state.visibleSourceState != null || - handle == handler.bends.length - 1 || state.visibleTargetState != null) - { - if (!entity && handle != mxEvent.LABEL_HANDLE) - { - var pts = state.absolutePoints; - - // Default case where handles are at corner points handles - // drag of corner as drag of existing point - if (pts != null && ((edgeStyle == null && handle == null) || - edgeStyle == mxEdgeStyle.OrthConnector)) - { - // Does not use handles if they were not initially visible - handle = start.handle; - - if (handle == null) - { - var box = new mxRectangle(start.point.x, start.point.y); - box.grow(mxEdgeHandler.prototype.handleImage.width / 2); - - if (mxUtils.contains(box, pts[0].x, pts[0].y)) - { - // Moves source terminal handle - handle = 0; - } - else if (mxUtils.contains(box, pts[pts.length - 1].x, pts[pts.length - 1].y)) - { - // Moves target terminal handle - handle = handler.bends.length - 1; - } - else - { - // Checks if edge has no bends - var nobends = edgeStyle != null && (pts.length == 2 || (pts.length == 3 && - ((Math.round(pts[0].x - pts[1].x) == 0 && Math.round(pts[1].x - pts[2].x) == 0) || - (Math.round(pts[0].y - pts[1].y) == 0 && Math.round(pts[1].y - pts[2].y) == 0)))); - - if (nobends) - { - // Moves central handle for straight orthogonal edges - handle = 2; - } - else - { - // Finds and moves vertical or horizontal segment - handle = mxUtils.findNearestSegment(state, start.point.x, start.point.y); - - // Converts segment to virtual handle index - if (edgeStyle == null) - { - handle = mxEvent.VIRTUAL_HANDLE - handle; - } - // Maps segment to handle - else - { - handle += 1; - } - } - } - } - } - - // Creates a new waypoint and starts moving it - if (handle == null) - { - handle = mxEvent.VIRTUAL_HANDLE; - } - } - - handler.start(me.getGraphX(), me.getGraphX(), handle); - me.consume(); - - // Removes preview rectangle in graph handler - this.graphHandler.reset(); - } - } - else if (entity && (state.visibleSourceState != null || state.visibleTargetState != null)) - { - // Disables moves on entity to make it consistent - this.graphHandler.reset(); - me.consume(); - } - } - - if (handler != null) - { - // Lazy selection for edges inside groups - if (this.selectionCellsHandler.isHandlerActive(handler)) - { - if (!this.isCellSelected(state.cell)) - { - this.selectionCellsHandler.handlers.put(state.cell, handler); - this.selectCellForEvent(state.cell, me.getEvent()); - } - } - else if (!this.isCellSelected(state.cell)) - { - // Destroy temporary handler - handler.destroy(); - } - } - - // Reset start state - start.selected = false; - start.handle = null; - start.state = null; - start.event = null; - start.point = null; - } - } - else - { - // Updates cursor for unselected edges under the mouse - var state = me.getState(); - - if (state != null) - { - var cursor = null; - - // Checks if state was removed in call to stopEditing above - if (this.model.isEdge(state.cell)) - { - var box = new mxRectangle(me.getGraphX(), me.getGraphY()); - box.grow(mxEdgeHandler.prototype.handleImage.width / 2); - var pts = state.absolutePoints; - - if (pts != null) - { - if (state.text != null && state.text.boundingBox != null && - mxUtils.contains(state.text.boundingBox, me.getGraphX(), me.getGraphY())) - { - cursor = 'move'; - } - else if (mxUtils.contains(box, pts[0].x, pts[0].y) || - mxUtils.contains(box, pts[pts.length - 1].x, pts[pts.length - 1].y)) - { - cursor = 'pointer'; - } - else if (state.visibleSourceState != null || state.visibleTargetState != null) - { - // Moving is not allowed for entity relation but still indicate hover state - var tmp = this.view.getEdgeStyle(state); - cursor = 'crosshair'; - - if (tmp != mxEdgeStyle.EntityRelation && this.isOrthogonal(state)) - { - var idx = mxUtils.findNearestSegment(state, me.getGraphX(), me.getGraphY()); - - if (idx < pts.length - 1 && idx >= 0) - { - cursor = (Math.round(pts[idx].x - pts[idx + 1].x) == 0) ? - 'col-resize' : 'row-resize'; - } - } - } - } - } - else if (!mxEvent.isControlDown(me.getEvent())) - { - var box = new mxRectangle(me.getGraphX() - 1, me.getGraphY() - 1); - box.grow(mxShape.prototype.svgStrokeTolerance / 2); - - if (this.isTableCell(state.cell)) - { - var row = this.model.getParent(state.cell); - var table = this.model.getParent(row); - - if (!this.isCellSelected(table)) - { - if ((mxUtils.intersects(box, new mxRectangle(state.x - 2, state.y, 2, state.height)) && - this.model.getChildAt(row, 0) != state.cell) || mxUtils.intersects(box, - new mxRectangle(state.x + state.width - 2, state.y, 2, state.height))) - { - cursor ='col-resize'; - } - else if ((mxUtils.intersects(box, new mxRectangle(state.x, state.y - 2, state.width, 3)) && - this.model.getChildAt(table, 0) != row) || mxUtils.intersects(box, - new mxRectangle(state.x, state.y + state.height - 2, state.width, 3))) - { - cursor ='row-resize'; - } - } - } - - // Hover for swimlane start sizes inside tables - var current = state; - - while (cursor == null && current != null && (this.isTableCell(current.cell) || - this.isTableRow(current.cell) || this.isTable(current.cell))) - { - if (this.isSwimlane(current.cell)) - { - var offset = this.getActualStartSize(current.cell); - var s = this.view.scale; - - if ((offset.x > 0 || offset.width > 0) && mxUtils.intersects(box, new mxRectangle( - current.x + (offset.x - offset.width - 1) * s + ((offset.x == 0) ? current.width * s : 0), - current.y, 1, current.height))) - { - cursor ='col-resize'; - } - else if ((offset.y > 0 || offset.height > 0) && mxUtils.intersects(box, new mxRectangle( - current.x, current.y + (offset.y - offset.height - 1) * s + ((offset.y == 0) ? current.height : 0), - current.width, 1))) - { - cursor ='row-resize'; - } - } - - current = this.view.getState(this.model.getParent(current.cell)); - } - } - - if (cursor != null) - { - state.setCursor(cursor); - } - } - } - } - }), - mouseUp: mxUtils.bind(this, function(sender, me) - { - start.state = null; - start.event = null; - start.point = null; - start.handle = null; - }) - }); - } - - // HTML entities are displayed as plain text in wrapped plain text labels - this.cellRenderer.getLabelValue = function(state) - { - var result = mxCellRenderer.prototype.getLabelValue.apply(this, arguments); - - if (state.view.graph.isHtmlLabel(state.cell)) - { - if (state.style['html'] != 1) - { - result = mxUtils.htmlEntities(result, false); - } - else - { - result = state.view.graph.sanitizeHtml(result); - } - } - - return result; - }; - - // All code below not available and not needed in embed mode - if (typeof mxVertexHandler !== 'undefined') - { - this.setConnectable(true); - this.setDropEnabled(true); - this.setPanning(true); - this.setTooltips(true); - this.setAllowLoops(true); - this.allowAutoPanning = true; - this.resetEdgesOnConnect = false; - this.constrainChildren = false; - this.constrainRelativeChildren = true; - - // Do not scroll after moving cells - this.graphHandler.scrollOnMove = false; - this.graphHandler.scaleGrid = true; - - // Disables cloning of connection sources by default - this.connectionHandler.setCreateTarget(false); - this.connectionHandler.insertBeforeSource = true; - - // Disables built-in connection starts - this.connectionHandler.isValidSource = function(cell, me) - { - return false; - }; - - // Sets the style to be used when an elbow edge is double clicked - this.alternateEdgeStyle = 'vertical'; - - if (stylesheet == null) - { - this.loadStylesheet(); - } - - // Adds page centers to the guides for moving cells - var graphHandlerGetGuideStates = this.graphHandler.getGuideStates; - this.graphHandler.getGuideStates = function() - { - var result = graphHandlerGetGuideStates.apply(this, arguments); - - // Create virtual cell state for page centers - if (this.graph.pageVisible) - { - var guides = []; - - var pf = this.graph.pageFormat; - var ps = this.graph.pageScale; - var pw = pf.width * ps; - var ph = pf.height * ps; - var t = this.graph.view.translate; - var s = this.graph.view.scale; - - var layout = this.graph.getPageLayout(); - - for (var i = 0; i < layout.width; i++) - { - guides.push(new mxRectangle(((layout.x + i) * pw + t.x) * s, - (layout.y * ph + t.y) * s, pw * s, ph * s)); - } - - for (var j = 1; j < layout.height; j++) - { - guides.push(new mxRectangle((layout.x * pw + t.x) * s, - ((layout.y + j) * ph + t.y) * s, pw * s, ph * s)); - } - - // Page center guides have precedence over normal guides - result = guides.concat(result); - } - - return result; - }; - - // Overrides zIndex for dragElement - mxDragSource.prototype.dragElementZIndex = mxPopupMenu.prototype.zIndex; - - // Overrides color for virtual guides for page centers - mxGuide.prototype.getGuideColor = function(state, horizontal) - { - return (state.cell == null) ? '#ffa500' /* orange */ : mxConstants.GUIDE_COLOR; - }; - - // Changes color of move preview for black backgrounds - this.graphHandler.createPreviewShape = function(bounds) - { - this.previewColor = (this.graph.background == '#000000') ? '#ffffff' : mxGraphHandler.prototype.previewColor; - - return mxGraphHandler.prototype.createPreviewShape.apply(this, arguments); - }; - - // Handles parts of cells by checking if part=1 is in the style and returning the parent - // if the parent is not already in the list of cells. container style is used to disable - // step into swimlanes and dropTarget style is used to disable acting as a drop target. - // LATER: Handle recursive parts - var graphHandlerGetCells = this.graphHandler.getCells; - - this.graphHandler.getCells = function(initialCell) - { - var cells = graphHandlerGetCells.apply(this, arguments); - var lookup = new mxDictionary(); - var newCells = []; - - for (var i = 0; i < cells.length; i++) - { - // Propagates to composite parents or moves selected table rows - var cell = (this.graph.isTableCell(initialCell) && - this.graph.isTableCell(cells[i]) && - this.graph.isCellSelected(cells[i])) ? - this.graph.model.getParent(cells[i]) : - ((this.graph.isTableRow(initialCell) && - this.graph.isTableRow(cells[i]) && - this.graph.isCellSelected(cells[i])) ? - cells[i] : this.graph.getCompositeParent(cells[i])); - - if (cell != null && !lookup.get(cell)) - { - lookup.put(cell, true); - newCells.push(cell); - } - } - - return newCells; - }; - - // Handles parts and selected rows in tables of cells for drag and drop - var graphHandlerStart = this.graphHandler.start; - - this.graphHandler.start = function(cell, x, y, cells) - { - // Propagates to selected table row to start move - var ignoreParent = false; - - if (this.graph.isTableCell(cell)) - { - if (!this.graph.isCellSelected(cell)) - { - cell = this.graph.model.getParent(cell); - } - else - { - ignoreParent = true; - } - } - - if (!ignoreParent && (!this.graph.isTableRow(cell) || !this.graph.isCellSelected(cell))) - { - cell = this.graph.getCompositeParent(cell); - } - - graphHandlerStart.apply(this, arguments); - }; - - // Handles parts of cells when cloning the source for new connections - this.connectionHandler.createTargetVertex = function(evt, source) - { - source = this.graph.getCompositeParent(source); - - return mxConnectionHandler.prototype.createTargetVertex.apply(this, arguments); - }; - - var rubberband = new mxRubberband(this); - - this.getRubberband = function() - { - return rubberband; - }; - - // Timer-based activation of outline connect in connection handler - var startTime = new Date().getTime(); - var timeOnTarget = 0; - - var connectionHandlerMouseMove = this.connectionHandler.mouseMove; - - this.connectionHandler.mouseMove = function() - { - var prev = this.currentState; - connectionHandlerMouseMove.apply(this, arguments); - - if (prev != this.currentState) - { - startTime = new Date().getTime(); - timeOnTarget = 0; - } - else - { - timeOnTarget = new Date().getTime() - startTime; - } - }; - - // Activates outline connect after 1500ms with touch event or if alt is pressed inside the shape - // outlineConnect=0 is a custom style that means do not connect to strokes inside the shape, - // or in other words, connect to the shape's perimeter if the highlight is under the mouse - // (the name is because the highlight, including all strokes, is called outline in the code) - var connectionHandleIsOutlineConnectEvent = this.connectionHandler.isOutlineConnectEvent; - - this.connectionHandler.isOutlineConnectEvent = function(me) - { - return (this.currentState != null && me.getState() == this.currentState && timeOnTarget > 2000) || - ((this.currentState == null || mxUtils.getValue(this.currentState.style, 'outlineConnect', '1') != '0') && - connectionHandleIsOutlineConnectEvent.apply(this, arguments)); - }; - - // Adds shift+click to toggle selection state - var isToggleEvent = this.isToggleEvent; - this.isToggleEvent = function(evt) - { - return isToggleEvent.apply(this, arguments) || (!mxClient.IS_CHROMEOS && mxEvent.isShiftDown(evt)); - }; - - // Workaround for Firefox where first mouse down is received - // after tap and hold if scrollbars are visible, which means - // start rubberband immediately if no cell is under mouse. - var isForceRubberBandEvent = rubberband.isForceRubberbandEvent; - rubberband.isForceRubberbandEvent = function(me) - { - return (isForceRubberBandEvent.apply(this, arguments) && !mxEvent.isShiftDown(me.getEvent()) && - !mxEvent.isControlDown(me.getEvent())) || (mxClient.IS_CHROMEOS && mxEvent.isShiftDown(me.getEvent())) || - (mxUtils.hasScrollbars(this.graph.container) && mxClient.IS_FF && - mxClient.IS_WIN && me.getState() == null && mxEvent.isTouchEvent(me.getEvent())); - }; - - // Shows hand cursor while panning - var prevCursor = null; - - this.panningHandler.addListener(mxEvent.PAN_START, mxUtils.bind(this, function() - { - if (this.isEnabled()) - { - prevCursor = this.container.style.cursor; - this.container.style.cursor = 'move'; - } - })); - - this.panningHandler.addListener(mxEvent.PAN_END, mxUtils.bind(this, function() - { - if (this.isEnabled()) - { - this.container.style.cursor = prevCursor; - } - })); - - this.popupMenuHandler.autoExpand = true; - - this.popupMenuHandler.isSelectOnPopup = function(me) - { - return mxEvent.isMouseEvent(me.getEvent()); - }; - - // Handles links if graph is read-only or cell is locked - var click = this.click; - this.click = function(me) - { - var locked = me.state == null && me.sourceState != null && - this.isCellLocked(me.sourceState.cell); - - if ((!this.isEnabled() || locked) && !me.isConsumed()) - { - var cell = (locked) ? me.sourceState.cell : me.getCell(); - - if (cell != null) - { - var link = this.getClickableLinkForCell(cell); - - if (link != null) - { - if (this.isCustomLink(link)) - { - this.customLinkClicked(link); - } - else - { - this.openLink(link); - } - } - } - - if (this.isEnabled() && locked) - { - this.clearSelection(); - } - } - else - { - return click.apply(this, arguments); - } - }; - - // Redirects tooltips for locked cells - this.tooltipHandler.getStateForEvent = function(me) - { - return me.sourceState; - }; - - // Opens links in tooltips in new windows - var tooltipHandlerShow = this.tooltipHandler.show; - this.tooltipHandler.show = function() - { - tooltipHandlerShow.apply(this, arguments); - - if (this.div != null) - { - var links = this.div.getElementsByTagName('a'); - - for (var i = 0; i < links.length; i++) - { - if (links[i].getAttribute('href') != null && - links[i].getAttribute('target') == null) - { - links[i].setAttribute('target', '_blank'); - } - } - } - }; - - // Redirects tooltips for locked cells - this.tooltipHandler.getStateForEvent = function(me) - { - return me.sourceState; - }; - - // Redirects cursor for locked cells - var getCursorForMouseEvent = this.getCursorForMouseEvent; - this.getCursorForMouseEvent = function(me) - { - var locked = me.state == null && me.sourceState != null && this.isCellLocked(me.sourceState.cell); - - return this.getCursorForCell((locked) ? me.sourceState.cell : me.getCell()); - }; - - // Shows pointer cursor for clickable cells with links - // ie. if the graph is disabled and cells cannot be selected - var getCursorForCell = this.getCursorForCell; - this.getCursorForCell = function(cell) - { - if (!this.isEnabled() || this.isCellLocked(cell)) - { - var link = this.getClickableLinkForCell(cell); - - if (link != null) - { - return 'pointer'; - } - else if (this.isCellLocked(cell)) - { - return 'default'; - } - } - - return getCursorForCell.apply(this, arguments); - }; - - // Changes rubberband selection ignore locked cells - this.selectRegion = function(rect, evt) - { - var cells = this.getCells(rect.x, rect.y, rect.width, rect.height, null, null, null, function(state) - { - return mxUtils.getValue(state.style, 'locked', '0') == '1'; - }, true); - - this.selectCellsForEvent(cells, evt); - - return cells; - }; - - // Never removes cells from parents that are being moved - var graphHandlerShouldRemoveCellsFromParent = this.graphHandler.shouldRemoveCellsFromParent; - this.graphHandler.shouldRemoveCellsFromParent = function(parent, cells, evt) - { - if (this.graph.isCellSelected(parent)) - { - return false; - } - - return graphHandlerShouldRemoveCellsFromParent.apply(this, arguments); - }; - - // Unlocks all cells - this.isCellLocked = function(cell) - { - var pState = this.view.getState(cell); - - while (pState != null) - { - if (mxUtils.getValue(pState.style, 'locked', '0') == '1') - { - return true; - } - - pState = this.view.getState(this.model.getParent(pState.cell)); - } - - return false; - }; - - var tapAndHoldSelection = null; - - // Uses this event to process mouseDown to check the selection state before it is changed - this.addListener(mxEvent.FIRE_MOUSE_EVENT, mxUtils.bind(this, function(sender, evt) - { - if (evt.getProperty('eventName') == 'mouseDown') - { - var me = evt.getProperty('event'); - var state = me.getState(); - - if (state != null && !this.isSelectionEmpty() && !this.isCellSelected(state.cell)) - { - tapAndHoldSelection = this.getSelectionCells(); - } - else - { - tapAndHoldSelection = null; - } - } - })); - - // Tap and hold on background starts rubberband for multiple selected - // cells the cell associated with the event is deselected - this.addListener(mxEvent.TAP_AND_HOLD, mxUtils.bind(this, function(sender, evt) - { - if (!mxEvent.isMultiTouchEvent(evt)) - { - var me = evt.getProperty('event'); - var cell = evt.getProperty('cell'); - - if (cell == null) - { - var pt = mxUtils.convertPoint(this.container, - mxEvent.getClientX(me), mxEvent.getClientY(me)); - rubberband.start(pt.x, pt.y); - } - else if (tapAndHoldSelection != null) - { - this.addSelectionCells(tapAndHoldSelection); - } - else if (this.getSelectionCount() > 1 && this.isCellSelected(cell)) - { - this.removeSelectionCell(cell); - } - - // Blocks further processing of the event - tapAndHoldSelection = null; - evt.consume(); - } - })); - - // On connect the target is selected and we clone the cell of the preview edge for insert - this.connectionHandler.selectCells = function(edge, target) - { - this.graph.setSelectionCell(target || edge); - }; - - // Shows connection points only if cell not selected and parent table not handled - this.connectionHandler.constraintHandler.isStateIgnored = function(state, source) - { - var graph = state.view.graph; - - return source && (graph.isCellSelected(state.cell) || (graph.isTableRow(state.cell) && - graph.selectionCellsHandler.isHandled(graph.model.getParent(state.cell)))); - }; - - // Updates constraint handler if the selection changes - this.selectionModel.addListener(mxEvent.CHANGE, mxUtils.bind(this, function() - { - var ch = this.connectionHandler.constraintHandler; - - if (ch.currentFocus != null && ch.isStateIgnored(ch.currentFocus, true)) - { - ch.currentFocus = null; - ch.constraints = null; - ch.destroyIcons(); - } - - ch.destroyFocusHighlight(); - })); - - // Initializes touch interface - if (Graph.touchStyle) - { - this.initTouch(); - } - - /** - * Adds locking - */ - var graphUpdateMouseEvent = this.updateMouseEvent; - this.updateMouseEvent = function(me) - { - me = graphUpdateMouseEvent.apply(this, arguments); - - if (me.state != null && this.isCellLocked(me.getCell())) - { - me.state = null; - } - - return me; - }; - } - - //Create a unique offset object for each graph instance. - this.currentTranslate = new mxPoint(0, 0); -}; - -/** - * Specifies if the touch UI should be used (cannot detect touch in FF so always on for Windows/Linux) - */ -Graph.touchStyle = mxClient.IS_TOUCH || (mxClient.IS_FF && mxClient.IS_WIN) || navigator.maxTouchPoints > 0 || - navigator.msMaxTouchPoints > 0 || window.urlParams == null || urlParams['touch'] == '1'; - -/** - * Shortcut for capability check. - */ -Graph.fileSupport = window.File != null && window.FileReader != null && window.FileList != null && - (window.urlParams == null || urlParams['filesupport'] != '0'); - -/** - * Shortcut for capability check. - */ -Graph.translateDiagram = urlParams['translate-diagram'] == '1'; - -/** - * Shortcut for capability check. - */ -Graph.diagramLanguage = (urlParams['diagram-language'] != null) ? urlParams['diagram-language'] : mxClient.language; - -/** - * Default size for line jumps. - */ -Graph.lineJumpsEnabled = true; - -/** - * Default size for line jumps. - */ -Graph.defaultJumpSize = 6; - -/** - * Minimum width for table columns. - */ -Graph.minTableColumnWidth = 20; - -/** - * Minimum height for table rows. - */ -Graph.minTableRowHeight = 20; - -/** - * Text for foreign object warning. - */ -Graph.foreignObjectWarningText = 'Viewer does not support full SVG 1.1'; - -/** - * Link for foreign object warning. - */ -Graph.foreignObjectWarningLink = 'https://www.diagrams.net/doc/faq/svg-export-text-problems'; - -/** - * Minimum height for table rows. - */ -Graph.pasteStyles = ['rounded', 'shadow', 'dashed', 'dashPattern', 'fontFamily', 'fontSource', 'fontSize', 'fontColor', 'fontStyle', - 'align', 'verticalAlign', 'strokeColor', 'strokeWidth', 'fillColor', 'gradientColor', 'swimlaneFillColor', - 'textOpacity', 'gradientDirection', 'glass', 'labelBackgroundColor', 'labelBorderColor', 'opacity', - 'spacing', 'spacingTop', 'spacingLeft', 'spacingBottom', 'spacingRight', 'endFill', 'endArrow', - 'endSize', 'targetPerimeterSpacing', 'startFill', 'startArrow', 'startSize', 'sourcePerimeterSpacing', - 'arcSize', 'comic', 'sketch', 'fillWeight', 'hachureGap', 'hachureAngle', 'jiggle', 'disableMultiStroke', - 'disableMultiStrokeFill', 'fillStyle', 'curveFitting', 'simplification', 'comicStyle']; - -/** - * Helper function for creating SVG data URI. - */ -Graph.createSvgImage = function(w, h, data, coordWidth, coordHeight) -{ - var tmp = unescape(encodeURIComponent( - '' + - '' + data + '')); - - return new mxImage('data:image/svg+xml;base64,' + ((window.btoa) ? btoa(tmp) : Base64.encode(tmp, true)), w, h) -}; - -/** - * Removes all illegal control characters with ASCII code <32 except TAB, LF - * and CR. - */ -Graph.zapGremlins = function(text) -{ - var lastIndex = 0; - var checked = []; - - for (var i = 0; i < text.length; i++) - { - var code = text.charCodeAt(i); - - // Removes all control chars except TAB, LF and CR - if (!((code >= 32 || code == 9 || code == 10 || code == 13) && - code != 0xFFFF && code != 0xFFFE)) - { - checked.push(text.substring(lastIndex, i)); - lastIndex = i + 1; - } - } - - if (lastIndex > 0 && lastIndex < text.length) - { - checked.push(text.substring(lastIndex)); - } - - return (checked.length == 0) ? text : checked.join(''); -}; - -/** - * Turns the given string into an array. - */ -Graph.stringToBytes = function(str) -{ - var arr = new Array(str.length); - - for (var i = 0; i < str.length; i++) - { - arr[i] = str.charCodeAt(i); - } - - return arr; -}; - -/** - * Turns the given array into a string. - */ -Graph.bytesToString = function(arr) -{ - var result = new Array(arr.length); - - for (var i = 0; i < arr.length; i++) - { - result[i] = String.fromCharCode(arr[i]); - } - - return result.join(''); -}; - -/** - * Turns the given array into a string. - */ -Graph.base64EncodeUnicode = function(str) -{ - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { - return String.fromCharCode(parseInt(p1, 16)) - })); -}; - -/** - * Turns the given array into a string. - */ -Graph.base64DecodeUnicode = function(str) -{ - return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) { - return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) - }).join('')); -}; - -/** - * Returns a base64 encoded version of the compressed outer XML of the given node. - */ -Graph.compressNode = function(node, checked) -{ - var xml = mxUtils.getXml(node); - - return Graph.compress((checked) ? xml : Graph.zapGremlins(xml)); -}; - -/** - * Returns a base64 encoded version of the compressed string. - */ -Graph.compress = function(data, deflate) -{ - if (data == null || data.length == 0 || typeof(pako) === 'undefined') - { - return data; - } - else - { - var tmp = (deflate) ? pako.deflate(encodeURIComponent(data), {to: 'string'}) : - pako.deflateRaw(encodeURIComponent(data), {to: 'string'}); - - return (window.btoa) ? btoa(tmp) : Base64.encode(tmp, true); - } -}; - -/** - * Returns a decompressed version of the base64 encoded string. - */ -Graph.decompress = function(data, inflate, checked) -{ - if (data == null || data.length == 0 || typeof(pako) === 'undefined') - { - return data; - } - else - { - var tmp = (window.atob) ? atob(data) : Base64.decode(data, true); - - var inflated = decodeURIComponent((inflate) ? - pako.inflate(tmp, {to: 'string'}) : - pako.inflateRaw(tmp, {to: 'string'})); - - return (checked) ? inflated : Graph.zapGremlins(inflated); - } -}; - -/** - * Removes formatting from pasted HTML. - */ -Graph.removePasteFormatting = function(elt) -{ - while (elt != null) - { - if (elt.firstChild != null) - { - Graph.removePasteFormatting(elt.firstChild); - } - - if (elt.nodeType == mxConstants.NODETYPE_ELEMENT && elt.style != null) - { - elt.style.whiteSpace = ''; - - if (elt.style.color == '#000000') - { - elt.style.color = ''; - } - } - - elt = elt.nextSibling; - } -}; - -/** - * Sanitizes the given HTML markup. - */ -Graph.sanitizeHtml = function(value, editing) -{ - // Uses https://code.google.com/p/google-caja/wiki/JsHtmlSanitizer - // NOTE: Original minimized sanitizer was modified to support - // data URIs for images, mailto and special data:-links. - // LATER: Add MathML to whitelisted tags - function urlX(link) - { - if (link != null && link.toString().toLowerCase().substring(0, 11) !== 'javascript:') - { - return link; - } - - return null; - }; - function idX(id) { return id }; - - return html_sanitize(value, urlX, idX); -}; - -/** - * Returns the CSS font family from the given computed style. - */ -Graph.stripQuotes = function(text) -{ - if (text != null) - { - if (text.charAt(0) == '\'') - { - text = text.substring(1); - } - - if (text.charAt(text.length - 1) == '\'') - { - text = text.substring(0, text.length - 1); - } - - if (text.charAt(0) == '"') - { - text = text.substring(1); - } - - if (text.charAt(text.length - 1) == '"') - { - text = text.substring(0, text.length - 1); - } - } - - return text; -}; - -/** - * Returns true if the given string is a link. - * - * See https://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-a-url - */ -Graph.isLink = function(text) -{ - return text != null && Graph.linkPattern.test(text); -}; - -/** - * Regular expression for links. - */ -Graph.linkPattern = new RegExp('^(https?:\\/\\/)?'+ // protocol - '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name - '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address - '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path - '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string - '(\\#[-a-z\\d_]*)?$','i'); // fragment locator - -/** - * Graph inherits from mxGraph. - */ -mxUtils.extend(Graph, mxGraph); - -/** - * Allows all values in fit. - */ -Graph.prototype.minFitScale = null; - -/** - * Allows all values in fit. - */ -Graph.prototype.maxFitScale = null; - -/** - * Sets the policy for links. Possible values are "self" to replace any framesets, - * "blank" to load the URL in and "auto" (default). - */ -Graph.prototype.linkPolicy = (urlParams['target'] == 'frame') ? 'blank' : (urlParams['target'] || 'auto'); - -/** - * Target for links that open in a new window. Default is _blank. - */ -Graph.prototype.linkTarget = (urlParams['target'] == 'frame') ? '_self' : '_blank'; - -/** - * Value to the rel attribute of links. Default is 'nofollow noopener noreferrer'. - * NOTE: There are security implications when this is changed and if noopener is removed, - * then must be overridden to allow for the opener to be set by default. - */ -Graph.prototype.linkRelation = 'nofollow noopener noreferrer'; - -/** - * Scrollbars are enabled on non-touch devices (not including Firefox because touch events - * cannot be detected in Firefox, see above). - */ -Graph.prototype.defaultScrollbars = !mxClient.IS_IOS; - -/** - * Specifies if the page should be visible for new files. Default is true. - */ -Graph.prototype.defaultPageVisible = true; - -/** - * Specifies if the app should run in chromeless mode. Default is false. - * This default is only used if the contructor argument is null. - */ -Graph.prototype.lightbox = false; - -/** - * - */ -Graph.prototype.defaultPageBackgroundColor = '#ffffff'; - -/** - * - */ -Graph.prototype.defaultPageBorderColor = '#ffffff'; - -/** - * Specifies the size of the size for "tiles" to be used for a graph with - * scrollbars but no visible background page. A good value is large - * enough to reduce the number of repaints that is caused for auto- - * translation, which depends on this value, and small enough to give - * a small empty buffer around the graph. Default is 400x400. - */ -Graph.prototype.scrollTileSize = new mxRectangle(0, 0, 400, 400); - -/** - * Overrides the background color and paints a transparent background. - */ -Graph.prototype.transparentBackground = true; - -/** - * Sets global constants. - */ -Graph.prototype.selectParentAfterDelete = false; - -/** - * Sets the default target for all links in cells. - */ -Graph.prototype.defaultEdgeLength = 80; - -/** - * Disables move of bends/segments without selecting. - */ -Graph.prototype.edgeMode = false; - -/** - * Allows all values in fit. - */ -Graph.prototype.connectionArrowsEnabled = true; - -/** - * Specifies the regular expression for matching placeholders. - */ -Graph.prototype.placeholderPattern = new RegExp('%(date\{.*\}|[^%^\{^\}]+)%', 'g'); - -/** - * Specifies the regular expression for matching placeholders. - */ -Graph.prototype.absoluteUrlPattern = new RegExp('^(?:[a-z]+:)?//', 'i'); - -/** - * Specifies the default name for the theme. Default is 'default'. - */ -Graph.prototype.defaultThemeName = 'default'; - -/** - * Specifies the default name for the theme. Default is 'default'. - */ -Graph.prototype.defaultThemes = {}; - -/** - * Base URL for relative links. - */ -Graph.prototype.baseUrl = (urlParams['base'] != null) ? - decodeURIComponent(urlParams['base']) : - (((window != window.top) ? document.referrer : - document.location.toString()).split('#')[0]); - -/** - * Specifies if the label should be edited after an insert. - */ -Graph.prototype.editAfterInsert = false; - -/** - * Defines the built-in properties to be ignored in tooltips. - */ -Graph.prototype.builtInProperties = ['label', 'tooltip', 'placeholders', 'placeholder']; - -/** - * Defines if the graph is part of an EditorUi. If this is false the graph can - * be used in an EditorUi instance but will not have a UI added, functions - * overridden or event handlers added. - */ -Graph.prototype.standalone = false; - -/** - * Installs child layout styles. - */ -Graph.prototype.init = function(container) -{ - mxGraph.prototype.init.apply(this, arguments); - - // Intercepts links with no target attribute and opens in new window - this.cellRenderer.initializeLabel = function(state, shape) - { - mxCellRenderer.prototype.initializeLabel.apply(this, arguments); - - // Checks tolerance for clicks on links - var tol = state.view.graph.tolerance; - var handleClick = true; - var first = null; - - var down = mxUtils.bind(this, function(evt) - { - handleClick = true; - first = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - }); - - var move = mxUtils.bind(this, function(evt) - { - handleClick = handleClick && first != null && - Math.abs(first.x - mxEvent.getClientX(evt)) < tol && - Math.abs(first.y - mxEvent.getClientY(evt)) < tol; - }); - - var up = mxUtils.bind(this, function(evt) - { - if (handleClick) - { - var elt = mxEvent.getSource(evt) - - while (elt != null && elt != shape.node) - { - if (elt.nodeName.toLowerCase() == 'a') - { - state.view.graph.labelLinkClicked(state, elt, evt); - break; - } - - elt = elt.parentNode; - } - } - }); - - mxEvent.addGestureListeners(shape.node, down, move, up); - mxEvent.addListener(shape.node, 'click', function(evt) - { - mxEvent.consume(evt); - }); - }; - - this.initLayoutManager(); -}; - -/** - * Implements zoom and offset via CSS transforms. This is currently only used - * in read-only as there are fewer issues with the mxCellState not being scaled - * and translated. - * - * KNOWN ISSUES TO FIX: - * - Apply CSS transforms to HTML labels in IE11 - */ -(function() -{ - /** - * Uses CSS transforms for scale and translate. - */ - Graph.prototype.useCssTransforms = false; - - /** - * Contains the scale. - */ - Graph.prototype.currentScale = 1; - - /** - * Contains the offset. - */ - Graph.prototype.currentTranslate = new mxPoint(0, 0); - - /** - * - */ - Graph.prototype.getVerticesAndEdges = function(vertices, edges) - { - vertices = (vertices != null) ? vertices : true; - edges = (edges != null) ? edges : true; - var model = this.model; - - return model.filterDescendants(function(cell) - { - return (vertices && model.isVertex(cell)) || (edges && model.isEdge(cell)); - }, model.getRoot()); - }; - - /** - * Returns the cell for editing the given cell. - */ - Graph.prototype.getStartEditingCell = function(cell, trigger) - { - // Redirect editing for tables - var style = this.getCellStyle(cell); - var size = parseInt(mxUtils.getValue(style, mxConstants.STYLE_STARTSIZE, 0)); - - if (this.isTable(cell) && (!this.isSwimlane(cell) || - size == 0) && this.getLabel(cell) == '' && - this.model.getChildCount(cell) > 0) - { - cell = this.model.getChildAt(cell, 0); - - style = this.getCellStyle(cell); - size = parseInt(mxUtils.getValue(style, mxConstants.STYLE_STARTSIZE, 0)); - } - - // Redirect editing for table rows - if (this.isTableRow(cell) && (!this.isSwimlane(cell) || - size == 0) && this.getLabel(cell) == '' && - this.model.getChildCount(cell) > 0) - { - for (var i = 0; i < this.model.getChildCount(cell); i++) - { - var temp = this.model.getChildAt(cell, i); - - if (this.isCellEditable(temp)) - { - cell = temp; - break; - } - } - } - - return cell; - }; - - /** - * Returns true if fast zoom preview should be used. - */ - Graph.prototype.copyStyle = function(cell) - { - var style = null; - - if (cell != null) - { - style = mxUtils.clone(this.getCurrentCellStyle(cell)); - - // Handles special case for value "none" - var cellStyle = this.model.getStyle(cell); - var tokens = (cellStyle != null) ? cellStyle.split(';') : []; - - for (var j = 0; j < tokens.length; j++) - { - var tmp = tokens[j]; - var pos = tmp.indexOf('='); - - if (pos >= 0) - { - var key = tmp.substring(0, pos); - var value = tmp.substring(pos + 1); - - if (style[key] == null && value == mxConstants.NONE) - { - style[key] = mxConstants.NONE; - } - } - } - } - - return style; - }; - - /** - * Returns true if fast zoom preview should be used. - */ - Graph.prototype.pasteStyle = function(style, cells, keys) - { - keys = (keys != null) ? keys : Graph.pasteStyles; - - this.model.beginUpdate(); - try - { - for (var i = 0; i < cells.length; i++) - { - var temp = this.getCurrentCellStyle(cells[i]); - - for (var j = 0; j < keys.length; j++) - { - var current = temp[keys[j]]; - var value = style[keys[j]]; - - if (current != value && (current != null || value != mxConstants.NONE)) - { - this.setCellStyles(keys[j], value, [cells[i]]); - } - } - } - } - finally - { - this.model.endUpdate(); - } - }; - - /** - * Returns true if fast zoom preview should be used. - */ - Graph.prototype.isFastZoomEnabled = function() - { - return urlParams['zoom'] != 'nocss' && !mxClient.NO_FO && !mxClient.IS_EDGE && - !this.useCssTransforms && this.isCssTransformsSupported(); - }; - - /** - * Only foreignObject supported for now (no IE11). Safari disabled as it ignores - * overflow visible on foreignObject in negative space (lightbox and viewer). - * Check the following test case on page 1 before enabling this in production: - * https://devhost.jgraph.com/git/drawio/etc/embed/sf-math-fo-clipping.html?dev=1 - */ - Graph.prototype.isCssTransformsSupported = function() - { - return this.dialect == mxConstants.DIALECT_SVG && !mxClient.NO_FO && - (!this.lightbox || !mxClient.IS_SF); - }; - - /** - * Function: getCellAt - * - * Needs to modify original method for recursive call. - */ - Graph.prototype.getCellAt = function(x, y, parent, vertices, edges, ignoreFn) - { - if (this.useCssTransforms) - { - x = x / this.currentScale - this.currentTranslate.x; - y = y / this.currentScale - this.currentTranslate.y; - } - - return this.getScaledCellAt.apply(this, arguments); - }; - - /** - * Function: getScaledCellAt - * - * Overridden for recursion. - */ - Graph.prototype.getScaledCellAt = function(x, y, parent, vertices, edges, ignoreFn) - { - vertices = (vertices != null) ? vertices : true; - edges = (edges != null) ? edges : true; - - if (parent == null) - { - parent = this.getCurrentRoot(); - - if (parent == null) - { - parent = this.getModel().getRoot(); - } - } - - if (parent != null) - { - var childCount = this.model.getChildCount(parent); - - for (var i = childCount - 1; i >= 0; i--) - { - var cell = this.model.getChildAt(parent, i); - var result = this.getScaledCellAt(x, y, cell, vertices, edges, ignoreFn); - - if (result != null) - { - return result; - } - else if (this.isCellVisible(cell) && (edges && this.model.isEdge(cell) || - vertices && this.model.isVertex(cell))) - { - var state = this.view.getState(cell); - - if (state != null && (ignoreFn == null || !ignoreFn(state, x, y)) && - this.intersects(state, x, y)) - { - return cell; - } - } - } - } - - return null; - }; - - /** - * Returns if the child cells of the given vertex cell state should be resized. - */ - Graph.prototype.isRecursiveVertexResize = function(state) - { - return !this.isSwimlane(state.cell) && this.model.getChildCount(state.cell) > 0 && - !this.isCellCollapsed(state.cell) && mxUtils.getValue(state.style, 'recursiveResize', '1') == '1' && - mxUtils.getValue(state.style, 'childLayout', null) == null; - } - - /** - * Returns the first parent that is not a part. - */ - Graph.prototype.isPart = function(cell) - { - return mxUtils.getValue(this.getCurrentCellStyle(cell), 'part', '0') == '1' || - this.isTableCell(cell) || this.isTableRow(cell); - }; - - /** - * Returns the first parent that is not a part. - */ - Graph.prototype.getCompositeParent = function(cell) - { - while (this.isPart(cell)) - { - var temp = this.model.getParent(cell); - - if (!this.model.isVertex(temp)) - { - break; - } - - cell = temp; - } - - return cell; - }; - - /** - * Function: repaint - * - * Updates the highlight after a change of the model or view. - */ - mxCellHighlight.prototype.getStrokeWidth = function(state) - { - var s = this.strokeWidth; - - if (this.graph.useCssTransforms) - { - s /= this.graph.currentScale; - } - - return s; - }; - - /** - * Function: getGraphBounds - * - * Overrides getGraphBounds to use bounding box from SVG. - */ - mxGraphView.prototype.getGraphBounds = function() - { - var b = this.graphBounds; - - if (this.graph.useCssTransforms) - { - var t = this.graph.currentTranslate; - var s = this.graph.currentScale; - - b = new mxRectangle( - (b.x + t.x) * s, (b.y + t.y) * s, - b.width * s, b.height * s); - } - - return b; - }; - - /** - * Overrides to bypass full cell tree validation. - * TODO: Check if this improves performance - */ - mxGraphView.prototype.viewStateChanged = function() - { - if (this.graph.useCssTransforms) - { - this.validate(); - this.graph.sizeDidChange(); - } - else - { - this.revalidate(); - this.graph.sizeDidChange(); - } - }; - - /** - * Overrides validate to normalize validation view state and pass - * current state to CSS transform. - */ - var graphViewValidate = mxGraphView.prototype.validate; - mxGraphView.prototype.validate = function(cell) - { - if (this.graph.useCssTransforms) - { - this.graph.currentScale = this.scale; - this.graph.currentTranslate.x = this.translate.x; - this.graph.currentTranslate.y = this.translate.y; - - this.scale = 1; - this.translate.x = 0; - this.translate.y = 0; - } - - graphViewValidate.apply(this, arguments); - - if (this.graph.useCssTransforms) - { - this.graph.updateCssTransform(); - - this.scale = this.graph.currentScale; - this.translate.x = this.graph.currentTranslate.x; - this.translate.y = this.graph.currentTranslate.y; - } - }; - - /** - * Overrides function to exclude table cells and rows from groups. - */ - var graphGetCellsForGroup = mxGraph.prototype.getCellsForGroup; - Graph.prototype.getCellsForGroup = function(cells) - { - cells = graphGetCellsForGroup.apply(this, arguments); - var result = []; - - // Filters selection cells with the same parent - for (var i = 0; i < cells.length; i++) - { - if (!this.isTableRow(cells[i]) && - !this.isTableCell(cells[i])) - { - result.push(cells[i]); - } - } - - return result; - }; - - /** - * Overrides function to exclude tables, rows and cells from ungrouping. - */ - var graphGetCellsForUngroup = mxGraph.prototype.getCellsForUngroup; - Graph.prototype.getCellsForUngroup = function(cells) - { - cells = graphGetCellsForUngroup.apply(this, arguments); - var result = []; - - // Filters selection cells with the same parent - for (var i = 0; i < cells.length; i++) - { - if (!this.isTable(cells[i]) && - !this.isTableRow(cells[i]) && - !this.isTableCell(cells[i])) - { - result.push(cells[i]); - } - } - - return result; - }; - - /** - * Function: updateCssTransform - * - * Zooms out of the graph by . - */ - Graph.prototype.updateCssTransform = function() - { - var temp = this.view.getDrawPane(); - - if (temp != null) - { - var g = temp.parentNode; - - if (!this.useCssTransforms) - { - g.removeAttribute('transformOrigin'); - g.removeAttribute('transform'); - } - else - { - var prev = g.getAttribute('transform'); - g.setAttribute('transformOrigin', '0 0'); - var s = Math.round(this.currentScale * 100) / 100; - var dx = Math.round(this.currentTranslate.x * 100) / 100; - var dy = Math.round(this.currentTranslate.y * 100) / 100; - g.setAttribute('transform', 'scale(' + s + ',' + s + ')' + - 'translate(' + dx + ',' + dy + ')'); - - // Applies workarounds only if translate has changed - if (prev != g.getAttribute('transform')) - { - try - { - // Applies transform to labels outside of the SVG DOM - // Excluded via isCssTransformsSupported - // if (mxClient.NO_FO) - // { - // var transform = 'scale(' + this.currentScale + ')' + 'translate(' + - // this.currentTranslate.x + 'px,' + this.currentTranslate.y + 'px)'; - // - // this.view.states.visit(mxUtils.bind(this, function(cell, state) - // { - // if (state.text != null && state.text.node != null) - // { - // // Stores initial CSS transform that is used for the label alignment - // if (state.text.originalTransform == null) - // { - // state.text.originalTransform = state.text.node.style.transform; - // } - // - // state.text.node.style.transform = transform + state.text.originalTransform; - // } - // })); - // } - // Workaround for https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/4320441/ - if (mxClient.IS_EDGE) - { - // Recommended workaround is to do this on all - // foreignObjects, but this seems to be faster - var val = g.style.display; - g.style.display = 'none'; - g.getBBox(); - g.style.display = val; - } - } - catch (e) - { - // ignore - } - } - } - } - }; - - var graphViewValidateBackgroundPage = mxGraphView.prototype.validateBackgroundPage; - mxGraphView.prototype.validateBackgroundPage = function() - { - var useCssTranforms = this.graph.useCssTransforms, scale = this.scale, - translate = this.translate; - - if (useCssTranforms) - { - this.scale = this.graph.currentScale; - this.translate = this.graph.currentTranslate; - } - - graphViewValidateBackgroundPage.apply(this, arguments); - - if (useCssTranforms) - { - this.scale = scale; - this.translate = translate; - } - }; - - var graphUpdatePageBreaks = mxGraph.prototype.updatePageBreaks; - mxGraph.prototype.updatePageBreaks = function(visible, width, height) - { - var useCssTranforms = this.useCssTransforms, scale = this.view.scale, - translate = this.view.translate; - - if (useCssTranforms) - { - this.view.scale = 1; - this.view.translate = new mxPoint(0, 0); - this.useCssTransforms = false; - } - - graphUpdatePageBreaks.apply(this, arguments); - - if (useCssTranforms) - { - this.view.scale = scale; - this.view.translate = translate; - this.useCssTransforms = true; - } - }; -})(); - -/** - * Sets the XML node for the current diagram. - */ -Graph.prototype.isLightboxView = function() -{ - return this.lightbox; -}; - -/** - * Sets the XML node for the current diagram. - */ -Graph.prototype.isViewer = function() -{ - return false; -}; - -/** - * Installs automatic layout via styles - */ -Graph.prototype.labelLinkClicked = function(state, elt, evt) -{ - var href = elt.getAttribute('href'); - - if (href != null && !this.isCustomLink(href) && ((mxEvent.isLeftMouseButton(evt) && - !mxEvent.isPopupTrigger(evt)) || mxEvent.isTouchEvent(evt))) - { - if (!this.isEnabled() || this.isCellLocked(state.cell)) - { - var target = this.isBlankLink(href) ? this.linkTarget : '_top'; - this.openLink(this.getAbsoluteUrl(href), target); - } - - mxEvent.consume(evt); - } -}; - -/** - * Returns the size of the page format scaled with the page size. - */ -Graph.prototype.openLink = function(href, target, allowOpener) -{ - var result = window; - - try - { - // Workaround for blocking in same iframe - if (target == '_self' && window != window.top) - { - window.location.href = href; - } - else - { - // Avoids page reload for anchors (workaround for IE but used everywhere) - if (href.substring(0, this.baseUrl.length) == this.baseUrl && - href.charAt(this.baseUrl.length) == '#' && - target == '_top' && window == window.top) - { - var hash = href.split('#')[1]; - - // Forces navigation if on same hash - if (window.location.hash == '#' + hash) - { - window.location.hash = ''; - } - - window.location.hash = hash; - } - else - { - result = window.open(href, (target != null) ? target : '_blank'); - - if (result != null && !allowOpener) - { - result.opener = null; - } - } - } - } - catch (e) - { - // ignores permission denied - } - - return result; -}; - -/** - * Adds support for page links. - */ -Graph.prototype.getLinkTitle = function(href) -{ - return href.substring(href.lastIndexOf('/') + 1); -}; - -/** - * Adds support for page links. - */ -Graph.prototype.isCustomLink = function(href) -{ - return href.substring(0, 5) == 'data:'; -}; - -/** - * Adds support for page links. - */ -Graph.prototype.customLinkClicked = function(link) -{ - return false; -}; - -/** - * Returns true if the given href references an external protocol that - * should never open in a new window. Default returns true for mailto. - */ -Graph.prototype.isExternalProtocol = function(href) -{ - return href.substring(0, 7) === 'mailto:'; -}; - -/** - * Hook for links to open in same window. Default returns true for anchors, - * links to same domain or if target == 'self' in the config. - */ -Graph.prototype.isBlankLink = function(href) -{ - return !this.isExternalProtocol(href) && - (this.linkPolicy === 'blank' || - (this.linkPolicy !== 'self' && - !this.isRelativeUrl(href) && - href.substring(0, this.domainUrl.length) !== this.domainUrl)); -}; - -/** - * - */ -Graph.prototype.isRelativeUrl = function(url) -{ - return url != null && !this.absoluteUrlPattern.test(url) && - url.substring(0, 5) !== 'data:' && - !this.isExternalProtocol(url); -}; - -/** - * - */ -Graph.prototype.getAbsoluteUrl = function(url) -{ - if (url != null && this.isRelativeUrl(url)) - { - if (url.charAt(0) == '#') - { - url = this.baseUrl + url; - } - else if (url.charAt(0) == '/') - { - url = this.domainUrl + url; - } - else - { - url = this.domainPathUrl + url; - } - } - - return url; -}; - -/** - * Installs automatic layout via styles - */ -Graph.prototype.initLayoutManager = function() -{ - this.layoutManager = new mxLayoutManager(this); - - this.layoutManager.hasLayout = function(cell, eventName) - { - return this.graph.getCellStyle(cell)['childLayout'] != null; - }; - - this.layoutManager.getLayout = function(cell, eventName) - { - var parent = this.graph.model.getParent(cell); - - // Executes layouts from top to bottom except for nested layouts where - // child layouts are executed before and after the parent layout runs - // in case the layout changes the size of the child cell - if (eventName != mxEvent.BEGIN_UPDATE || this.hasLayout(parent, eventName)) - { - var style = this.graph.getCellStyle(cell); - - if (style['childLayout'] == 'stackLayout') - { - var stackLayout = new mxStackLayout(this.graph, true); - stackLayout.resizeParentMax = mxUtils.getValue(style, 'resizeParentMax', '1') == '1'; - stackLayout.horizontal = mxUtils.getValue(style, 'horizontalStack', '1') == '1'; - stackLayout.resizeParent = mxUtils.getValue(style, 'resizeParent', '1') == '1'; - stackLayout.resizeLast = mxUtils.getValue(style, 'resizeLast', '0') == '1'; - stackLayout.spacing = style['stackSpacing'] || stackLayout.spacing; - stackLayout.border = style['stackBorder'] || stackLayout.border; - stackLayout.marginLeft = style['marginLeft'] || 0; - stackLayout.marginRight = style['marginRight'] || 0; - stackLayout.marginTop = style['marginTop'] || 0; - stackLayout.marginBottom = style['marginBottom'] || 0; - stackLayout.allowGaps = style['allowGaps'] || 0; - stackLayout.fill = true; - - if (stackLayout.allowGaps) - { - stackLayout.gridSize = parseFloat(mxUtils.getValue(style, 'stackUnitSize', 20)); - } - - return stackLayout; - } - else if (style['childLayout'] == 'treeLayout') - { - var treeLayout = new mxCompactTreeLayout(this.graph); - treeLayout.horizontal = mxUtils.getValue(style, 'horizontalTree', '1') == '1'; - treeLayout.resizeParent = mxUtils.getValue(style, 'resizeParent', '1') == '1'; - treeLayout.groupPadding = mxUtils.getValue(style, 'parentPadding', 20); - treeLayout.levelDistance = mxUtils.getValue(style, 'treeLevelDistance', 30); - treeLayout.maintainParentLocation = true; - treeLayout.edgeRouting = false; - treeLayout.resetEdges = false; - - return treeLayout; - } - else if (style['childLayout'] == 'flowLayout') - { - var flowLayout = new mxHierarchicalLayout(this.graph, mxUtils.getValue(style, - 'flowOrientation', mxConstants.DIRECTION_EAST)); - flowLayout.resizeParent = mxUtils.getValue(style, 'resizeParent', '1') == '1'; - flowLayout.parentBorder = mxUtils.getValue(style, 'parentPadding', 20); - flowLayout.maintainParentLocation = true; - - // Special undocumented styles for changing the hierarchical - flowLayout.intraCellSpacing = mxUtils.getValue(style, 'intraCellSpacing', - mxHierarchicalLayout.prototype.intraCellSpacing); - flowLayout.interRankCellSpacing = mxUtils.getValue(style, 'interRankCellSpacing', - mxHierarchicalLayout.prototype.interRankCellSpacing); - flowLayout.interHierarchySpacing = mxUtils.getValue(style, 'interHierarchySpacing', - mxHierarchicalLayout.prototype.interHierarchySpacing); - flowLayout.parallelEdgeSpacing = mxUtils.getValue(style, 'parallelEdgeSpacing', - mxHierarchicalLayout.prototype.parallelEdgeSpacing); - - return flowLayout; - } - else if (style['childLayout'] == 'circleLayout') - { - return new mxCircleLayout(this.graph); - } - else if (style['childLayout'] == 'organicLayout') - { - return new mxFastOrganicLayout(this.graph); - } - else if (style['childLayout'] == 'tableLayout') - { - return new TableLayout(this.graph); - } - } - - return null; - }; -}; - -/** - * Returns the size of the page format scaled with the page size. - */ -Graph.prototype.getPageSize = function() -{ - return (this.pageVisible) ? new mxRectangle(0, 0, this.pageFormat.width * this.pageScale, - this.pageFormat.height * this.pageScale) : this.scrollTileSize; -}; - -/** - * Returns a rectangle describing the position and count of the - * background pages, where x and y are the position of the top, - * left page and width and height are the vertical and horizontal - * page count. - */ -Graph.prototype.getPageLayout = function() -{ - var size = this.getPageSize(); - var bounds = this.getGraphBounds(); - - if (bounds.width == 0 || bounds.height == 0) - { - return new mxRectangle(0, 0, 1, 1); - } - else - { - var x0 = Math.floor(Math.ceil(bounds.x / this.view.scale - - this.view.translate.x) / size.width); - var y0 = Math.floor(Math.ceil(bounds.y / this.view.scale - - this.view.translate.y) / size.height); - var w0 = Math.ceil((Math.floor((bounds.x + bounds.width) / this.view.scale) - - this.view.translate.x) / size.width) - x0; - var h0 = Math.ceil((Math.floor((bounds.y + bounds.height) / this.view.scale) - - this.view.translate.y) / size.height) - y0; - - return new mxRectangle(x0, y0, w0, h0); - } -}; - -/** - * Sanitizes the given HTML markup. - */ -Graph.prototype.sanitizeHtml = function(value, editing) -{ - return Graph.sanitizeHtml(value, editing); -}; - -/** - * Revalidates all cells with placeholders in the current graph model. - */ -Graph.prototype.updatePlaceholders = function() -{ - var model = this.model; - var validate = false; - - for (var key in this.model.cells) - { - var cell = this.model.cells[key]; - - if (this.isReplacePlaceholders(cell)) - { - this.view.invalidate(cell, false, false); - validate = true; - } - } - - if (validate) - { - this.view.validate(); - } -}; - -/** - * Adds support for placeholders in labels. - */ -Graph.prototype.isReplacePlaceholders = function(cell) -{ - return cell.value != null && typeof(cell.value) == 'object' && - cell.value.getAttribute('placeholders') == '1'; -}; - -/** - * Returns true if the given mouse wheel event should be used for zooming. This - * is invoked if no dialogs are showing and returns true with Alt or Control - * (or cmd in macOS only) is pressed. - */ -Graph.prototype.isZoomWheelEvent = function(evt) -{ - return mxEvent.isAltDown(evt) || (mxEvent.isMetaDown(evt) && mxClient.IS_MAC) || - mxEvent.isControlDown(evt); -}; - -/** - * Returns true if the given scroll wheel event should be used for scrolling. - */ -Graph.prototype.isScrollWheelEvent = function(evt) -{ - return !this.isZoomWheelEvent(evt); -}; - -/** - * Adds Alt+click to select cells behind cells (Shift+Click on Chrome OS). - */ -Graph.prototype.isTransparentClickEvent = function(evt) -{ - return mxEvent.isAltDown(evt) || (mxClient.IS_CHROMEOS && mxEvent.isShiftDown(evt)); -}; - -/** - * Adds ctrl+shift+connect to disable connections. - */ -Graph.prototype.isIgnoreTerminalEvent = function(evt) -{ - return mxEvent.isShiftDown(evt) && mxEvent.isControlDown(evt); -}; - -/** - * Adds support for placeholders in labels. - */ -Graph.prototype.isSplitTarget = function(target, cells, evt) -{ - return !this.model.isEdge(cells[0]) && - !mxEvent.isAltDown(evt) && !mxEvent.isShiftDown(evt) && - mxGraph.prototype.isSplitTarget.apply(this, arguments); -}; - -/** - * Adds support for placeholders in labels. - */ -Graph.prototype.getLabel = function(cell) -{ - var result = mxGraph.prototype.getLabel.apply(this, arguments); - - if (result != null && this.isReplacePlaceholders(cell) && cell.getAttribute('placeholder') == null) - { - result = this.replacePlaceholders(cell, result); - } - - return result; -}; - -/** - * Adds labelMovable style. - */ -Graph.prototype.isLabelMovable = function(cell) -{ - var style = this.getCurrentCellStyle(cell); - - return !this.isCellLocked(cell) && - ((this.model.isEdge(cell) && this.edgeLabelsMovable) || - (this.model.isVertex(cell) && (this.vertexLabelsMovable || - mxUtils.getValue(style, 'labelMovable', '0') == '1'))); -}; - -/** - * Adds event if grid size is changed. - */ -Graph.prototype.setGridSize = function(value) -{ - this.gridSize = value; - this.fireEvent(new mxEventObject('gridSizeChanged')); -}; - -/** - * Adds event if default parent is changed. - */ -Graph.prototype.setDefaultParent = function(cell) -{ - this.defaultParent = cell; - this.fireEvent(new mxEventObject('defaultParentChanged')); -}; - -/** - * Function: getClickableLinkForCell - * - * Returns the first non-null link for the cell or its ancestors. - * - * Parameters: - * - * cell - whose link should be returned. - */ -Graph.prototype.getClickableLinkForCell = function(cell) -{ - do - { - var link = this.getLinkForCell(cell); - - if (link != null) - { - return link; - } - - cell = this.model.getParent(cell); - } while (cell != null); - - return null; -}; - -/** - * Private helper method. - */ -Graph.prototype.getGlobalVariable = function(name) -{ - var val = null; - - if (name == 'date') - { - val = new Date().toLocaleDateString(); - } - else if (name == 'time') - { - val = new Date().toLocaleTimeString(); - } - else if (name == 'timestamp') - { - val = new Date().toLocaleString(); - } - else if (name.substring(0, 5) == 'date{') - { - var fmt = name.substring(5, name.length - 1); - val = this.formatDate(new Date(), fmt); - } - - return val; -}; - -/** - * Formats a date, see http://blog.stevenlevithan.com/archives/date-time-format - */ -Graph.prototype.formatDate = function(date, mask, utc) -{ - // LATER: Cache regexs - if (this.dateFormatCache == null) - { - this.dateFormatCache = { - i18n: { - dayNames: [ - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" - ], - monthNames: [ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", - "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" - ] - }, - - masks: { - "default": "ddd mmm dd yyyy HH:MM:ss", - shortDate: "m/d/yy", - mediumDate: "mmm d, yyyy", - longDate: "mmmm d, yyyy", - fullDate: "dddd, mmmm d, yyyy", - shortTime: "h:MM TT", - mediumTime: "h:MM:ss TT", - longTime: "h:MM:ss TT Z", - isoDate: "yyyy-mm-dd", - isoTime: "HH:MM:ss", - isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", - isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" - } - }; - } - - var dF = this.dateFormatCache; - var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, - timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, - timezoneClip = /[^-+\dA-Z]/g, - pad = function (val, len) { - val = String(val); - len = len || 2; - while (val.length < len) val = "0" + val; - return val; - }; - - // You can't provide utc if you skip other args (use the "UTC:" mask prefix) - if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { - mask = date; - date = undefined; - } - - // Passing date through Date applies Date.parse, if necessary - date = date ? new Date(date) : new Date; - if (isNaN(date)) throw SyntaxError("invalid date"); - - mask = String(dF.masks[mask] || mask || dF.masks["default"]); - - // Allow setting the utc argument via the mask - if (mask.slice(0, 4) == "UTC:") { - mask = mask.slice(4); - utc = true; - } - - var _ = utc ? "getUTC" : "get", - d = date[_ + "Date"](), - D = date[_ + "Day"](), - m = date[_ + "Month"](), - y = date[_ + "FullYear"](), - H = date[_ + "Hours"](), - M = date[_ + "Minutes"](), - s = date[_ + "Seconds"](), - L = date[_ + "Milliseconds"](), - o = utc ? 0 : date.getTimezoneOffset(), - flags = { - d: d, - dd: pad(d), - ddd: dF.i18n.dayNames[D], - dddd: dF.i18n.dayNames[D + 7], - m: m + 1, - mm: pad(m + 1), - mmm: dF.i18n.monthNames[m], - mmmm: dF.i18n.monthNames[m + 12], - yy: String(y).slice(2), - yyyy: y, - h: H % 12 || 12, - hh: pad(H % 12 || 12), - H: H, - HH: pad(H), - M: M, - MM: pad(M), - s: s, - ss: pad(s), - l: pad(L, 3), - L: pad(L > 99 ? Math.round(L / 10) : L), - t: H < 12 ? "a" : "p", - tt: H < 12 ? "am" : "pm", - T: H < 12 ? "A" : "P", - TT: H < 12 ? "AM" : "PM", - Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), - o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), - S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] - }; - - return mask.replace(token, function ($0) - { - return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); - }); -}; - -/** - * - */ -Graph.prototype.createLayersDialog = function(onchange) -{ - var div = document.createElement('div'); - div.style.position = 'absolute'; - - var model = this.getModel(); - var childCount = model.getChildCount(model.root); - - for (var i = 0; i < childCount; i++) - { - (mxUtils.bind(this, function(layer) - { - var span = document.createElement('div'); - span.style.overflow = 'hidden'; - span.style.textOverflow = 'ellipsis'; - span.style.padding = '2px'; - span.style.whiteSpace = 'nowrap'; - - var cb = document.createElement('input'); - cb.style.display = 'inline-block'; - cb.setAttribute('type', 'checkbox'); - - if (model.isVisible(layer)) - { - cb.setAttribute('checked', 'checked'); - cb.defaultChecked = true; - } - - span.appendChild(cb); - - var title = this.convertValueToString(layer) || (mxResources.get('background') || 'Background'); - span.setAttribute('title', title); - mxUtils.write(span, title); - div.appendChild(span); - - mxEvent.addListener(cb, 'click', function() - { - if (cb.getAttribute('checked') != null) - { - cb.removeAttribute('checked'); - } - else - { - cb.setAttribute('checked', 'checked'); - } - - model.setVisible(layer, cb.checked); - - if (onchange != null) - { - onchange(layer); - } - }); - })(model.getChildAt(model.root, i))); - } - - return div; -}; - -/** - * Private helper method. - */ -Graph.prototype.replacePlaceholders = function(cell, str, vars, translate) -{ - var result = []; - - if (str != null) - { - var last = 0; - - while (match = this.placeholderPattern.exec(str)) - { - var val = match[0]; - - if (val.length > 2 && val != '%label%' && val != '%tooltip%') - { - var tmp = null; - - if (match.index > last && str.charAt(match.index - 1) == '%') - { - tmp = val.substring(1); - } - else - { - var name = val.substring(1, val.length - 1); - - // Workaround for invalid char for getting attribute in older versions of IE - if (name == 'id') - { - tmp = cell.id; - } - else if (name.indexOf('{') < 0) - { - var current = cell; - - while (tmp == null && current != null) - { - if (current.value != null && typeof(current.value) == 'object') - { - if (Graph.translateDiagram && Graph.diagramLanguage != null) - { - tmp = current.getAttribute(name + '_' + Graph.diagramLanguage); - } - - if (tmp == null) - { - tmp = (current.hasAttribute(name)) ? ((current.getAttribute(name) != null) ? - current.getAttribute(name) : '') : null; - } - } - - current = this.model.getParent(current); - } - } - - if (tmp == null) - { - tmp = this.getGlobalVariable(name); - } - - if (tmp == null && vars != null) - { - tmp = vars[name]; - } - } - - result.push(str.substring(last, match.index) + ((tmp != null) ? tmp : val)); - last = match.index + val.length; - } - } - - result.push(str.substring(last)); - } - - return result.join(''); -}; - -/** - * Resolves the given cells in the model and selects them. - */ -Graph.prototype.restoreSelection = function(cells) -{ - if (cells != null && cells.length > 0) - { - var temp = []; - - for (var i = 0; i < cells.length; i++) - { - var newCell = this.model.getCell(cells[i].id); - - if (newCell != null) - { - temp.push(newCell); - } - } - - this.setSelectionCells(temp); - } - else - { - this.clearSelection(); - } -}; - -/** - * Selects cells for connect vertex return value. - */ -Graph.prototype.selectCellsForConnectVertex = function(cells, evt, hoverIcons) -{ - // Selects only target vertex if one exists - if (cells.length == 2 && this.model.isVertex(cells[1])) - { - this.setSelectionCell(cells[1]); - this.scrollCellToVisible(cells[1]); - - if (hoverIcons != null) - { - // Adds hover icons for cloned vertex or hides icons - if (mxEvent.isTouchEvent(evt)) - { - hoverIcons.update(hoverIcons.getState(this.view.getState(cells[1]))); - } - else - { - hoverIcons.reset(); - } - } - } - else - { - this.setSelectionCells(cells); - } -}; - -/** - * Never connects children in stack layouts or tables. - */ -Graph.prototype.isCloneConnectSource = function(source) -{ - var layout = null; - - if (this.layoutManager != null) - { - layout = this.layoutManager.getLayout(this.model.getParent(source)); - } - - return this.isTableRow(source) || this.isTableCell(source) || - (layout != null && layout.constructor == mxStackLayout); -}; - -/** - * Adds a connection to the given vertex. - */ -Graph.prototype.connectVertex = function(source, direction, length, evt, forceClone, ignoreCellAt, createTarget, done) -{ - ignoreCellAt = (ignoreCellAt) ? ignoreCellAt : false; - - // Ignores relative edge labels - if (source.geometry.relative && this.model.isEdge(source.parent)) - { - return []; - } - - // Uses parent for relative child cells - while (source.geometry.relative && this.model.isVertex(source.parent)) - { - source = source.parent; - } - - // Handles clone connect sources - var cloneSource = this.isCloneConnectSource(source); - var composite = (cloneSource) ? source : this.getCompositeParent(source); - - var pt = (source.geometry.relative && source.parent.geometry != null) ? - new mxPoint(source.parent.geometry.width * source.geometry.x, - source.parent.geometry.height * source.geometry.y) : - new mxPoint(composite.geometry.x, composite.geometry.y); - - if (direction == mxConstants.DIRECTION_NORTH) - { - pt.x += composite.geometry.width / 2; - pt.y -= length ; - } - else if (direction == mxConstants.DIRECTION_SOUTH) - { - pt.x += composite.geometry.width / 2; - pt.y += composite.geometry.height + length; - } - else if (direction == mxConstants.DIRECTION_WEST) - { - pt.x -= length; - pt.y += composite.geometry.height / 2; - } - else - { - pt.x += composite.geometry.width + length; - pt.y += composite.geometry.height / 2; - } - - var parentState = this.view.getState(this.model.getParent(source)); - var s = this.view.scale; - var t = this.view.translate; - var dx = t.x * s; - var dy = t.y * s; - - if (parentState != null && this.model.isVertex(parentState.cell)) - { - dx = parentState.x; - dy = parentState.y; - } - - // Workaround for relative child cells - if (this.model.isVertex(source.parent) && source.geometry.relative) - { - pt.x += source.parent.geometry.x; - pt.y += source.parent.geometry.y; - } - - // Checks actual end point of edge for target cell - var rect = (!ignoreCellAt) ? new mxRectangle(dx + pt.x * s, dy + pt.y * s).grow(40) : null; - var tempCells = (rect != null) ? this.getCells(0, 0, 0, 0, null, null, rect) : null; - var target = (tempCells != null && tempCells.length > 0) ? tempCells.reverse()[0] : null; - var keepParent = false; - - if (target != null && this.model.isAncestor(target, source)) - { - keepParent = true; - target = null; - } - - // Checks for swimlane at drop location - if (target == null) - { - var temp = this.getSwimlaneAt(dx + pt.x * s, dy + pt.y * s); - - if (temp != null) - { - keepParent = false; - target = temp; - } - } - - // Checks if target or ancestor is locked - var temp = target; - - while (temp != null) - { - if (this.isCellLocked(temp)) - { - target = null; - break; - } - - temp = this.model.getParent(temp); - } - - // Checks if source and target intersect - if (target != null) - { - var sourceState = this.view.getState(source); - var targetState = this.view.getState(target); - - if (sourceState != null && targetState != null && mxUtils.intersects(sourceState, targetState)) - { - target = null; - } - } - - var duplicate = (!mxEvent.isShiftDown(evt) || mxEvent.isControlDown(evt)) || forceClone; - - if (duplicate) - { - if (direction == mxConstants.DIRECTION_NORTH) - { - pt.y -= source.geometry.height / 2; - } - else if (direction == mxConstants.DIRECTION_SOUTH) - { - pt.y += source.geometry.height / 2; - } - else if (direction == mxConstants.DIRECTION_WEST) - { - pt.x -= source.geometry.width / 2; - } - else - { - pt.x += source.geometry.width / 2; - } - } - - // Uses connectable parent vertex if one exists - // TODO: Fix using target as parent for swimlane - if (target != null && !this.isCellConnectable(target) && !this.isSwimlane(target)) - { - var parent = this.getModel().getParent(target); - - if (this.getModel().isVertex(parent) && this.isCellConnectable(parent)) - { - target = parent; - } - } - - if (target == source || this.model.isEdge(target) || - !this.isCellConnectable(target) && - !this.isSwimlane(target)) - { - target = null; - } - - var result = []; - var swimlane = target != null && this.isSwimlane(target); - var realTarget = (!swimlane) ? target : null; - - var execute = mxUtils.bind(this, function(targetCell) - { - if (createTarget == null || targetCell != null || (target == null && cloneSource)) - { - this.model.beginUpdate(); - try - { - if (realTarget == null && duplicate) - { - // Handles relative children - var cellToClone = (targetCell != null) ? targetCell : source; - var geo = this.getCellGeometry(cellToClone); - - while (geo != null && geo.relative) - { - cellToClone = this.getModel().getParent(cellToClone); - geo = this.getCellGeometry(cellToClone); - } - - // Handles composite cells for cloning - cellToClone = (cloneSource) ? source : this.getCompositeParent(cellToClone); - realTarget = (targetCell != null) ? targetCell : this.duplicateCells([cellToClone], false)[0]; - - if (targetCell != null) - { - this.addCells([realTarget], this.model.getParent(source), null, null, null, true); - } - - var geo = this.getCellGeometry(realTarget); - - if (geo != null) - { - geo.x = pt.x - geo.width / 2; - geo.y = pt.y - geo.height / 2; - } - - if (swimlane) - { - this.addCells([realTarget], target, null, null, null, true); - target = null; - } - else if (duplicate && target == null && !keepParent && !cloneSource) - { - this.addCells([realTarget], this.getDefaultParent(), null, null, null, true); - } - } - - var edge = ((mxEvent.isControlDown(evt) && mxEvent.isShiftDown(evt) && duplicate) || - (target == null && cloneSource)) ? null : this.insertEdge(this.model.getParent(source), - null, '', source, realTarget, this.createCurrentEdgeStyle()); - - // Inserts edge before source - if (edge != null && this.connectionHandler.insertBeforeSource) - { - var index = null; - var tmp = source; - - while (tmp.parent != null && tmp.geometry != null && - tmp.geometry.relative && tmp.parent != edge.parent) - { - tmp = this.model.getParent(tmp); - } - - if (tmp != null && tmp.parent != null && tmp.parent == edge.parent) - { - var index = tmp.parent.getIndex(tmp); - this.model.add(tmp.parent, edge, index); - } - } - - // Special case: Click on west icon puts clone before cell - if (target == null && realTarget != null && source.parent != null && - cloneSource && direction == mxConstants.DIRECTION_WEST) - { - var index = source.parent.getIndex(source); - this.model.add(source.parent, realTarget, index); - } - - if (edge != null) - { - result.push(edge); - } - - if (target == null && realTarget != null) - { - result.push(realTarget); - } - - if (realTarget == null && edge != null) - { - edge.geometry.setTerminalPoint(pt, false); - } - - if (edge != null) - { - this.fireEvent(new mxEventObject('cellsInserted', 'cells', [edge])); - } - } - finally - { - this.model.endUpdate(); - } - } - - if (done != null) - { - done(result); - } - else - { - return result; - } - }); - - if (createTarget != null && realTarget == null && duplicate && - (target != null || !cloneSource)) - { - createTarget(dx + pt.x * s, dy + pt.y * s, execute); - } - else - { - return execute(realTarget); - } -}; - -/** - * Returns all labels in the diagram as a string. - */ -Graph.prototype.getIndexableText = function() -{ - var tmp = document.createElement('div'); - var labels = []; - var label = ''; - - for (var key in this.model.cells) - { - var cell = this.model.cells[key]; - - if (this.model.isVertex(cell) || this.model.isEdge(cell)) - { - if (this.isHtmlLabel(cell)) - { - tmp.innerHTML = this.sanitizeHtml(this.getLabel(cell)); - label = mxUtils.extractTextWithWhitespace([tmp]); - } - else - { - label = this.getLabel(cell); - } - - label = mxUtils.trim(label.replace(/[\x00-\x1F\x7F-\x9F]|\s+/g, ' ')); - - if (label.length > 0) - { - labels.push(label); - } - } - } - - return labels.join(' '); -}; - -/** - * Returns the label for the given cell. - */ -Graph.prototype.convertValueToString = function(cell) -{ - var value = this.model.getValue(cell); - - if (value != null && typeof(value) == 'object') - { - var result = null; - - if (this.isReplacePlaceholders(cell) && cell.getAttribute('placeholder') != null) - { - var name = cell.getAttribute('placeholder'); - var current = cell; - - while (result == null && current != null) - { - if (current.value != null && typeof(current.value) == 'object') - { - result = (current.hasAttribute(name)) ? ((current.getAttribute(name) != null) ? - current.getAttribute(name) : '') : null; - } - - current = this.model.getParent(current); - } - } - else - { - var result = null; - - if (Graph.translateDiagram && Graph.diagramLanguage != null) - { - result = value.getAttribute('label_' + Graph.diagramLanguage); - } - - if (result == null) - { - result = value.getAttribute('label') || ''; - } - } - - return result || ''; - } - - return mxGraph.prototype.convertValueToString.apply(this, arguments); -}; - -/** - * Returns the link for the given cell. - */ -Graph.prototype.getLinksForState = function(state) -{ - if (state != null && state.text != null && state.text.node != null) - { - return state.text.node.getElementsByTagName('a'); - } - - return null; -}; - -/** - * Returns the link for the given cell. - */ -Graph.prototype.getLinkForCell = function(cell) -{ - if (cell.value != null && typeof(cell.value) == 'object') - { - var link = cell.value.getAttribute('link'); - - // Removes links with leading javascript: protocol - // TODO: Check more possible attack vectors - if (link != null && link.toLowerCase().substring(0, 11) === 'javascript:') - { - link = link.substring(11); - } - - return link; - } - - return null; -}; - -/** - * Overrides label orientation for collapsed swimlanes inside stack and - * for partial rectangles inside tables. - */ -Graph.prototype.getCellStyle = function(cell) -{ - var style = mxGraph.prototype.getCellStyle.apply(this, arguments); - - if (cell != null && this.layoutManager != null) - { - var parent = this.model.getParent(cell); - - if (this.model.isVertex(parent) && this.isCellCollapsed(cell)) - { - var layout = this.layoutManager.getLayout(parent); - - if (layout != null && layout.constructor == mxStackLayout) - { - style[mxConstants.STYLE_HORIZONTAL] = !layout.horizontal; - } - } - } - - return style; -}; - -/** - * Disables alternate width persistence for stack layout parents - */ -Graph.prototype.updateAlternateBounds = function(cell, geo, willCollapse) -{ - if (cell != null && geo != null && this.layoutManager != null && geo.alternateBounds != null) - { - var layout = this.layoutManager.getLayout(this.model.getParent(cell)); - - if (layout != null && layout.constructor == mxStackLayout) - { - if (layout.horizontal) - { - geo.alternateBounds.height = 0; - } - else - { - geo.alternateBounds.width = 0; - } - } - } - - mxGraph.prototype.updateAlternateBounds.apply(this, arguments); -}; - -/** - * Adds Shift+collapse/expand and size management for folding inside stack - */ -Graph.prototype.isMoveCellsEvent = function(evt, state) -{ - return mxEvent.isShiftDown(evt) || mxUtils.getValue(state.style, 'moveCells', '0') == '1'; -}; - -/** - * Adds Shift+collapse/expand and size management for folding inside stack - */ -Graph.prototype.foldCells = function(collapse, recurse, cells, checkFoldable, evt) -{ - recurse = (recurse != null) ? recurse : false; - - if (cells == null) - { - cells = this.getFoldableCells(this.getSelectionCells(), collapse); - } - - if (cells != null) - { - this.model.beginUpdate(); - - try - { - mxGraph.prototype.foldCells.apply(this, arguments); - - // Resizes all parent stacks if alt is not pressed - if (this.layoutManager != null) - { - for (var i = 0; i < cells.length; i++) - { - var state = this.view.getState(cells[i]); - var geo = this.getCellGeometry(cells[i]); - - if (state != null && geo != null) - { - var dx = Math.round(geo.width - state.width / this.view.scale); - var dy = Math.round(geo.height - state.height / this.view.scale); - - if (dy != 0 || dx != 0) - { - var parent = this.model.getParent(cells[i]); - var layout = this.layoutManager.getLayout(parent); - - if (layout == null) - { - // Moves cells to the right and down after collapse/expand - if (evt != null && this.isMoveCellsEvent(evt, state)) - { - this.moveSiblings(state, parent, dx, dy); - } - } - else if ((evt == null || !mxEvent.isAltDown(evt)) && - layout.constructor == mxStackLayout && !layout.resizeLast) - { - this.resizeParentStacks(parent, layout, dx, dy); - } - } - } - } - } - } - finally - { - this.model.endUpdate(); - } - - // Selects cells after folding - if (this.isEnabled()) - { - this.setSelectionCells(cells); - } - } -}; - -/** - * Overrides label orientation for collapsed swimlanes inside stack. - */ -Graph.prototype.moveSiblings = function(state, parent, dx, dy) -{ - this.model.beginUpdate(); - try - { - var cells = this.getCellsBeyond(state.x, state.y, parent, true, true); - - for (var i = 0; i < cells.length; i++) - { - if (cells[i] != state.cell) - { - var tmp = this.view.getState(cells[i]); - var geo = this.getCellGeometry(cells[i]); - - if (tmp != null && geo != null) - { - geo = geo.clone(); - geo.translate(Math.round(dx * Math.max(0, Math.min(1, (tmp.x - state.x) / state.width))), - Math.round(dy * Math.max(0, Math.min(1, (tmp.y - state.y) / state.height)))); - this.model.setGeometry(cells[i], geo); - } - } - } - } - finally - { - this.model.endUpdate(); - } -}; - -/** - * Overrides label orientation for collapsed swimlanes inside stack. - */ -Graph.prototype.resizeParentStacks = function(parent, layout, dx, dy) -{ - if (this.layoutManager != null && layout != null && layout.constructor == mxStackLayout && !layout.resizeLast) - { - this.model.beginUpdate(); - try - { - var dir = layout.horizontal; - - // Bubble resize up for all parent stack layouts with same orientation - while (parent != null && layout != null && layout.constructor == mxStackLayout && - layout.horizontal == dir && !layout.resizeLast) - { - var pgeo = this.getCellGeometry(parent); - var pstate = this.view.getState(parent); - - if (pstate != null && pgeo != null) - { - pgeo = pgeo.clone(); - - if (layout.horizontal) - { - pgeo.width += dx + Math.min(0, pstate.width / this.view.scale - pgeo.width); - } - else - { - pgeo.height += dy + Math.min(0, pstate.height / this.view.scale - pgeo.height); - } - - this.model.setGeometry(parent, pgeo); - } - - parent = this.model.getParent(parent); - layout = this.layoutManager.getLayout(parent); - } - } - finally - { - this.model.endUpdate(); - } - } -}; - -/** - * Disables drill-down for non-swimlanes. - */ -Graph.prototype.isContainer = function(cell) -{ - var style = this.getCurrentCellStyle(cell); - - if (this.isSwimlane(cell)) - { - return style['container'] != '0'; - } - else - { - return style['container'] == '1'; - } -}; - -/** - * Adds a connectable style. - */ -Graph.prototype.isCellConnectable = function(cell) -{ - var style = this.getCurrentCellStyle(cell); - - return (style['connectable'] != null) ? style['connectable'] != '0' : - mxGraph.prototype.isCellConnectable.apply(this, arguments); -}; - -/** - * Adds labelMovable style. - */ -Graph.prototype.isLabelMovable = function(cell) -{ - var style = this.getCurrentCellStyle(cell); - - return (style['movableLabel'] != null) ? style['movableLabel'] != '0' : - mxGraph.prototype.isLabelMovable.apply(this, arguments); -}; - -/** - * Function: selectAll - * - * Selects all children of the given parent cell or the children of the - * default parent if no parent is specified. To select leaf vertices and/or - * edges use . - * - * Parameters: - * - * parent - Optional whose children should be selected. - * Default is . - */ -Graph.prototype.selectAll = function(parent) -{ - parent = parent || this.getDefaultParent(); - - if (!this.isCellLocked(parent)) - { - mxGraph.prototype.selectAll.apply(this, arguments); - } -}; - -/** - * Function: selectCells - * - * Selects all vertices and/or edges depending on the given boolean - * arguments recursively, starting at the given parent or the default - * parent if no parent is specified. Use to select all cells. - * For vertices, only cells with no children are selected. - * - * Parameters: - * - * vertices - Boolean indicating if vertices should be selected. - * edges - Boolean indicating if edges should be selected. - * parent - Optional that acts as the root of the recursion. - * Default is . - */ -Graph.prototype.selectCells = function(vertices, edges, parent) -{ - parent = parent || this.getDefaultParent(); - - if (!this.isCellLocked(parent)) - { - mxGraph.prototype.selectCells.apply(this, arguments); - } -}; - -/** - * Function: getSwimlaneAt - * - * Returns the bottom-most swimlane that intersects the given point (x, y) - * in the cell hierarchy that starts at the given parent. - * - * Parameters: - * - * x - X-coordinate of the location to be checked. - * y - Y-coordinate of the location to be checked. - * parent - that should be used as the root of the recursion. - * Default is . - */ -Graph.prototype.getSwimlaneAt = function (x, y, parent) -{ - var result = mxGraph.prototype.getSwimlaneAt.apply(this, arguments); - - if (this.isCellLocked(result)) - { - result = null; - } - - return result; -}; - -/** - * Disables folding for non-swimlanes. - */ -Graph.prototype.isCellFoldable = function(cell) -{ - var style = this.getCurrentCellStyle(cell); - - return this.foldingEnabled && (style['treeFolding'] == '1' || - (!this.isCellLocked(cell) && - ((this.isContainer(cell) && style['collapsible'] != '0') || - (!this.isContainer(cell) && style['collapsible'] == '1')))); -}; - -/** - * Stops all interactions and clears the selection. - */ -Graph.prototype.reset = function() -{ - if (this.isEditing()) - { - this.stopEditing(true); - } - - this.escape(); - - if (!this.isSelectionEmpty()) - { - this.clearSelection(); - } -}; - -/** - * Overridden to limit zoom to 1% - 16.000%. - */ -Graph.prototype.zoom = function(factor, center) -{ - factor = Math.max(0.01, Math.min(this.view.scale * factor, 160)) / this.view.scale; - - mxGraph.prototype.zoom.apply(this, arguments); -}; - -/** - * Function: zoomIn - * - * Zooms into the graph by . - */ -Graph.prototype.zoomIn = function() -{ - // Switches to 1% zoom steps below 15% - if (this.view.scale < 0.15) - { - this.zoom((this.view.scale + 0.01) / this.view.scale); - } - else - { - // Uses to 5% zoom steps for better grid rendering in webkit - // and to avoid rounding errors for zoom steps - this.zoom((Math.round(this.view.scale * this.zoomFactor * 20) / 20) / this.view.scale); - } -}; - -/** - * Function: zoomOut - * - * Zooms out of the graph by . - */ -Graph.prototype.zoomOut = function() -{ - // Switches to 1% zoom steps below 15% - if (this.view.scale <= 0.15) - { - this.zoom((this.view.scale - 0.01) / this.view.scale); - } - else - { - // Uses to 5% zoom steps for better grid rendering in webkit - // and to avoid rounding errors for zoom steps - this.zoom((Math.round(this.view.scale * (1 / this.zoomFactor) * 20) / 20) / this.view.scale); - } -}; - -/** - * Function: fitWindow - * - * Sets the current visible rectangle of the window in graph coordinates. - */ -Graph.prototype.fitWindow = function(bounds, border) -{ - border = (border != null) ? border : 10; - - var cw = this.container.clientWidth - border; - var ch = this.container.clientHeight - border; - var scale = Math.floor(20 * Math.min(cw / bounds.width, ch / bounds.height)) / 20; - this.zoomTo(scale); - - if (mxUtils.hasScrollbars(this.container)) - { - var t = this.view.translate; - this.container.scrollTop = (bounds.y + t.y) * scale - - Math.max((ch - bounds.height * scale) / 2 + border / 2, 0); - this.container.scrollLeft = (bounds.x + t.x) * scale - - Math.max((cw - bounds.width * scale) / 2 + border / 2, 0); - } -}; - -/** - * Overrides tooltips to show custom tooltip or metadata. - */ -Graph.prototype.getTooltipForCell = function(cell) -{ - var tip = ''; - - if (mxUtils.isNode(cell.value)) - { - var tmp = null; - - if (Graph.translateDiagram && Graph.diagramLanguage != null) - { - tmp = cell.value.getAttribute('tooltip_' + Graph.diagramLanguage); - } - - if (tmp == null) - { - tmp = cell.value.getAttribute('tooltip'); - } - - if (tmp != null) - { - if (tmp != null && this.isReplacePlaceholders(cell)) - { - tmp = this.replacePlaceholders(cell, tmp); - } - - tip = this.sanitizeHtml(tmp); - } - else - { - var ignored = this.builtInProperties; - var attrs = cell.value.attributes; - var temp = []; - - // Hides links in edit mode - if (this.isEnabled()) - { - ignored.push('link'); - } - - for (var i = 0; i < attrs.length; i++) - { - if (mxUtils.indexOf(ignored, attrs[i].nodeName) < 0 && attrs[i].nodeValue.length > 0) - { - temp.push({name: attrs[i].nodeName, value: attrs[i].nodeValue}); - } - } - - // Sorts by name - temp.sort(function(a, b) - { - if (a.name < b.name) - { - return -1; - } - else if (a.name > b.name) - { - return 1; - } - else - { - return 0; - } - }); - - for (var i = 0; i < temp.length; i++) - { - if (temp[i].name != 'link' || !this.isCustomLink(temp[i].value)) - { - tip += ((temp[i].name != 'link') ? '' + temp[i].name + ': ' : '') + - mxUtils.htmlEntities(temp[i].value) + '\n'; - } - } - - if (tip.length > 0) - { - tip = tip.substring(0, tip.length - 1); - - if (mxClient.IS_SVG) - { - tip = '
' + - tip + '
'; - } - } - } - } - - return tip; -}; - -/** - * Turns the given string into an array. - */ -Graph.prototype.stringToBytes = function(str) -{ - return Graph.stringToBytes(str); -}; - -/** - * Turns the given array into a string. - */ -Graph.prototype.bytesToString = function(arr) -{ - return Graph.bytesToString(arr); -}; - -/** - * Returns a base64 encoded version of the compressed outer XML of the given node. - */ -Graph.prototype.compressNode = function(node) -{ - return Graph.compressNode(node); -}; - -/** - * Returns a base64 encoded version of the compressed string. - */ -Graph.prototype.compress = function(data, deflate) -{ - return Graph.compress(data, deflate); -}; - -/** - * Returns a decompressed version of the base64 encoded string. - */ -Graph.prototype.decompress = function(data, inflate) -{ - return Graph.decompress(data, inflate); -}; - -/** - * Redirects to Graph.zapGremlins. - */ -Graph.prototype.zapGremlins = function(text) -{ - return Graph.zapGremlins(text); -}; - -/** - * Hover icons are used for hover, vertex handler and drag from sidebar. - */ -HoverIcons = function(graph) -{ - this.graph = graph; - this.init(); -}; - -/** - * Up arrow. - */ -HoverIcons.prototype.arrowSpacing = 2; - -/** - * Delay to switch to another state for overlapping bbox. Default is 500ms. - */ -HoverIcons.prototype.updateDelay = 500; - -/** - * Delay to switch between states. Default is 140ms. - */ -HoverIcons.prototype.activationDelay = 140; - -/** - * Up arrow. - */ -HoverIcons.prototype.currentState = null; - -/** - * Up arrow. - */ -HoverIcons.prototype.activeArrow = null; - -/** - * Up arrow. - */ -HoverIcons.prototype.inactiveOpacity = 15; - -/** - * Up arrow. - */ -HoverIcons.prototype.cssCursor = 'copy'; - -/** - * Whether to hide arrows that collide with vertices. - * LATER: Add keyboard override, touch support. - */ -HoverIcons.prototype.checkCollisions = true; - -/** - * Up arrow. - */ -HoverIcons.prototype.arrowFill = '#29b6f2'; - -/** - * Up arrow. - */ -HoverIcons.prototype.triangleUp = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/triangle-up.png', 26, 14) : - Graph.createSvgImage(18, 28, ''); - -/** - * Right arrow. - */ -HoverIcons.prototype.triangleRight = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/triangle-right.png', 14, 26) : - Graph.createSvgImage(26, 18, ''); - -/** - * Down arrow. - */ -HoverIcons.prototype.triangleDown = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/triangle-down.png', 26, 14) : - Graph.createSvgImage(18, 26, ''); - -/** - * Left arrow. - */ -HoverIcons.prototype.triangleLeft = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/triangle-left.png', 14, 26) : - Graph.createSvgImage(28, 18, ''); - -/** - * Round target. - */ -HoverIcons.prototype.roundDrop = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/round-drop.png', 26, 26) : - Graph.createSvgImage(26, 26, ''); - -/** - * Refresh target. - */ -HoverIcons.prototype.refreshTarget = new mxImage((mxClient.IS_SVG) ? 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjM2cHgiIGhlaWdodD0iMzZweCI+PGVsbGlwc2UgZmlsbD0iIzI5YjZmMiIgY3g9IjEyIiBjeT0iMTIiIHJ4PSIxMiIgcnk9IjEyIi8+PHBhdGggdHJhbnNmb3JtPSJzY2FsZSgwLjgpIHRyYW5zbGF0ZSgyLjQsIDIuNCkiIHN0cm9rZT0iI2ZmZiIgZmlsbD0iI2ZmZiIgZD0iTTEyIDZ2M2w0LTQtNC00djNjLTQuNDIgMC04IDMuNTgtOCA4IDAgMS41Ny40NiAzLjAzIDEuMjQgNC4yNkw2LjcgMTQuOGMtLjQ1LS44My0uNy0xLjc5LS43LTIuOCAwLTMuMzEgMi42OS02IDYtNnptNi43NiAxLjc0TDE3LjMgOS4yYy40NC44NC43IDEuNzkuNyAyLjggMCAzLjMxLTIuNjkgNi02IDZ2LTNsLTQgNCA0IDR2LTNjNC40MiAwIDgtMy41OCA4LTggMC0xLjU3LS40Ni0zLjAzLTEuMjQtNC4yNnoiLz48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PC9zdmc+Cg==' : - IMAGE_PATH + '/refresh.png', 38, 38); - -/** - * Tolerance for hover icon clicks. - */ -HoverIcons.prototype.tolerance = (mxClient.IS_TOUCH) ? 6 : 0; - -/** - * - */ -HoverIcons.prototype.init = function() -{ - this.arrowUp = this.createArrow(this.triangleUp, mxResources.get('plusTooltip')); - this.arrowRight = this.createArrow(this.triangleRight, mxResources.get('plusTooltip')); - this.arrowDown = this.createArrow(this.triangleDown, mxResources.get('plusTooltip')); - this.arrowLeft = this.createArrow(this.triangleLeft, mxResources.get('plusTooltip')); - - this.elts = [this.arrowUp, this.arrowRight, this.arrowDown, this.arrowLeft]; - - this.resetHandler = mxUtils.bind(this, function() - { - this.reset(); - }); - - this.repaintHandler = mxUtils.bind(this, function() - { - this.repaint(); - }); - - this.graph.selectionModel.addListener(mxEvent.CHANGE, this.resetHandler); - this.graph.model.addListener(mxEvent.CHANGE, this.repaintHandler); - this.graph.view.addListener(mxEvent.SCALE_AND_TRANSLATE, this.repaintHandler); - this.graph.view.addListener(mxEvent.TRANSLATE, this.repaintHandler); - this.graph.view.addListener(mxEvent.SCALE, this.repaintHandler); - this.graph.view.addListener(mxEvent.DOWN, this.repaintHandler); - this.graph.view.addListener(mxEvent.UP, this.repaintHandler); - this.graph.addListener(mxEvent.ROOT, this.repaintHandler); - this.graph.addListener(mxEvent.ESCAPE, this.resetHandler); - mxEvent.addListener(this.graph.container, 'scroll', this.resetHandler); - - // Resets the mouse point on escape - this.graph.addListener(mxEvent.ESCAPE, mxUtils.bind(this, function() - { - this.mouseDownPoint = null; - })); - - // Removes hover icons if mouse leaves the container - mxEvent.addListener(this.graph.container, 'mouseleave', mxUtils.bind(this, function(evt) - { - // Workaround for IE11 firing mouseleave for touch in diagram - if (evt.relatedTarget != null && mxEvent.getSource(evt) == this.graph.container) - { - this.setDisplay('none'); - } - })); - - // Resets current state when in-place editor starts - this.graph.addListener(mxEvent.START_EDITING, mxUtils.bind(this, function(evt) - { - this.reset(); - })); - - // Resets current state after update of selection state for touch events - var graphClick = this.graph.click; - this.graph.click = mxUtils.bind(this, function(me) - { - graphClick.apply(this.graph, arguments); - - if (this.currentState != null && !this.graph.isCellSelected(this.currentState.cell) && - mxEvent.isTouchEvent(me.getEvent()) && !this.graph.model.isVertex(me.getCell())) - { - this.reset(); - } - }); - - // Checks if connection handler was active in mouse move - // as workaround for possible double connection inserted - var connectionHandlerActive = false; - - // Implements a listener for hover and click handling - this.graph.addMouseListener( - { - mouseDown: mxUtils.bind(this, function(sender, me) - { - connectionHandlerActive = false; - var evt = me.getEvent(); - - if (this.isResetEvent(evt)) - { - this.reset(); - } - else if (!this.isActive()) - { - var state = this.getState(me.getState()); - - if (state != null || !mxEvent.isTouchEvent(evt)) - { - this.update(state); - } - } - - this.setDisplay('none'); - }), - mouseMove: mxUtils.bind(this, function(sender, me) - { - var evt = me.getEvent(); - - if (this.isResetEvent(evt)) - { - this.reset(); - } - else if (!this.graph.isMouseDown && !mxEvent.isTouchEvent(evt)) - { - this.update(this.getState(me.getState()), - me.getGraphX(), me.getGraphY()); - } - - if (this.graph.connectionHandler != null && - this.graph.connectionHandler.shape != null) - { - connectionHandlerActive = true; - } - }), - mouseUp: mxUtils.bind(this, function(sender, me) - { - var evt = me.getEvent(); - var pt = mxUtils.convertPoint(this.graph.container, - mxEvent.getClientX(evt), mxEvent.getClientY(evt)) - - if (this.isResetEvent(evt)) - { - this.reset(); - } - else if (this.isActive() && !connectionHandlerActive && - this.mouseDownPoint != null) - { - this.click(this.currentState, this.getDirection(), me); - } - else if (this.isActive()) - { - // Selects target vertex after drag and clone if not only new edge was inserted - if (this.graph.getSelectionCount() != 1 || !this.graph.model.isEdge( - this.graph.getSelectionCell())) - { - this.update(this.getState(this.graph.view.getState( - this.graph.getCellAt(me.getGraphX(), me.getGraphY())))); - } - else - { - this.reset(); - } - } - else if (mxEvent.isTouchEvent(evt) || (this.bbox != null && - mxUtils.contains(this.bbox, me.getGraphX(), me.getGraphY()))) - { - // Shows existing hover icons if inside bounding box - this.setDisplay(''); - this.repaint(); - } - else if (!mxEvent.isTouchEvent(evt)) - { - this.reset(); - } - - connectionHandlerActive = false; - this.resetActiveArrow(); - }) - }); -}; - -/** - * - */ -HoverIcons.prototype.isResetEvent = function(evt, allowShift) -{ - return mxEvent.isAltDown(evt) || (this.activeArrow == null && mxEvent.isShiftDown(evt)) || - (mxEvent.isPopupTrigger(evt) && !this.graph.isCloneEvent(evt)); -}; - -/** - * - */ -HoverIcons.prototype.createArrow = function(img, tooltip) -{ - var arrow = null; - - if (mxClient.IS_IE && !mxClient.IS_SVG) - { - // Workaround for PNG images in IE6 - if (mxClient.IS_IE6 && document.compatMode != 'CSS1Compat') - { - arrow = document.createElement(mxClient.VML_PREFIX + ':image'); - arrow.setAttribute('src', img.src); - arrow.style.borderStyle = 'none'; - } - else - { - arrow = document.createElement('div'); - arrow.style.backgroundImage = 'url(' + img.src + ')'; - arrow.style.backgroundPosition = 'center'; - arrow.style.backgroundRepeat = 'no-repeat'; - } - - arrow.style.width = (img.width + 4) + 'px'; - arrow.style.height = (img.height + 4) + 'px'; - arrow.style.display = (mxClient.IS_QUIRKS) ? 'inline' : 'inline-block'; - } - else - { - arrow = mxUtils.createImage(img.src); - arrow.style.width = img.width + 'px'; - arrow.style.height = img.height + 'px'; - arrow.style.padding = this.tolerance + 'px'; - } - - if (tooltip != null) - { - arrow.setAttribute('title', tooltip); - } - - arrow.style.position = 'absolute'; - arrow.style.cursor = this.cssCursor; - - mxEvent.addGestureListeners(arrow, mxUtils.bind(this, function(evt) - { - if (this.currentState != null && !this.isResetEvent(evt)) - { - this.mouseDownPoint = mxUtils.convertPoint(this.graph.container, - mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - this.drag(evt, this.mouseDownPoint.x, this.mouseDownPoint.y); - this.activeArrow = arrow; - this.setDisplay('none'); - mxEvent.consume(evt); - } - })); - - // Captures mouse events as events on graph - mxEvent.redirectMouseEvents(arrow, this.graph, this.currentState); - - mxEvent.addListener(arrow, 'mouseenter', mxUtils.bind(this, function(evt) - { - // Workaround for Firefox firing mouseenter on touchend - if (mxEvent.isMouseEvent(evt)) - { - if (this.activeArrow != null && this.activeArrow != arrow) - { - mxUtils.setOpacity(this.activeArrow, this.inactiveOpacity); - } - - this.graph.connectionHandler.constraintHandler.reset(); - mxUtils.setOpacity(arrow, 100); - this.activeArrow = arrow; - } - })); - - mxEvent.addListener(arrow, 'mouseleave', mxUtils.bind(this, function(evt) - { - // Workaround for IE11 firing this event on touch - if (!this.graph.isMouseDown) - { - this.resetActiveArrow(); - } - })); - - return arrow; -}; - -/** - * - */ -HoverIcons.prototype.resetActiveArrow = function() -{ - if (this.activeArrow != null) - { - mxUtils.setOpacity(this.activeArrow, this.inactiveOpacity); - this.activeArrow = null; - } -}; - -/** - * - */ -HoverIcons.prototype.getDirection = function() -{ - var dir = mxConstants.DIRECTION_EAST; - - if (this.activeArrow == this.arrowUp) - { - dir = mxConstants.DIRECTION_NORTH; - } - else if (this.activeArrow == this.arrowDown) - { - dir = mxConstants.DIRECTION_SOUTH; - } - else if (this.activeArrow == this.arrowLeft) - { - dir = mxConstants.DIRECTION_WEST; - } - - return dir; -}; - -/** - * - */ -HoverIcons.prototype.visitNodes = function(visitor) -{ - for (var i = 0; i < this.elts.length; i++) - { - if (this.elts[i] != null) - { - visitor(this.elts[i]); - } - } -}; - -/** - * - */ -HoverIcons.prototype.removeNodes = function() -{ - this.visitNodes(function(elt) - { - if (elt.parentNode != null) - { - elt.parentNode.removeChild(elt); - } - }); -}; - -/** - * - */ -HoverIcons.prototype.setDisplay = function(display) -{ - this.visitNodes(function(elt) - { - elt.style.display = display; - }); -}; - -/** - * - */ -HoverIcons.prototype.isActive = function() -{ - return this.activeArrow != null && this.currentState != null; -}; - -/** - * - */ -HoverIcons.prototype.drag = function(evt, x, y) -{ - this.graph.popupMenuHandler.hideMenu(); - this.graph.stopEditing(false); - - // Checks if state was removed in call to stopEditing above - if (this.currentState != null) - { - this.graph.connectionHandler.start(this.currentState, x, y); - this.graph.isMouseTrigger = mxEvent.isMouseEvent(evt); - this.graph.isMouseDown = true; - - // Hides handles for selection cell - var handler = this.graph.selectionCellsHandler.getHandler(this.currentState.cell); - - if (handler != null) - { - handler.setHandlesVisible(false); - } - - // Ctrl+shift drag sets source constraint - var es = this.graph.connectionHandler.edgeState; - - if (evt != null && mxEvent.isShiftDown(evt) && mxEvent.isControlDown(evt) && es != null && - mxUtils.getValue(es.style, mxConstants.STYLE_EDGE, null) === 'orthogonalEdgeStyle') - { - var direction = this.getDirection(); - es.cell.style = mxUtils.setStyle(es.cell.style, 'sourcePortConstraint', direction); - es.style['sourcePortConstraint'] = direction; - } - } -}; - -/** - * - */ -HoverIcons.prototype.getStateAt = function(state, x, y) -{ - return this.graph.view.getState(this.graph.getCellAt(x, y)); -}; - -/** - * - */ -HoverIcons.prototype.click = function(state, dir, me) -{ - var evt = me.getEvent(); - var x = me.getGraphX(); - var y = me.getGraphY(); - - var tmp = this.getStateAt(state, x, y); - - if (tmp != null && this.graph.model.isEdge(tmp.cell) && !this.graph.isCloneEvent(evt) && - (tmp.getVisibleTerminalState(true) == state || tmp.getVisibleTerminalState(false) == state)) - { - this.graph.setSelectionCell(tmp.cell); - this.reset(); - } - else if (state != null) - { - this.execute(state, dir, me); - } - - me.consume(); -}; - -/** - * - */ -HoverIcons.prototype.execute = function(state, dir, me) -{ - var evt = me.getEvent(); - - this.graph.selectCellsForConnectVertex(this.graph.connectVertex( - state.cell, dir, this.graph.defaultEdgeLength, evt, this.graph.isCloneEvent(evt), - this.graph.isCloneEvent(evt)), evt, this); -}; - -/** - * - */ -HoverIcons.prototype.reset = function(clearTimeout) -{ - clearTimeout = (clearTimeout == null) ? true : clearTimeout; - - if (clearTimeout && this.updateThread != null) - { - window.clearTimeout(this.updateThread); - } - - this.mouseDownPoint = null; - this.currentState = null; - this.activeArrow = null; - this.removeNodes(); - this.bbox = null; -}; - -/** - * - */ -HoverIcons.prototype.repaint = function() -{ - this.bbox = null; - - if (this.currentState != null) - { - // Checks if cell was deleted - this.currentState = this.getState(this.currentState); - - // Cell was deleted - if (this.currentState != null && - this.graph.model.isVertex(this.currentState.cell) && - this.graph.isCellConnectable(this.currentState.cell)) - { - var bds = mxRectangle.fromRectangle(this.currentState); - - // Uses outer bounding box to take rotation into account - if (this.currentState.shape != null && this.currentState.shape.boundingBox != null) - { - bds = mxRectangle.fromRectangle(this.currentState.shape.boundingBox); - } - - bds.grow(this.graph.tolerance); - bds.grow(this.arrowSpacing); - - var handler = this.graph.selectionCellsHandler.getHandler(this.currentState.cell); - - if (this.graph.isTableRow(this.currentState.cell)) - { - handler = this.graph.selectionCellsHandler.getHandler( - this.graph.model.getParent(this.currentState.cell)); - } - - var rotationBbox = null; - - if (handler != null) - { - bds.x -= handler.horizontalOffset / 2; - bds.y -= handler.verticalOffset / 2; - bds.width += handler.horizontalOffset; - bds.height += handler.verticalOffset; - - // Adds bounding box of rotation handle to avoid overlap - if (handler.rotationShape != null && handler.rotationShape.node != null && - handler.rotationShape.node.style.visibility != 'hidden' && - handler.rotationShape.node.style.display != 'none' && - handler.rotationShape.boundingBox != null) - { - rotationBbox = handler.rotationShape.boundingBox; - } - } - - // Positions arrows avoid collisions with rotation handle - var positionArrow = mxUtils.bind(this, function(arrow, x, y) - { - if (rotationBbox != null) - { - var bbox = new mxRectangle(x, y, arrow.clientWidth, arrow.clientHeight); - - if (mxUtils.intersects(bbox, rotationBbox)) - { - if (arrow == this.arrowUp) - { - y -= bbox.y + bbox.height - rotationBbox.y; - } - else if (arrow == this.arrowRight) - { - x += rotationBbox.x + rotationBbox.width - bbox.x; - } - else if (arrow == this.arrowDown) - { - y += rotationBbox.y + rotationBbox.height - bbox.y; - } - else if (arrow == this.arrowLeft) - { - x -= bbox.x + bbox.width - rotationBbox.x; - } - } - } - - arrow.style.left = x + 'px'; - arrow.style.top = y + 'px'; - mxUtils.setOpacity(arrow, this.inactiveOpacity); - }); - - positionArrow(this.arrowUp, - Math.round(this.currentState.getCenterX() - this.triangleUp.width / 2 - this.tolerance), - Math.round(bds.y - this.triangleUp.height - this.tolerance)); - - positionArrow(this.arrowRight, Math.round(bds.x + bds.width - this.tolerance), - Math.round(this.currentState.getCenterY() - this.triangleRight.height / 2 - this.tolerance)); - - positionArrow(this.arrowDown, parseInt(this.arrowUp.style.left), - Math.round(bds.y + bds.height - this.tolerance)); - - positionArrow(this.arrowLeft, Math.round(bds.x - this.triangleLeft.width - this.tolerance), - parseInt(this.arrowRight.style.top)); - - if (this.checkCollisions) - { - var right = this.graph.getCellAt(bds.x + bds.width + - this.triangleRight.width / 2, this.currentState.getCenterY()); - var left = this.graph.getCellAt(bds.x - this.triangleLeft.width / 2, this.currentState.getCenterY()); - var top = this.graph.getCellAt(this.currentState.getCenterX(), bds.y - this.triangleUp.height / 2); - var bottom = this.graph.getCellAt(this.currentState.getCenterX(), bds.y + bds.height + this.triangleDown.height / 2); - - // Shows hover icons large cell is behind all directions of current cell - if (right != null && right == left && left == top && top == bottom) - { - right = null; - left = null; - top = null; - bottom = null; - } - - var currentGeo = this.graph.getCellGeometry(this.currentState.cell); - - var checkCollision = mxUtils.bind(this, function(cell, arrow) - { - var geo = this.graph.model.isVertex(cell) && this.graph.getCellGeometry(cell); - - // Ignores collision if vertex is more than 3 times the size of this vertex - if (cell != null && !this.graph.model.isAncestor(cell, this.currentState.cell) && - !this.graph.isSwimlane(cell) && (geo == null || currentGeo == null || - (geo.height < 3 * currentGeo.height && geo.width < 3 * currentGeo.width))) - { - arrow.style.visibility = 'hidden'; - } - else - { - arrow.style.visibility = 'visible'; - } - }); - - checkCollision(right, this.arrowRight); - checkCollision(left, this.arrowLeft); - checkCollision(top, this.arrowUp); - checkCollision(bottom, this.arrowDown); - } - else - { - this.arrowLeft.style.visibility = 'visible'; - this.arrowRight.style.visibility = 'visible'; - this.arrowUp.style.visibility = 'visible'; - this.arrowDown.style.visibility = 'visible'; - } - - if (this.graph.tooltipHandler.isEnabled()) - { - this.arrowLeft.setAttribute('title', mxResources.get('plusTooltip')); - this.arrowRight.setAttribute('title', mxResources.get('plusTooltip')); - this.arrowUp.setAttribute('title', mxResources.get('plusTooltip')); - this.arrowDown.setAttribute('title', mxResources.get('plusTooltip')); - } - else - { - this.arrowLeft.removeAttribute('title'); - this.arrowRight.removeAttribute('title'); - this.arrowUp.removeAttribute('title'); - this.arrowDown.removeAttribute('title'); - } - } - else - { - this.reset(); - } - - // Updates bounding box - if (this.currentState != null) - { - this.bbox = this.computeBoundingBox(); - - // Adds tolerance for hover - if (this.bbox != null) - { - this.bbox.grow(10); - } - } - } -}; - -/** - * - */ -HoverIcons.prototype.computeBoundingBox = function() -{ - var bbox = (!this.graph.model.isEdge(this.currentState.cell)) ? mxRectangle.fromRectangle(this.currentState) : null; - - this.visitNodes(function(elt) - { - if (elt.parentNode != null) - { - var tmp = new mxRectangle(elt.offsetLeft, elt.offsetTop, elt.offsetWidth, elt.offsetHeight); - - if (bbox == null) - { - bbox = tmp; - } - else - { - bbox.add(tmp); - } - } - }); - - return bbox; -}; - -/** - * - */ -HoverIcons.prototype.getState = function(state) -{ - if (state != null) - { - var cell = state.cell; - - if (!this.graph.getModel().contains(cell)) - { - state = null; - } - else - { - // Uses connectable parent vertex if child is not connectable - if (this.graph.getModel().isVertex(cell) && !this.graph.isCellConnectable(cell)) - { - var parent = this.graph.getModel().getParent(cell); - - if (this.graph.getModel().isVertex(parent) && this.graph.isCellConnectable(parent)) - { - cell = parent; - } - } - - // Ignores locked cells and edges - if (this.graph.isCellLocked(cell) || this.graph.model.isEdge(cell)) - { - cell = null; - } - - state = this.graph.view.getState(cell); - - if (state != null && state.style == null) - { - state = null; - } - } - } - - return state; -}; - -/** - * - */ -HoverIcons.prototype.update = function(state, x, y) -{ - if (!this.graph.connectionArrowsEnabled || (state != null && - mxUtils.getValue(state.style, 'allowArrows', '1') == '0')) - { - this.reset(); - } - else - { - if (state != null && state.cell.geometry != null && state.cell.geometry.relative && - this.graph.model.isEdge(state.cell.parent)) - { - state = null; - } - - var timeOnTarget = null; - - // Time on target - if (this.prev != state || this.isActive()) - { - this.startTime = new Date().getTime(); - this.prev = state; - timeOnTarget = 0; - - if (this.updateThread != null) - { - window.clearTimeout(this.updateThread); - } - - if (state != null) - { - // Starts timer to update current state with no mouse events - this.updateThread = window.setTimeout(mxUtils.bind(this, function() - { - if (!this.isActive() && !this.graph.isMouseDown && - !this.graph.panningHandler.isActive()) - { - this.prev = state; - this.update(state, x, y); - } - }), this.updateDelay + 10); - } - } - else if (this.startTime != null) - { - timeOnTarget = new Date().getTime() - this.startTime; - } - - this.setDisplay(''); - - if (this.currentState != null && this.currentState != state && timeOnTarget < this.activationDelay && - this.bbox != null && !mxUtils.contains(this.bbox, x, y)) - { - this.reset(false); - } - else if (this.currentState != null || timeOnTarget > this.activationDelay) - { - if (this.currentState != state && ((timeOnTarget > this.updateDelay && state != null) || - this.bbox == null || x == null || y == null || !mxUtils.contains(this.bbox, x, y))) - { - if (state != null && this.graph.isEnabled()) - { - this.removeNodes(); - this.setCurrentState(state); - this.repaint(); - - // Resets connection points on other focused cells - if (this.graph.connectionHandler.constraintHandler.currentFocus != state) - { - this.graph.connectionHandler.constraintHandler.reset(); - } - } - else - { - this.reset(); - } - } - } - } -}; - -/** - * - */ -HoverIcons.prototype.setCurrentState = function(state) -{ - if (state.style['portConstraint'] != 'eastwest') - { - this.graph.container.appendChild(this.arrowUp); - this.graph.container.appendChild(this.arrowDown); - } - - this.graph.container.appendChild(this.arrowRight); - this.graph.container.appendChild(this.arrowLeft); - this.currentState = state; -}; - -/** - * Returns true if the given cell is a table. - */ -Graph.prototype.createParent = function(parent, child, childCount, dx, dy) -{ - parent = this.cloneCell(parent); - - for (var i = 0; i < childCount; i++) - { - var clone = this.cloneCell(child); - var geo = this.getCellGeometry(clone) - - if (geo != null) - { - geo.x += i * dx; - geo.y += i * dy; - } - - parent.insert(clone); - } - - return parent; -}; - -/** - * Returns true if the given cell is a table. - */ -Graph.prototype.createTable = function(rowCount, colCount, w, h, title, startSize, tableStyle, rowStyle, cellStyle) -{ - w = (w != null) ? w : 60; - h = (h != null) ? h : 40; - startSize = (startSize != null) ? startSize : 30; - tableStyle = (tableStyle != null) ? tableStyle : 'shape=table;html=1;whiteSpace=wrap;startSize=' + - ((title != null) ? startSize : '0') + ';container=1;collapsible=0;childLayout=tableLayout;'; - rowStyle = (rowStyle != null) ? rowStyle : 'shape=partialRectangle;html=1;whiteSpace=wrap;collapsible=0;dropTarget=0;' + - 'pointerEvents=0;fillColor=none;top=0;left=0;bottom=0;right=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;'; - cellStyle = (cellStyle != null) ? cellStyle : 'shape=partialRectangle;html=1;whiteSpace=wrap;connectable=0;' + - 'overflow=hidden;fillColor=none;top=0;left=0;bottom=0;right=0;'; - - return this.createParent(this.createVertex(null, null, (title != null) ? title : '', - 0, 0, colCount * w, rowCount * h + ((title != null) ? startSize : 0), tableStyle), - this.createParent(this.createVertex(null, null, '', 0, 0, colCount * w, h, rowStyle), - this.createVertex(null, null, '', 0, 0, w, h, cellStyle), - colCount, w, 0), rowCount, 0, h); -}; - -/** - * Sets the values for the cells and rows in the given table and returns the table. - */ -Graph.prototype.setTableValues = function(table, values, rowValues) -{ - var rows = this.model.getChildCells(table, true); - - for (var i = 0; i < rows.length; i++) - { - if (rowValues != null) - { - rows[i].value = rowValues[i]; - } - - if (values != null) - { - var cells = this.model.getChildCells(rows[i], true); - - for (var j = 0; j < cells.length; j++) - { - if (values[i][j] != null) - { - cells[j].value = values[i][j]; - } - } - } - } - - return table; -}; - -/** - * - */ -Graph.prototype.createCrossFunctionalSwimlane = function(rowCount, colCount, w, h, startSize, tableStyle, rowStyle, firstCellStyle, cellStyle) -{ - w = (w != null) ? w : 120; - h = (h != null) ? h : 120; - startSize = (startSize != null) ? startSize : 40; - - var s = 'html=1;whiteSpace=wrap;collapsible=0;recursiveResize=0;expand=0;pointerEvents=0;'; - tableStyle = (tableStyle != null) ? tableStyle : 'shape=table;childLayout=tableLayout;' + - 'rowLines=0;columnLines=0;startSize=' + startSize + ';' + s; - rowStyle = (rowStyle != null) ? rowStyle : 'swimlane;horizontal=0;points=[[0,0.5],[1,0.5]];' + - 'portConstraint=eastwest;startSize=' + startSize + ';' + s; - firstCellStyle = (firstCellStyle != null) ? firstCellStyle : 'swimlane;connectable=0;startSize=40;' + s; - cellStyle = (cellStyle != null) ? cellStyle : 'swimlane;connectable=0;startSize=0;' + s; - - var table = this.createVertex(null, null, '', 0, 0, - colCount * w, rowCount * h, tableStyle); - var t = mxUtils.getValue(this.getCellStyle(table), mxConstants.STYLE_STARTSIZE, - mxConstants.DEFAULT_STARTSIZE); - table.geometry.width += t; - table.geometry.height += t; - - var row = this.createVertex(null, null, '', 0, t, colCount * w + t, h, rowStyle); - table.insert(this.createParent(row, this.createVertex(null, null, - '', t, 0, w, h, firstCellStyle), colCount, w, 0)); - - if (rowCount > 1) - { - row.geometry.y = h + t; - - return this.createParent(table, this.createParent(row, - this.createVertex(null, null, '', t, 0, w, h, cellStyle), - colCount, w, 0), rowCount - 1, 0, h); - } - else - { - return table; - } -}; - -/** - * Returns true if the given cell is a table cell. - */ -Graph.prototype.isTableCell = function(cell) -{ - return this.model.isVertex(cell) && this.isTableRow(this.model.getParent(cell)); -}; - -/** - * Returns true if the given cell is a table row. - */ -Graph.prototype.isTableRow = function(cell) -{ - return this.model.isVertex(cell) && this.isTable(this.model.getParent(cell)); -}; - -/** - * Returns true if the given cell is a table. - */ -Graph.prototype.isTable = function(cell) -{ - var style = this.getCellStyle(cell); - - return style != null && style['childLayout'] == 'tableLayout'; -}; - -/** - * Updates the row and table heights. - */ -Graph.prototype.setTableRowHeight = function(row, dy, extend) -{ - extend = (extend != null) ? extend : true; - var model = this.getModel(); - - model.beginUpdate(); - try - { - var rgeo = this.getCellGeometry(row); - - // Sets height of row - if (rgeo != null) - { - rgeo = rgeo.clone(); - rgeo.height += dy; - model.setGeometry(row, rgeo); - - var table = model.getParent(row); - var rows = model.getChildCells(table, true); - - // Shifts and resizes neighbor row - if (!extend) - { - var index = mxUtils.indexOf(rows, row); - - if (index < rows.length - 1) - { - var nextRow = rows[index + 1]; - var geo = this.getCellGeometry(nextRow); - - if (geo != null) - { - geo = geo.clone(); - geo.y += dy; - geo.height -= dy; - - model.setGeometry(nextRow, geo); - } - } - } - - // Updates height of table - var tgeo = this.getCellGeometry(table); - - if (tgeo != null) - { - // Always extends for last row - if (!extend) - { - extend = row == rows[rows.length - 1]; - } - - if (extend) - { - tgeo = tgeo.clone(); - tgeo.height += dy; - model.setGeometry(table, tgeo); - } - } - - if (this.layoutManager != null) - { - this.layoutManager.executeLayout(table, true); - } - } - } - finally - { - model.endUpdate(); - } -}; - -/** - * Updates column width and row height. - */ -Graph.prototype.setTableColumnWidth = function(col, dx, extend) -{ - extend = (extend != null) ? extend : false; - - var model = this.getModel(); - var row = model.getParent(col); - var table = model.getParent(row); - var cells = model.getChildCells(row, true); - var index = mxUtils.indexOf(cells, col); - var lastColumn = index == cells.length - 1; - - model.beginUpdate(); - try - { - // Sets width of child cell - var rows = model.getChildCells(table, true); - - for (var i = 0; i < rows.length; i++) - { - row = rows[i]; - cells = model.getChildCells(row, true); - var cell = cells[index]; - var geo = this.getCellGeometry(cell); - - if (geo != null) - { - geo = geo.clone(); - geo.width += dx; - model.setGeometry(cell, geo); - } - - // Shifts and resizes neighbor column - if (index < cells.length - 1) - { - cell = cells[index + 1]; - var geo = this.getCellGeometry(cell); - - if (geo != null) - { - geo = geo.clone(); - geo.x += dx; - - if (!extend) - { - geo.width -= dx; - } - - model.setGeometry(cell, geo); - } - } - } - - if (lastColumn || extend) - { - // Updates width of table - var tgeo = this.getCellGeometry(table); - - if (tgeo != null) - { - tgeo = tgeo.clone(); - tgeo.width += dx; - model.setGeometry(table, tgeo); - } - } - - if (this.layoutManager != null) - { - this.layoutManager.executeLayout(table, true); - } - } - finally - { - model.endUpdate(); - } -}; - -/** - * Special Layout for tables. - */ -function TableLayout(graph) -{ - mxGraphLayout.call(this, graph); -}; - -/** - * Extends mxGraphLayout. - */ -TableLayout.prototype = new mxStackLayout(); -TableLayout.prototype.constructor = TableLayout; - -/** - * Function: isHorizontal - * - * Overrides stack layout to handle row reorder. - */ -TableLayout.prototype.isHorizontal = function() -{ - return false; -}; - -/** - * Function: isVertexIgnored - * - * Overrides to allow for table rows and cells. - */ -TableLayout.prototype.isVertexIgnored = function(vertex) -{ - return !this.graph.getModel().isVertex(vertex) || - !this.graph.isCellVisible(vertex); -}; - -/** - * Function: getSize - * - * Returns the total vertical or horizontal size of the given cells. - */ -TableLayout.prototype.getSize = function(cells, horizontal) -{ - var total = 0; - - for (var i = 0; i < cells.length; i++) - { - if (!this.isVertexIgnored(cells[i])) - { - var geo = this.graph.getCellGeometry(cells[i]); - - if (geo != null) - { - total += (horizontal) ? geo.width : geo.height; - } - } - } - - return total; -}; - -/** - * Function: getRowLayout - * - * Returns the column positions for the given row and table width. - */ -TableLayout.prototype.getRowLayout = function(row, width) -{ - var cells = this.graph.model.getChildCells(row, true); - var off = this.graph.getActualStartSize(row, true); - var sw = this.getSize(cells, true); - var rw = width - off.x - off.width; - var result = []; - var x = off.x; - - for (var i = 0; i < cells.length; i++) - { - var cell = this.graph.getCellGeometry(cells[i]); - - if (cell != null) - { - x += cell.width * rw / sw; - result.push(Math.round(x)); - } - } - - return result; -}; - -/** - * Function: layoutRow - * - * Places the cells at the given positions in the given row. - */ -TableLayout.prototype.layoutRow = function(row, positions, height, tw) -{ - var model = this.graph.getModel(); - var cells = model.getChildCells(row, true); - var off = this.graph.getActualStartSize(row, true); - var x = off.x; - var sw = 0; - - if (positions != null) - { - positions = positions.slice(); - positions.splice(0, 0, off.x); - } - - for (var i = 0; i < cells.length; i++) - { - var cell = this.graph.getCellGeometry(cells[i]); - - if (cell != null) - { - cell = cell.clone(); - - cell.y = off.y; - cell.height = height - off.y - off.height; - - if (positions != null) - { - cell.x = positions[i]; - cell.width = positions[i + 1] - cell.x; - - // Fills with last cell if not enough cells - if (i == cells.length - 1 && i < positions.length - 2) - { - cell.width = tw - cell.x - off.x - off.width; - } - } - else - { - cell.x = x; - x += cell.width; - - if (i == cells.length - 1) - { - cell.width = tw - off.x - off.width - sw; - } - else - { - sw += cell.width; - } - } - - model.setGeometry(cells[i], cell); - } - } - - return sw; -}; - -/** - * Function: execute - * - * Implements . - */ -TableLayout.prototype.execute = function(parent) -{ - if (parent != null) - { - var offset = this.graph.getActualStartSize(parent, true); - var table = this.graph.getCellGeometry(parent); - var style = this.graph.getCellStyle(parent); - var resizeLastRow = mxUtils.getValue(style, - 'resizeLastRow', '0') == '1'; - var resizeLast = mxUtils.getValue(style, - 'resizeLast', '0') == '1'; - var fixedRows = mxUtils.getValue(style, - 'fixedRows', '0') == '1'; - var model = this.graph.getModel(); - var sw = 0; - - model.beginUpdate(); - try - { - var th = table.height - offset.y - offset.height; - var tw = table.width - offset.x - offset.width; - var rows = model.getChildCells(parent, true); - var sh = this.getSize(rows, false); - - if (th > 0 && tw > 0 && rows.length > 0 && sh > 0) - { - if (resizeLastRow) - { - var row = this.graph.getCellGeometry(rows[rows.length - 1]); - - if (row != null) - { - row = row.clone(); - row.height = th - sh + row.height; - model.setGeometry(rows[rows.length - 1], row); - } - } - - var pos = (resizeLast) ? null : this.getRowLayout(rows[0], tw); - var y = offset.y; - - // Updates row geometries - for (var i = 0; i < rows.length; i++) - { - var row = this.graph.getCellGeometry(rows[i]); - - if (row != null) - { - row = row.clone(); - row.x = offset.x; - row.width = tw; - row.y = Math.round(y); - - if (resizeLastRow || fixedRows) - { - y += row.height; - } - else - { - y += (row.height / sh) * th; - } - - row.height = Math.round(y) - row.y; - model.setGeometry(rows[i], row); - } - - // Updates cell geometries - sw = Math.max(sw, this.layoutRow(rows[i], pos, row.height, tw)); - } - - if (fixedRows && th < sh) - { - table = table.clone(); - table.height = y + offset.height; - model.setGeometry(parent, table); - } - - if (resizeLast && tw < sw + Graph.minTableColumnWidth) - { - table = table.clone(); - table.width = sw + offset.width + offset.x + Graph.minTableColumnWidth; - model.setGeometry(parent, table); - } - } - } - finally - { - model.endUpdate(); - } - } -}; - -(function() -{ - /** - * Reset the list of processed edges. - */ - var mxGraphViewResetValidationState = mxGraphView.prototype.resetValidationState; - mxGraphView.prototype.resetValidationState = function() - { - mxGraphViewResetValidationState.apply(this, arguments); - - this.validEdges = []; - }; - - /** - * Updates jumps for valid edges and repaints if needed. - */ - var mxGraphViewValidateCellState = mxGraphView.prototype.validateCellState; - mxGraphView.prototype.validateCellState = function(cell, recurse) - { - recurse = (recurse != null) ? recurse : true; - var state = this.getState(cell); - - // Forces repaint if jumps change on a valid edge - if (state != null && recurse && this.graph.model.isEdge(state.cell) && - state.style != null && state.style[mxConstants.STYLE_CURVED] != 1 && - !state.invalid && this.updateLineJumps(state)) - { - this.graph.cellRenderer.redraw(state, false, this.isRendering()); - } - - state = mxGraphViewValidateCellState.apply(this, arguments); - - // Adds to the list of edges that may intersect with later edges - if (state != null && recurse && this.graph.model.isEdge(state.cell) && - state.style != null && state.style[mxConstants.STYLE_CURVED] != 1) - { - // LATER: Reuse jumps for valid edges - this.validEdges.push(state); - } - - return state; - }; - - /** - * Forces repaint if routed points have changed. - */ - var mxCellRendererIsShapeInvalid = mxCellRenderer.prototype.isShapeInvalid; - mxCellRenderer.prototype.isShapeInvalid = function(state, shape) - { - return mxCellRendererIsShapeInvalid.apply(this, arguments) || - (state.routedPoints != null && shape.routedPoints != null && - !mxUtils.equalPoints(shape.routedPoints, state.routedPoints)) - }; - - /** - * Updates jumps for invalid edges. - */ - var mxGraphViewUpdateCellState = mxGraphView.prototype.updateCellState; - mxGraphView.prototype.updateCellState = function(state) - { - mxGraphViewUpdateCellState.apply(this, arguments); - - // Updates jumps on invalid edge before repaint - if (this.graph.model.isEdge(state.cell) && - state.style[mxConstants.STYLE_CURVED] != 1) - { - this.updateLineJumps(state); - } - }; - - /** - * Updates the jumps between given state and processed edges. - */ - mxGraphView.prototype.updateLineJumps = function(state) - { - var pts = state.absolutePoints; - - if (Graph.lineJumpsEnabled) - { - var changed = state.routedPoints != null; - var actual = null; - - if (pts != null && this.validEdges != null && - mxUtils.getValue(state.style, 'jumpStyle', 'none') !== 'none') - { - var thresh = 0.5 * this.scale; - changed = false; - actual = []; - - // Type 0 means normal waypoint, 1 means jump - function addPoint(type, x, y) - { - var rpt = new mxPoint(x, y); - rpt.type = type; - - actual.push(rpt); - var curr = (state.routedPoints != null) ? state.routedPoints[actual.length - 1] : null; - - return curr == null || curr.type != type || curr.x != x || curr.y != y; - }; - - for (var i = 0; i < pts.length - 1; i++) - { - var p1 = pts[i + 1]; - var p0 = pts[i]; - var list = []; - - // Ignores waypoints on straight segments - var pn = pts[i + 2]; - - while (i < pts.length - 2 && - mxUtils.ptSegDistSq(p0.x, p0.y, pn.x, pn.y, - p1.x, p1.y) < 1 * this.scale * this.scale) - { - p1 = pn; - i++; - pn = pts[i + 2]; - } - - changed = addPoint(0, p0.x, p0.y) || changed; - - // Processes all previous edges - for (var e = 0; e < this.validEdges.length; e++) - { - var state2 = this.validEdges[e]; - var pts2 = state2.absolutePoints; - - if (pts2 != null && mxUtils.intersects(state, state2) && state2.style['noJump'] != '1') - { - // Compares each segment of the edge with the current segment - for (var j = 0; j < pts2.length - 1; j++) - { - var p3 = pts2[j + 1]; - var p2 = pts2[j]; - - // Ignores waypoints on straight segments - pn = pts2[j + 2]; - - while (j < pts2.length - 2 && - mxUtils.ptSegDistSq(p2.x, p2.y, pn.x, pn.y, - p3.x, p3.y) < 1 * this.scale * this.scale) - { - p3 = pn; - j++; - pn = pts2[j + 2]; - } - - var pt = mxUtils.intersection(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); - - // Handles intersection between two segments - if (pt != null && (Math.abs(pt.x - p0.x) > thresh || - Math.abs(pt.y - p0.y) > thresh) && - (Math.abs(pt.x - p1.x) > thresh || - Math.abs(pt.y - p1.y) > thresh) && - (Math.abs(pt.x - p2.x) > thresh || - Math.abs(pt.y - p2.y) > thresh) && - (Math.abs(pt.x - p3.x) > thresh || - Math.abs(pt.y - p3.y) > thresh)) - { - var dx = pt.x - p0.x; - var dy = pt.y - p0.y; - var temp = {distSq: dx * dx + dy * dy, x: pt.x, y: pt.y}; - - // Intersections must be ordered by distance from start of segment - for (var t = 0; t < list.length; t++) - { - if (list[t].distSq > temp.distSq) - { - list.splice(t, 0, temp); - temp = null; - - break; - } - } - - // Ignores multiple intersections at segment joint - if (temp != null && (list.length == 0 || - list[list.length - 1].x !== temp.x || - list[list.length - 1].y !== temp.y)) - { - list.push(temp); - } - } - } - } - } - - // Adds ordered intersections to routed points - for (var j = 0; j < list.length; j++) - { - changed = addPoint(1, list[j].x, list[j].y) || changed; - } - } - - var pt = pts[pts.length - 1]; - changed = addPoint(0, pt.x, pt.y) || changed; - } - - state.routedPoints = actual; - - return changed; - } - else - { - return false; - } - }; - - /** - * Overrides painting the actual shape for taking into account jump style. - */ - var mxConnectorPaintLine = mxConnector.prototype.paintLine; - - mxConnector.prototype.paintLine = function (c, absPts, rounded) - { - // Required for checking dirty state - this.routedPoints = (this.state != null) ? this.state.routedPoints : null; - - if (this.outline || this.state == null || this.style == null || - this.state.routedPoints == null || this.state.routedPoints.length == 0) - { - mxConnectorPaintLine.apply(this, arguments); - } - else - { - var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, - mxConstants.LINE_ARCSIZE) / 2; - var size = (parseInt(mxUtils.getValue(this.style, 'jumpSize', - Graph.defaultJumpSize)) - 2) / 2 + this.strokewidth; - var style = mxUtils.getValue(this.style, 'jumpStyle', 'none'); - var moveTo = true; - var last = null; - var len = null; - var pts = []; - var n = null; - c.begin(); - - for (var i = 0; i < this.state.routedPoints.length; i++) - { - var rpt = this.state.routedPoints[i]; - var pt = new mxPoint(rpt.x / this.scale, rpt.y / this.scale); - - // Takes first and last point from passed-in array - if (i == 0) - { - pt = absPts[0]; - } - else if (i == this.state.routedPoints.length - 1) - { - pt = absPts[absPts.length - 1]; - } - - var done = false; - - // Type 1 is an intersection - if (last != null && rpt.type == 1) - { - // Checks if next/previous points are too close - var next = this.state.routedPoints[i + 1]; - var dx = next.x / this.scale - pt.x; - var dy = next.y / this.scale - pt.y; - var dist = dx * dx + dy * dy; - - if (n == null) - { - n = new mxPoint(pt.x - last.x, pt.y - last.y); - len = Math.sqrt(n.x * n.x + n.y * n.y); - - if (len > 0) - { - n.x = n.x * size / len; - n.y = n.y * size / len; - } - else - { - n = null; - } - } - - if (dist > size * size && len > 0) - { - var dx = last.x - pt.x; - var dy = last.y - pt.y; - var dist = dx * dx + dy * dy; - - if (dist > size * size) - { - var p0 = new mxPoint(pt.x - n.x, pt.y - n.y); - var p1 = new mxPoint(pt.x + n.x, pt.y + n.y); - pts.push(p0); - - this.addPoints(c, pts, rounded, arcSize, false, null, moveTo); - - var f = (Math.round(n.x) < 0 || (Math.round(n.x) == 0 - && Math.round(n.y) <= 0)) ? 1 : -1; - moveTo = false; - - if (style == 'sharp') - { - c.lineTo(p0.x - n.y * f, p0.y + n.x * f); - c.lineTo(p1.x - n.y * f, p1.y + n.x * f); - c.lineTo(p1.x, p1.y); - } - else if (style == 'arc') - { - f *= 1.3; - c.curveTo(p0.x - n.y * f, p0.y + n.x * f, - p1.x - n.y * f, p1.y + n.x * f, - p1.x, p1.y); - } - else - { - c.moveTo(p1.x, p1.y); - moveTo = true; - } - - pts = [p1]; - done = true; - } - } - } - else - { - n = null; - } - - if (!done) - { - pts.push(pt); - last = pt; - } - } - - this.addPoints(c, pts, rounded, arcSize, false, null, moveTo); - c.stroke(); - } - }; - - /** - * Adds support for snapToPoint style. - */ - var mxGraphViewUpdateFloatingTerminalPoint = mxGraphView.prototype.updateFloatingTerminalPoint; - - mxGraphView.prototype.updateFloatingTerminalPoint = function(edge, start, end, source) - { - if (start != null && edge != null && - (start.style['snapToPoint'] == '1' || - edge.style['snapToPoint'] == '1')) - { - start = this.getTerminalPort(edge, start, source); - var next = this.getNextPoint(edge, end, source); - - var orth = this.graph.isOrthogonal(edge); - var alpha = mxUtils.toRadians(Number(start.style[mxConstants.STYLE_ROTATION] || '0')); - var center = new mxPoint(start.getCenterX(), start.getCenterY()); - - if (alpha != 0) - { - var cos = Math.cos(-alpha); - var sin = Math.sin(-alpha); - next = mxUtils.getRotatedPoint(next, cos, sin, center); - } - - var border = parseFloat(edge.style[mxConstants.STYLE_PERIMETER_SPACING] || 0); - border += parseFloat(edge.style[(source) ? - mxConstants.STYLE_SOURCE_PERIMETER_SPACING : - mxConstants.STYLE_TARGET_PERIMETER_SPACING] || 0); - var pt = this.getPerimeterPoint(start, next, alpha == 0 && orth, border); - - if (alpha != 0) - { - var cos = Math.cos(alpha); - var sin = Math.sin(alpha); - pt = mxUtils.getRotatedPoint(pt, cos, sin, center); - } - - edge.setAbsoluteTerminalPoint(this.snapToAnchorPoint(edge, start, end, source, pt), source); - } - else - { - mxGraphViewUpdateFloatingTerminalPoint.apply(this, arguments); - } - }; - - mxGraphView.prototype.snapToAnchorPoint = function(edge, start, end, source, pt) - { - if (start != null && edge != null) - { - var constraints = this.graph.getAllConnectionConstraints(start) - var nearest = null; - var dist = null; - - if (constraints != null) - { - for (var i = 0; i < constraints.length; i++) - { - var cp = this.graph.getConnectionPoint(start, constraints[i]); - - if (cp != null) - { - var tmp = (cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y); - - if (dist == null || tmp < dist) - { - nearest = cp; - dist = tmp; - } - } - } - } - - if (nearest != null) - { - pt = nearest; - } - } - - return pt; - }; - - /** - * Adds support for placeholders in text elements of shapes. - */ - var mxStencilEvaluateTextAttribute = mxStencil.prototype.evaluateTextAttribute; - - mxStencil.prototype.evaluateTextAttribute = function(node, attribute, shape) - { - var result = mxStencilEvaluateTextAttribute.apply(this, arguments); - var placeholders = node.getAttribute('placeholders'); - - if (placeholders == '1' && shape.state != null) - { - result = shape.state.view.graph.replacePlaceholders(shape.state.cell, result); - } - - return result; - }; - - /** - * Adds custom stencils defined via shape=stencil(value) style. The value is a base64 encoded, compressed and - * URL encoded XML definition of the shape according to the stencil definition language of mxGraph. - * - * Needs to be in this file to make sure its part of the embed client code. Also the check for ZLib is - * different than for the Editor code. - */ - var mxCellRendererCreateShape = mxCellRenderer.prototype.createShape; - mxCellRenderer.prototype.createShape = function(state) - { - if (state.style != null && typeof(pako) !== 'undefined') - { - var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null); - - // Extracts and decodes stencil XML if shape has the form shape=stencil(value) - if (shape != null && typeof shape === 'string' && shape.substring(0, 8) == 'stencil(') - { - try - { - var stencil = shape.substring(8, shape.length - 1); - var doc = mxUtils.parseXml(Graph.decompress(stencil)); - - return new mxShape(new mxStencil(doc.documentElement)); - } - catch (e) - { - if (window.console != null) - { - console.log('Error in shape: ' + e); - } - } - } - } - - return mxCellRendererCreateShape.apply(this, arguments); - }; -})(); - -/** - * Overrides stencil registry for dynamic loading of stencils. - */ -/** - * Maps from library names to an array of Javascript filenames, - * which are synchronously loaded. Currently only stencil files - * (.xml) and JS files (.js) are supported. - * IMPORTANT: For embedded diagrams to work entries must also - * be added in EmbedServlet.java. - */ -mxStencilRegistry.libraries = {}; - -/** - * Global switch to disable dynamic loading. - */ -mxStencilRegistry.dynamicLoading = true; - -/** - * Global switch to disable eval for JS (preload all JS instead). - */ -mxStencilRegistry.allowEval = true; - -/** - * Stores all package names that have been dynamically loaded. - * Each package is only loaded once. - */ -mxStencilRegistry.packages = []; - -// Extends the default stencil registry to add dynamic loading -mxStencilRegistry.getStencil = function(name) -{ - var result = mxStencilRegistry.stencils[name]; - - if (result == null && mxCellRenderer.defaultShapes[name] == null && mxStencilRegistry.dynamicLoading) - { - var basename = mxStencilRegistry.getBasenameForStencil(name); - - // Loads stencil files and tries again - if (basename != null) - { - var libs = mxStencilRegistry.libraries[basename]; - - if (libs != null) - { - if (mxStencilRegistry.packages[basename] == null) - { - for (var i = 0; i < libs.length; i++) - { - var fname = libs[i]; - - if (fname.toLowerCase().substring(fname.length - 4, fname.length) == '.xml') - { - mxStencilRegistry.loadStencilSet(fname, null); - } - else if (fname.toLowerCase().substring(fname.length - 3, fname.length) == '.js') - { - try - { - if (mxStencilRegistry.allowEval) - { - var req = mxUtils.load(fname); - - if (req != null && req.getStatus() >= 200 && req.getStatus() <= 299) - { - eval.call(window, req.getText()); - } - } - } - catch (e) - { - if (window.console != null) - { - console.log('error in getStencil:', fname, e); - } - } - } - else - { - // FIXME: This does not yet work as the loading is triggered after - // the shape was used in the graph, at which point the keys have - // typically been translated in the calling method. - //mxResources.add(fname); - } - } - - mxStencilRegistry.packages[basename] = 1; - } - } - else - { - // Replaces '_-_' with '_' - basename = basename.replace('_-_', '_'); - mxStencilRegistry.loadStencilSet(STENCIL_PATH + '/' + basename + '.xml', null); - } - - result = mxStencilRegistry.stencils[name]; - } - } - - return result; -}; - -// Returns the basename for the given stencil or null if no file must be -// loaded to render the given stencil. -mxStencilRegistry.getBasenameForStencil = function(name) -{ - var tmp = null; - - if (name != null && typeof name === 'string') - { - var parts = name.split('.'); - - if (parts.length > 0 && parts[0] == 'mxgraph') - { - tmp = parts[1]; - - for (var i = 2; i < parts.length - 1; i++) - { - tmp += '/' + parts[i]; - } - } - } - - return tmp; -}; - -// Loads the given stencil set -mxStencilRegistry.loadStencilSet = function(stencilFile, postStencilLoad, force, async) -{ - force = (force != null) ? force : false; - - // Uses additional cache for detecting previous load attempts - var xmlDoc = mxStencilRegistry.packages[stencilFile]; - - if (force || xmlDoc == null) - { - var install = false; - - if (xmlDoc == null) - { - try - { - if (async) - { - mxStencilRegistry.loadStencil(stencilFile, mxUtils.bind(this, function(xmlDoc2) - { - if (xmlDoc2 != null && xmlDoc2.documentElement != null) - { - mxStencilRegistry.packages[stencilFile] = xmlDoc2; - install = true; - mxStencilRegistry.parseStencilSet(xmlDoc2.documentElement, postStencilLoad, install); - } - })); - - return; - } - else - { - xmlDoc = mxStencilRegistry.loadStencil(stencilFile); - mxStencilRegistry.packages[stencilFile] = xmlDoc; - install = true; - } - } - catch (e) - { - if (window.console != null) - { - console.log('error in loadStencilSet:', stencilFile, e); - } - } - } - - if (xmlDoc != null && xmlDoc.documentElement != null) - { - mxStencilRegistry.parseStencilSet(xmlDoc.documentElement, postStencilLoad, install); - } - } -}; - -// Loads the given stencil XML file. -mxStencilRegistry.loadStencil = function(filename, fn) -{ - if (fn != null) - { - var req = mxUtils.get(filename, mxUtils.bind(this, function(req) - { - fn((req.getStatus() >= 200 && req.getStatus() <= 299) ? req.getXml() : null); - })); - } - else - { - return mxUtils.load(filename).getXml(); - } -}; - -// Takes array of strings -mxStencilRegistry.parseStencilSets = function(stencils) -{ - for (var i = 0; i < stencils.length; i++) - { - mxStencilRegistry.parseStencilSet(mxUtils.parseXml(stencils[i]).documentElement); - } -}; - -// Parses the given stencil set -mxStencilRegistry.parseStencilSet = function(root, postStencilLoad, install) -{ - if (root.nodeName == 'stencils') - { - var shapes = root.firstChild; - - while (shapes != null) - { - if (shapes.nodeName == 'shapes') - { - mxStencilRegistry.parseStencilSet(shapes, postStencilLoad, install); - } - - shapes = shapes.nextSibling; - } - } - else - { - install = (install != null) ? install : true; - var shape = root.firstChild; - var packageName = ''; - var name = root.getAttribute('name'); - - if (name != null) - { - packageName = name + '.'; - } - - while (shape != null) - { - if (shape.nodeType == mxConstants.NODETYPE_ELEMENT) - { - name = shape.getAttribute('name'); - - if (name != null) - { - packageName = packageName.toLowerCase(); - var stencilName = name.replace(/ /g,"_"); - - if (install) - { - mxStencilRegistry.addStencil(packageName + stencilName.toLowerCase(), new mxStencil(shape)); - } - - if (postStencilLoad != null) - { - var w = shape.getAttribute('w'); - var h = shape.getAttribute('h'); - - w = (w == null) ? 80 : parseInt(w, 10); - h = (h == null) ? 80 : parseInt(h, 10); - - postStencilLoad(packageName, stencilName, name, w, h); - } - } - } - - shape = shape.nextSibling; - } - } -}; - -/** - * These overrides are only added if mxVertexHandler is defined (ie. not in embedded graph) - */ -if (typeof mxVertexHandler != 'undefined') -{ - (function() - { - // Sets colors for handles - mxConstants.HANDLE_FILLCOLOR = '#29b6f2'; - mxConstants.HANDLE_STROKECOLOR = '#0088cf'; - mxConstants.VERTEX_SELECTION_COLOR = '#00a8ff'; - mxConstants.OUTLINE_COLOR = '#00a8ff'; - mxConstants.OUTLINE_HANDLE_FILLCOLOR = '#99ccff'; - mxConstants.OUTLINE_HANDLE_STROKECOLOR = '#00a8ff'; - mxConstants.CONNECT_HANDLE_FILLCOLOR = '#cee7ff'; - mxConstants.EDGE_SELECTION_COLOR = '#00a8ff'; - mxConstants.DEFAULT_VALID_COLOR = '#00a8ff'; - mxConstants.LABEL_HANDLE_FILLCOLOR = '#cee7ff'; - mxConstants.GUIDE_COLOR = '#0088cf'; - mxConstants.HIGHLIGHT_OPACITY = 30; - mxConstants.HIGHLIGHT_SIZE = 5; - - // Enables snapping to off-grid terminals for edge waypoints - mxEdgeHandler.prototype.snapToTerminals = true; - - // Enables guides - mxGraphHandler.prototype.guidesEnabled = true; - - // Removes parents where all child cells are moved out - mxGraphHandler.prototype.removeEmptyParents = true; - - // Enables fading of rubberband - mxRubberband.prototype.fadeOut = true; - - // Alt-move disables guides - mxGuide.prototype.isEnabledForEvent = function(evt) - { - return !mxEvent.isAltDown(evt); - }; - - // Ignores all table cells in layouts - var graphLayoutIsVertexIgnored = mxGraphLayout.prototype.isVertexIgnored; - mxGraphLayout.prototype.isVertexIgnored = function(vertex) - { - return graphLayoutIsVertexIgnored.apply(this, arguments) || - this.graph.isTableRow(vertex) || this.graph.isTableCell(vertex); - }; - - // Extends connection handler to enable ctrl+drag for cloning source cell - // since copyOnConnect is now disabled by default - var mxConnectionHandlerCreateTarget = mxConnectionHandler.prototype.isCreateTarget; - mxConnectionHandler.prototype.isCreateTarget = function(evt) - { - return this.graph.isCloneEvent(evt) || mxConnectionHandlerCreateTarget.apply(this, arguments); - }; - - // Overrides highlight shape for connection points - mxConstraintHandler.prototype.createHighlightShape = function() - { - var hl = new mxEllipse(null, this.highlightColor, this.highlightColor, 0); - hl.opacity = mxConstants.HIGHLIGHT_OPACITY; - - return hl; - }; - - // Overrides edge preview to use current edge shape and default style - mxConnectionHandler.prototype.livePreview = true; - mxConnectionHandler.prototype.cursor = 'crosshair'; - - // Uses current edge style for connect preview - mxConnectionHandler.prototype.createEdgeState = function(me) - { - var style = this.graph.createCurrentEdgeStyle(); - var edge = this.graph.createEdge(null, null, null, null, null, style); - var state = new mxCellState(this.graph.view, edge, this.graph.getCellStyle(edge)); - - for (var key in this.graph.currentEdgeStyle) - { - state.style[key] = this.graph.currentEdgeStyle[key]; - } - - return state; - }; - - // Overrides dashed state with current edge style - var connectionHandlerCreateShape = mxConnectionHandler.prototype.createShape; - mxConnectionHandler.prototype.createShape = function() - { - var shape = connectionHandlerCreateShape.apply(this, arguments); - - shape.isDashed = this.graph.currentEdgeStyle[mxConstants.STYLE_DASHED] == '1'; - - return shape; - } - - // Overrides live preview to keep current style - mxConnectionHandler.prototype.updatePreview = function(valid) - { - // do not change color of preview - }; - - // Overrides connection handler to ignore edges instead of not allowing connections - var mxConnectionHandlerCreateMarker = mxConnectionHandler.prototype.createMarker; - mxConnectionHandler.prototype.createMarker = function() - { - var marker = mxConnectionHandlerCreateMarker.apply(this, arguments); - - var markerGetCell = marker.getCell; - marker.getCell = mxUtils.bind(this, function(me) - { - var result = markerGetCell.apply(this, arguments); - - this.error = null; - - return result; - }); - - return marker; - }; - - /** - * - */ - Graph.prototype.defaultVertexStyle = {}; - - /** - * Contains the default style for edges. - */ - Graph.prototype.defaultEdgeStyle = {'edgeStyle': 'orthogonalEdgeStyle', 'rounded': '0', - 'jettySize': 'auto', 'orthogonalLoop': '1'}; - - /** - * Returns the current edge style as a string. - */ - Graph.prototype.createCurrentEdgeStyle = function() - { - var style = 'edgeStyle=' + (this.currentEdgeStyle['edgeStyle'] || 'none') + ';'; - var keys = ['shape', 'curved', 'rounded', 'comic', 'sketch', 'fillWeight', 'hachureGap', - 'hachureAngle', 'jiggle', 'disableMultiStroke', 'disableMultiStrokeFill', 'fillStyle', - 'curveFitting', 'simplification', 'comicStyle', 'jumpStyle', 'jumpSize']; - - for (var i = 0; i < keys.length; i++) - { - if (this.currentEdgeStyle[keys[i]] != null) - { - style += keys[i] + '=' + this.currentEdgeStyle[keys[i]] + ';'; - } - } - - // Overrides the global default to match the default edge style - if (this.currentEdgeStyle['orthogonalLoop'] != null) - { - style += 'orthogonalLoop=' + this.currentEdgeStyle['orthogonalLoop'] + ';'; - } - else if (Graph.prototype.defaultEdgeStyle['orthogonalLoop'] != null) - { - style += 'orthogonalLoop=' + Graph.prototype.defaultEdgeStyle['orthogonalLoop'] + ';'; - } - - // Overrides the global default to match the default edge style - if (this.currentEdgeStyle['jettySize'] != null) - { - style += 'jettySize=' + this.currentEdgeStyle['jettySize'] + ';'; - } - else if (Graph.prototype.defaultEdgeStyle['jettySize'] != null) - { - style += 'jettySize=' + Graph.prototype.defaultEdgeStyle['jettySize'] + ';'; - } - - // Special logic for custom property of elbowEdgeStyle - if (this.currentEdgeStyle['edgeStyle'] == 'elbowEdgeStyle' && this.currentEdgeStyle['elbow'] != null) - { - style += 'elbow=' + this.currentEdgeStyle['elbow'] + ';'; - } - - if (this.currentEdgeStyle['html'] != null) - { - style += 'html=' + this.currentEdgeStyle['html'] + ';'; - } - else - { - style += 'html=1;'; - } - - return style; - }; - - /** - * Removes implicit styles from cell styles so that dark mode works using the - * default values from the stylesheet. - */ - Graph.prototype.updateCellStyles = function(key, value, cells) - { - this.model.beginUpdate(); - try - { - for (var i = 0; i < cells.length; i++) - { - if (this.model.isVertex(cells[i]) || this.model.isEdge(cells[i])) - { - this.setCellStyles(key, null, [cells[i]]); - var style = this.getCellStyle(cells[i]); - var temp = style[key]; - - if (value != ((temp == null) ? mxConstants.NONE : temp)) - { - this.setCellStyles(key, value, [cells[i]]); - } - } - } - } - finally - { - this.model.endUpdate(); - } - }; - - /** - * Hook for subclassers. - */ - Graph.prototype.getPagePadding = function() - { - return new mxPoint(0, 0); - }; - - /** - * Loads the stylesheet for this graph. - */ - Graph.prototype.loadStylesheet = function() - { - var node = (this.themes != null) ? this.themes[this.defaultThemeName] : - (!mxStyleRegistry.dynamicLoading) ? null : - mxUtils.load(STYLE_PATH + '/default.xml').getDocumentElement(); - - if (node != null) - { - var dec = new mxCodec(node.ownerDocument); - dec.decode(node, this.getStylesheet()); - } - }; - - /** - * Creates lookup from object IDs to cell IDs. - */ - Graph.prototype.createCellLookup = function(cells, lookup) - { - lookup = (lookup != null) ? lookup : new Object(); - - for (var i = 0; i < cells.length; i++) - { - var cell = cells[i]; - lookup[mxObjectIdentity.get(cell)] = cell.getId(); - var childCount = this.model.getChildCount(cell); - - for (var j = 0; j < childCount; j++) - { - this.createCellLookup([this.model.getChildAt(cell, j)], lookup); - } - } - - return lookup; - }; - - /** - * Creates lookup from original to cloned cell IDs where mapping is - * the mapping used in cloneCells and lookup is a mapping from - * object IDs to cell IDs. - */ - Graph.prototype.createCellMapping = function(mapping, lookup, cellMapping) - { - cellMapping = (cellMapping != null) ? cellMapping : new Object(); - - for (var objectId in mapping) - { - var cellId = lookup[objectId]; - - if (cellMapping[cellId] == null) - { - // Uses empty string if clone ID was null which means - // the cell was cloned but not inserted into the model. - cellMapping[cellId] = mapping[objectId].getId() || ''; - } - } - - return cellMapping; - }; - - /** - * - */ - Graph.prototype.importGraphModel = function(node, dx, dy, crop) - { - dx = (dx != null) ? dx : 0; - dy = (dy != null) ? dy : 0; - - var codec = new mxCodec(node.ownerDocument); - var tempModel = new mxGraphModel(); - codec.decode(node, tempModel); - var cells = [] - - // Clones cells to remove invalid edges - var cloneMap = new Object(); - var cellMapping = new Object(); - var layers = tempModel.getChildren(this.cloneCell(tempModel.root, - this.isCloneInvalidEdges(), cloneMap)); - - if (layers != null) - { - // Creates lookup from object IDs to cell IDs - var lookup = this.createCellLookup([tempModel.root]); - - // Uses copy as layers are removed from array inside loop - layers = layers.slice(); - - this.model.beginUpdate(); - try - { - // Merges into unlocked current layer if one layer is pasted - if (layers.length == 1 && !this.isCellLocked(this.getDefaultParent())) - { - var children = tempModel.getChildren(layers[0]); - - if (children != null) - { - cells = this.moveCells(children, - dx, dy, false, this.getDefaultParent()); - - // Imported default parent maps to local default parent - cellMapping[tempModel.getChildAt(tempModel.root, 0).getId()] = - this.getDefaultParent().getId(); - } - } - else - { - for (var i = 0; i < layers.length; i++) - { - var children = this.model.getChildren(this.moveCells( - [layers[i]], dx, dy, false, this.model.getRoot())[0]); - - if (children != null) - { - cells = cells.concat(children); - } - } - } - - if (cells != null) - { - // Adds mapping for all cloned entries from imported to local cell ID - this.createCellMapping(cloneMap, lookup, cellMapping); - this.updateCustomLinks(cellMapping, cells); - - if (crop) - { - if (this.isGridEnabled()) - { - dx = this.snap(dx); - dy = this.snap(dy); - } - - var bounds = this.getBoundingBoxFromGeometry(cells, true); - - if (bounds != null) - { - this.moveCells(cells, dx - bounds.x, dy - bounds.y); - } - } - } - } - finally - { - this.model.endUpdate(); - } - } - - return cells; - }; - - /** - * Translates this point by the given vector. - * - * @param {number} dx X-coordinate of the translation. - * @param {number} dy Y-coordinate of the translation. - */ - Graph.prototype.encodeCells = function(cells) - { - var cloneMap = new Object(); - var clones = this.cloneCells(cells, null, cloneMap); - - // Creates a dictionary for fast lookups - var dict = new mxDictionary(); - - for (var i = 0; i < cells.length; i++) - { - dict.put(cells[i], true); - } - - var codec = new mxCodec(); - var model = new mxGraphModel(); - var parent = model.getChildAt(model.getRoot(), 0); - - for (var i = 0; i < clones.length; i++) - { - model.add(parent, clones[i]); - - // Checks for orphaned relative children and makes absolute - var state = this.view.getState(cells[i]); - - if (state != null) - { - var geo = this.getCellGeometry(clones[i]); - - if (geo != null && geo.relative && !this.model.isEdge(cells[i]) && - dict.get(this.model.getParent(cells[i])) == null) - { - geo.offset = null; - geo.relative = false; - geo.x = state.x / state.view.scale - state.view.translate.x; - geo.y = state.y / state.view.scale - state.view.translate.y; - } - } - } - - this.updateCustomLinks(this.createCellMapping(cloneMap, - this.createCellLookup(cells)), clones); - - return codec.encode(model); - }; - - /** - * Overridden to check for table shape. - */ - Graph.prototype.isSwimlane = function(cell, ignoreState) - { - if (cell != null && this.model.getParent(cell) != this.model.getRoot() && - !this.model.isEdge(cell)) - { - var shape = this.getCurrentCellStyle(cell, ignoreState) - [mxConstants.STYLE_SHAPE]; - - return shape == mxConstants.SHAPE_SWIMLANE || shape == 'table'; - } - - return false; - }; - - /** - * Overridden to add expand style. - */ - var graphIsExtendParent = Graph.prototype.isExtendParent; - Graph.prototype.isExtendParent = function(cell) - { - var parent = this.model.getParent(cell); - - if (parent != null) - { - var style = this.getCurrentCellStyle(parent); - - if (style['expand'] != null) - { - return style['expand'] != '0'; - } - } - - return graphIsExtendParent.apply(this, arguments) && - (parent == null || !this.isTable(parent)); - }; - - /** - * Overridden to use table cell instead of table as parent. - */ - var graphSplitEdge = Graph.prototype.splitEdge; - Graph.prototype.splitEdge = function(edge, cells, newEdge, dx, dy, x, y, parent) - { - if (parent == null) - { - parent = this.model.getParent(edge); - - if (this.isTable(parent) || this.isTableRow(parent)) - { - parent = this.getCellAt(x, y, null, true, false); - } - } - - graphSplitEdge.apply(this, [edge, cells, newEdge, dx, dy, x, y, parent]); - }; - - /** - * Overridden to flatten cell hierarchy for selecting next and previous. - */ - var graphSelectCell = Graph.prototype.selectCell; - Graph.prototype.selectCell = function(isNext, isParent, isChild) - { - if (isParent || isChild) - { - graphSelectCell.apply(this, arguments); - } - else - { - var cell = this.getSelectionCell(); - var index = null; - var cells = []; - - // LATER: Reverse traverse order for !isNext - var flatten = mxUtils.bind(this, function(temp) - { - if (this.view.getState(temp) != null && - (this.model.isVertex(temp) || - this.model.isEdge(temp))) - { - cells.push(temp); - - if (temp == cell) - { - index = cells.length - 1; - } - else if ((isNext && cell == null && cells.length > 0) || - (index != null && ((isNext && cells.length > index)) || - (!isNext && index > 0))) - { - return; - } - } - - for (var i = 0; i < this.model.getChildCount(temp); i++) - { - flatten(this.model.getChildAt(temp, i)); - } - }); - - flatten(this.model.root); - - if (cells.length > 0) - { - if (index != null) - { - index = mxUtils.mod(index + ((isNext) ? 1 : -1), cells.length) - } - else - { - index = 0; - } - - this.setSelectionCell(cells[index]); - } - } - }; - - /** - * Overrides cloning cells in moveCells. - */ - var graphMoveCells = Graph.prototype.moveCells; - Graph.prototype.moveCells = function(cells, dx, dy, clone, target, evt, mapping) - { - mapping = (mapping != null) ? mapping : new Object(); - - // Replaces source tables with rows - if (this.isTable(target)) - { - var newCells = []; - - for (var i = 0; i < cells.length; i++) - { - if (this.isTable(cells[i])) - { - newCells = newCells.concat(this.model.getChildCells(cells[i], true).reverse()); - } - else - { - newCells.push(cells[i]); - } - } - - cells = newCells; - } - - this.model.beginUpdate(); - try - { - // Updates source and target table heights and matches - // column count for moving rows between tables - var sourceTables = []; - - for (var i = 0; i < cells.length; i++) - { - if (target != null && this.isTableRow(cells[i])) - { - var parent = this.model.getParent(cells[i]); - var row = this.getCellGeometry(cells[i]); - - if (this.isTable(parent)) - { - sourceTables.push(parent); - } - - if (parent != null && row != null && - this.isTable(parent) && - this.isTable(target) && - (clone || parent != target)) - { - if (!clone) - { - var table = this.getCellGeometry(parent); - - if (table != null) - { - table = table.clone(); - table.height -= row.height; - this.model.setGeometry(parent, table); - } - } - - var table = this.getCellGeometry(target); - - if (table != null) - { - table = table.clone(); - table.height += row.height; - this.model.setGeometry(target, table); - } - - // Matches column count - var rows = this.model.getChildCells(target, true); - - if (rows.length > 0) - { - cells[i] = (clone) ? this.cloneCell(cells[i]) : cells[i]; - var sourceCols = this.model.getChildCells(cells[i], true); - var cols = this.model.getChildCells(rows[0], true); - var count = cols.length - sourceCols.length; - - if (count > 0) - { - for (var j = 0; j < count; j++) - { - var col = this.cloneCell(sourceCols[sourceCols.length - 1]); - - if (col != null) - { - col.value = ''; - - this.model.add(cells[i], col); - } - } - } - else if (count < 0) - { - for (var j = 0; j > count; j--) - { - this.model.remove(sourceCols[sourceCols.length + j - 1]); - } - } - - // Updates column widths - sourceCols = this.model.getChildCells(cells[i], true); - - for (var j = 0; j < cols.length; j++) - { - var geo = this.getCellGeometry(cols[j]); - var geo2 = this.getCellGeometry(sourceCols[j]); - - if (geo != null && geo2 != null) - { - geo2 = geo2.clone(); - geo2.width = geo.width; - - this.model.setGeometry(sourceCols[j], geo2); - } - } - } - } - } - } - - var result = graphMoveCells.apply(this, arguments); - - // Removes empty tables - for (var i = 0; i < sourceTables.length; i++) - { - if (!clone && this.model.contains(sourceTables[i]) && - this.model.getChildCount(sourceTables[i]) == 0) - { - this.model.remove(sourceTables[i]); - } - } - - if (clone) - { - this.updateCustomLinks(this.createCellMapping(mapping, - this.createCellLookup(cells)), result); - } - } - finally - { - this.model.endUpdate(); - } - - return result; - }; - - /** - * Overriddes to delete label for table cells. - */ - var graphRemoveCells = Graph.prototype.removeCells; - Graph.prototype.removeCells = function(cells, includeEdges) - { - var result = []; - - this.model.beginUpdate(); - try - { - // Clears labels on table cells - for (var i = 0; i < cells.length; i++) - { - if (this.isTableCell(cells[i])) - { - var row = this.model.getParent(cells[i]); - var table = this.model.getParent(row); - - // Removes table if one cell in one row left - if (this.model.getChildCount(row) == 1 && - this.model.getChildCount(table) == 1) - { - if (mxUtils.indexOf(cells, table) < 0 && - mxUtils.indexOf(result, table) < 0) - { - result.push(table); - } - } - else - { - this.labelChanged(cells[i], ''); - } - } - else - { - // Deletes table if all rows are removed - if (this.isTableRow(cells[i])) - { - var table = this.model.getParent(cells[i]); - - if (mxUtils.indexOf(cells, table) < 0 && - mxUtils.indexOf(result, table) < 0) - { - var rows = this.model.getChildCells(table, true); - var deleteCount = 0; - - for (var j = 0; j < rows.length; j++) - { - if (mxUtils.indexOf(cells, rows[j]) >= 0) - { - deleteCount++; - } - } - - if (deleteCount == rows.length) - { - result.push(table); - } - } - } - - result.push(cells[i]); - } - } - - result = graphRemoveCells.apply(this, [result, includeEdges]); - } - finally - { - this.model.endUpdate(); - } - - return result; - }; - - /** - * Updates cells IDs for custom links in the given cells. - */ - Graph.prototype.updateCustomLinks = function(mapping, cells) - { - for (var i = 0; i < cells.length; i++) - { - if (cells[i] != null) - { - this.updateCustomLinksForCell(mapping, cells[i]); - } - } - }; - - /** - * Updates cell IDs in custom links on the given cell and its label. - */ - Graph.prototype.updateCustomLinksForCell = function(mapping, cell) - { - // Hook for subclassers - }; - - /** - * Overrides method to provide connection constraints for shapes. - */ - Graph.prototype.getAllConnectionConstraints = function(terminal, source) - { - if (terminal != null) - { - var constraints = mxUtils.getValue(terminal.style, 'points', null); - - if (constraints != null) - { - // Requires an array of arrays with x, y (0..1), an optional - // [perimeter (0 or 1), dx, and dy] eg. points=[[0,0,1,-10,10],[0,1,0],[1,1]] - var result = []; - - try - { - var c = JSON.parse(constraints); - - for (var i = 0; i < c.length; i++) - { - var tmp = c[i]; - result.push(new mxConnectionConstraint(new mxPoint(tmp[0], tmp[1]), (tmp.length > 2) ? tmp[2] != '0' : true, - null, (tmp.length > 3) ? tmp[3] : 0, (tmp.length > 4) ? tmp[4] : 0)); - } - } - catch (e) - { - // ignore - } - - return result; - } - else if (terminal.shape != null && terminal.shape.bounds != null) - { - var dir = terminal.shape.direction; - var bounds = terminal.shape.bounds; - var scale = terminal.shape.scale; - var w = bounds.width / scale; - var h = bounds.height / scale; - - if (dir == mxConstants.DIRECTION_NORTH || dir == mxConstants.DIRECTION_SOUTH) - { - var tmp = w; - w = h; - h = tmp; - } - - constraints = terminal.shape.getConstraints(terminal.style, w, h); - - if (constraints != null) - { - return constraints; - } - else if (terminal.shape.stencil != null && terminal.shape.stencil.constraints != null) - { - return terminal.shape.stencil.constraints; - } - else if (terminal.shape.constraints != null) - { - return terminal.shape.constraints; - } - } - } - - return null; - }; - - /** - * Inverts the elbow edge style without removing existing styles. - */ - Graph.prototype.flipEdge = function(edge) - { - if (edge != null) - { - var style = this.getCurrentCellStyle(edge); - var elbow = mxUtils.getValue(style, mxConstants.STYLE_ELBOW, - mxConstants.ELBOW_HORIZONTAL); - var value = (elbow == mxConstants.ELBOW_HORIZONTAL) ? - mxConstants.ELBOW_VERTICAL : mxConstants.ELBOW_HORIZONTAL; - this.setCellStyles(mxConstants.STYLE_ELBOW, value, [edge]); - } - }; - - /** - * Disables drill-down for non-swimlanes. - */ - Graph.prototype.isValidRoot = function(cell) - { - // Counts non-relative children - var childCount = this.model.getChildCount(cell); - var realChildCount = 0; - - for (var i = 0; i < childCount; i++) - { - var child = this.model.getChildAt(cell, i); - - if (this.model.isVertex(child)) - { - var geometry = this.getCellGeometry(child); - - if (geometry != null && !geometry.relative) - { - realChildCount++; - } - } - } - - return realChildCount > 0 || this.isContainer(cell); - }; - - /** - * Disables drill-down for non-swimlanes. - */ - Graph.prototype.isValidDropTarget = function(cell, cells, evt) - { - var style = this.getCurrentCellStyle(cell); - var tables = true; - var rows = true; - - for (var i = 0; i < cells.length && rows; i++) - { - tables = tables && this.isTable(cells[i]); - rows = rows && this.isTableRow(cells[i]); - } - - return (mxUtils.getValue(style, 'part', '0') != '1' || this.isContainer(cell)) && - mxUtils.getValue(style, 'dropTarget', '1') != '0' && - (mxGraph.prototype.isValidDropTarget.apply(this, arguments) || - this.isContainer(cell)) && !this.isTableRow(cell) && - (!this.isTable(cell) || rows || tables); - }; - - /** - * Overrides createGroupCell to set the group style for new groups to 'group'. - */ - Graph.prototype.createGroupCell = function() - { - var group = mxGraph.prototype.createGroupCell.apply(this, arguments); - group.setStyle('group'); - - return group; - }; - - /** - * Disables extending parents with stack layouts on add - */ - Graph.prototype.isExtendParentsOnAdd = function(cell) - { - var result = mxGraph.prototype.isExtendParentsOnAdd.apply(this, arguments); - - if (result && cell != null && this.layoutManager != null) - { - var parent = this.model.getParent(cell); - - if (parent != null) - { - var layout = this.layoutManager.getLayout(parent); - - if (layout != null && layout.constructor == mxStackLayout) - { - result = false; - } - } - } - - return result; - }; - - /** - * Overrides autosize to add a border. - */ - Graph.prototype.getPreferredSizeForCell = function(cell) - { - var result = mxGraph.prototype.getPreferredSizeForCell.apply(this, arguments); - - // Adds buffer - if (result != null) - { - result.width += 10; - result.height += 4; - - if (this.gridEnabled) - { - result.width = this.snap(result.width); - result.height = this.snap(result.height); - } - } - - return result; - } - - /** - * Turns the given cells and returns the changed cells. - */ - Graph.prototype.turnShapes = function(cells, backwards) - { - var model = this.getModel(); - var select = []; - - model.beginUpdate(); - try - { - for (var i = 0; i < cells.length; i++) - { - var cell = cells[i]; - - if (model.isEdge(cell)) - { - var src = model.getTerminal(cell, true); - var trg = model.getTerminal(cell, false); - - model.setTerminal(cell, trg, true); - model.setTerminal(cell, src, false); - - var geo = model.getGeometry(cell); - - if (geo != null) - { - geo = geo.clone(); - - if (geo.points != null) - { - geo.points.reverse(); - } - - var sp = geo.getTerminalPoint(true); - var tp = geo.getTerminalPoint(false) - - geo.setTerminalPoint(sp, false); - geo.setTerminalPoint(tp, true); - model.setGeometry(cell, geo); - - // Inverts constraints - var edgeState = this.view.getState(cell); - var sourceState = this.view.getState(src); - var targetState = this.view.getState(trg); - - if (edgeState != null) - { - var sc = (sourceState != null) ? this.getConnectionConstraint(edgeState, sourceState, true) : null; - var tc = (targetState != null) ? this.getConnectionConstraint(edgeState, targetState, false) : null; - - this.setConnectionConstraint(cell, src, true, tc); - this.setConnectionConstraint(cell, trg, false, sc); - } - - select.push(cell); - } - } - else if (model.isVertex(cell)) - { - var geo = this.getCellGeometry(cell); - - if (geo != null) - { - // Rotates the size and position in the geometry - if (!this.isTable(cell) && !this.isTableRow(cell) && - !this.isTableCell(cell) && !this.isSwimlane(cell)) - { - geo = geo.clone(); - geo.x += geo.width / 2 - geo.height / 2; - geo.y += geo.height / 2 - geo.width / 2; - var tmp = geo.width; - geo.width = geo.height; - geo.height = tmp; - model.setGeometry(cell, geo); - } - - // Reads the current direction and advances by 90 degrees - var state = this.view.getState(cell); - - if (state != null) - { - var dirs = [mxConstants.DIRECTION_EAST, mxConstants.DIRECTION_SOUTH, - mxConstants.DIRECTION_WEST, mxConstants.DIRECTION_NORTH]; - var dir = mxUtils.getValue(state.style, mxConstants.STYLE_DIRECTION, - mxConstants.DIRECTION_EAST); - this.setCellStyles(mxConstants.STYLE_DIRECTION, - dirs[mxUtils.mod(mxUtils.indexOf(dirs, dir) + - ((backwards) ? -1 : 1), dirs.length)], [cell]); - } - - select.push(cell); - } - } - } - } - finally - { - model.endUpdate(); - } - - return select; - }; - - /** - * Returns true if the given stencil contains any placeholder text. - */ - Graph.prototype.stencilHasPlaceholders = function(stencil) - { - if (stencil != null && stencil.fgNode != null) - { - var node = stencil.fgNode.firstChild; - - while (node != null) - { - if (node.nodeName == 'text' && node.getAttribute('placeholders') == '1') - { - return true; - } - - node = node.nextSibling; - } - } - - return false; - }; - - /** - * Updates the child cells with placeholders if metadata of a - * cell has changed and propagates geometry changes in tables. - */ - var graphProcessChange = Graph.prototype.processChange; - Graph.prototype.processChange = function(change) - { - if (change instanceof mxGeometryChange && - (this.isTableCell(change.cell) || this.isTableRow(change.cell)) && - ((change.previous == null && change.geometry != null) || - (change.previous != null && !change.previous.equals(change.geometry)))) - { - var cell = change.cell; - - if (this.isTableCell(cell)) - { - cell = this.model.getParent(cell); - } - - if (this.isTableRow(cell)) - { - cell = this.model.getParent(cell); - } - - // Forces repaint of table with unchanged style and geometry - var state = this.view.getState(cell); - - if (state != null && state.shape != null) - { - this.view.invalidate(cell); - state.shape.bounds = null; - } - } - - graphProcessChange.apply(this, arguments); - - if (change instanceof mxValueChange && change.cell != null && - change.cell.value != null && typeof(change.cell.value) == 'object') - { - this.invalidateDescendantsWithPlaceholders(change.cell); - } - }; - - /** - * Replaces the given element with a span. - */ - Graph.prototype.invalidateDescendantsWithPlaceholders = function(cell) - { - // Invalidates all descendants with placeholders - var desc = this.model.getDescendants(cell); - - // LATER: Check if only label or tooltip have changed - if (desc.length > 0) - { - for (var i = 0; i < desc.length; i++) - { - var state = this.view.getState(desc[i]); - - if (state != null && state.shape != null && state.shape.stencil != null && - this.stencilHasPlaceholders(state.shape.stencil)) - { - this.removeStateForCell(desc[i]); - } - else if (this.isReplacePlaceholders(desc[i])) - { - this.view.invalidate(desc[i], false, false); - } - } - } - }; - - /** - * Replaces the given element with a span. - */ - Graph.prototype.replaceElement = function(elt, tagName) - { - var span = elt.ownerDocument.createElement((tagName != null) ? tagName : 'span'); - var attributes = Array.prototype.slice.call(elt.attributes); - - while (attr = attributes.pop()) - { - span.setAttribute(attr.nodeName, attr.nodeValue); - } - - span.innerHTML = elt.innerHTML; - elt.parentNode.replaceChild(span, elt); - }; - - /** - * - */ - Graph.prototype.processElements = function(elt, fn) - { - if (elt != null) - { - var elts = elt.getElementsByTagName('*'); - - for (var i = 0; i < elts.length; i++) - { - fn(elts[i]); - } - } - }; - - /** - * Handles label changes for XML user objects. - */ - Graph.prototype.updateLabelElements = function(cells, fn, tagName) - { - cells = (cells != null) ? cells : this.getSelectionCells(); - var div = document.createElement('div'); - - for (var i = 0; i < cells.length; i++) - { - // Changes font tags inside HTML labels - if (this.isHtmlLabel(cells[i])) - { - var label = this.convertValueToString(cells[i]); - - if (label != null && label.length > 0) - { - div.innerHTML = label; - var elts = div.getElementsByTagName((tagName != null) ? tagName : '*'); - - for (var j = 0; j < elts.length; j++) - { - fn(elts[j]); - } - - if (div.innerHTML != label) - { - this.cellLabelChanged(cells[i], div.innerHTML); - } - } - } - } - }; - - /** - * Handles label changes for XML user objects. - */ - Graph.prototype.cellLabelChanged = function(cell, value, autoSize) - { - // Removes all illegal control characters in user input - value = Graph.zapGremlins(value); - - this.model.beginUpdate(); - try - { - if (cell.value != null && typeof cell.value == 'object') - { - if (this.isReplacePlaceholders(cell) && - cell.getAttribute('placeholder') != null) - { - // LATER: Handle delete, name change - var name = cell.getAttribute('placeholder'); - var current = cell; - - while (current != null) - { - if (current == this.model.getRoot() || (current.value != null && - typeof(current.value) == 'object' && current.hasAttribute(name))) - { - this.setAttributeForCell(current, name, value); - - break; - } - - current = this.model.getParent(current); - } - } - - var tmp = cell.value.cloneNode(true); - - if (Graph.translateDiagram && Graph.diagramLanguage != null && - tmp.hasAttribute('label_' + Graph.diagramLanguage)) - { - tmp.setAttribute('label_' + Graph.diagramLanguage, value); - } - else - { - tmp.setAttribute('label', value); - } - - value = tmp; - } - - mxGraph.prototype.cellLabelChanged.apply(this, arguments); - } - finally - { - this.model.endUpdate(); - } - }; - - /** - * Removes transparent empty groups if all children are removed. - */ - Graph.prototype.cellsRemoved = function(cells) - { - if (cells != null) - { - var dict = new mxDictionary(); - - for (var i = 0; i < cells.length; i++) - { - dict.put(cells[i], true); - } - - // LATER: Recurse up the cell hierarchy - var parents = []; - - for (var i = 0; i < cells.length; i++) - { - var parent = this.model.getParent(cells[i]); - - if (parent != null && !dict.get(parent)) - { - dict.put(parent, true); - parents.push(parent); - } - } - - for (var i = 0; i < parents.length; i++) - { - var state = this.view.getState(parents[i]); - - if (state != null && (this.model.isEdge(state.cell) || - this.model.isVertex(state.cell)) && - this.isCellDeletable(state.cell) && - this.isTransparentState(state)) - { - var allChildren = true; - - for (var j = 0; j < this.model.getChildCount(state.cell) && allChildren; j++) - { - if (!dict.get(this.model.getChildAt(state.cell, j))) - { - allChildren = false; - } - } - - if (allChildren) - { - cells.push(state.cell); - } - } - } - } - - mxGraph.prototype.cellsRemoved.apply(this, arguments); - }; - - /** - * Overrides ungroup to check if group should be removed. - */ - Graph.prototype.removeCellsAfterUngroup = function(cells) - { - var cellsToRemove = []; - - for (var i = 0; i < cells.length; i++) - { - if (this.isCellDeletable(cells[i]) && - this.isTransparentState( - this.view.getState(cells[i]))) - { - cellsToRemove.push(cells[i]); - } - } - - cells = cellsToRemove; - - mxGraph.prototype.removeCellsAfterUngroup.apply(this, arguments); - }; - - /** - * Sets the link for the given cell. - */ - Graph.prototype.setLinkForCell = function(cell, link) - { - this.setAttributeForCell(cell, 'link', link); - }; - - /** - * Sets the link for the given cell. - */ - Graph.prototype.setTooltipForCell = function(cell, link) - { - var key = 'tooltip'; - - if (Graph.translateDiagram && Graph.diagramLanguage != null && - mxUtils.isNode(cell.value) && cell.value.hasAttribute('tooltip_' + Graph.diagramLanguage)) - { - key = 'tooltip_' + Graph.diagramLanguage; - } - - this.setAttributeForCell(cell, key, link); - }; - - /** - * Returns the cells in the model (or given array) that have all of the - * given tags in their tags property. - */ - Graph.prototype.getAttributeForCell = function(cell, attributeName, defaultValue) - { - var value = (cell.value != null && typeof cell.value === 'object') ? - cell.value.getAttribute(attributeName) : null; - - return (value != null) ? value : defaultValue; - }; - - /** - * Sets the link for the given cell. - */ - Graph.prototype.setAttributeForCell = function(cell, attributeName, attributeValue) - { - var value = null; - - if (cell.value != null && typeof(cell.value) == 'object') - { - value = cell.value.cloneNode(true); - } - else - { - var doc = mxUtils.createXmlDocument(); - - value = doc.createElement('UserObject'); - value.setAttribute('label', cell.value || ''); - } - - if (attributeValue != null) - { - value.setAttribute(attributeName, attributeValue); - } - else - { - value.removeAttribute(attributeName); - } - - this.model.setValue(cell, value); - }; - - /** - * Overridden to stop moving edge labels between cells. - */ - var graphGetDropTarget = Graph.prototype.getDropTarget; - Graph.prototype.getDropTarget = function(cells, evt, cell, clone) - { - var model = this.getModel(); - - // Disables drop into group if alt is pressed - if (mxEvent.isAltDown(evt)) - { - return null; - } - - // Disables dragging edge labels out of edges - for (var i = 0; i < cells.length; i++) - { - if (this.model.isEdge(this.model.getParent(cells[i]))) - { - return null; - } - } - - var target = graphGetDropTarget.apply(this, arguments); - - // Always drops rows to tables - var rows = true; - - for (var i = 0; i < cells.length && rows; i++) - { - rows = rows && this.isTableRow(cells[i]); - } - - if (rows) - { - if (this.isTableCell(target)) - { - target = this.model.getParent(target); - } - - if (this.isTableRow(target)) - { - target = this.model.getParent(target); - } - - if (!this.isTable(target)) - { - target = null; - } - } - - return target; - }; - - /** - * Overrides double click handling to avoid accidental inserts of new labels in dblClick below. - */ - Graph.prototype.click = function(me) - { - mxGraph.prototype.click.call(this, me); - - // Stores state and source for checking in dblClick - this.firstClickState = me.getState(); - this.firstClickSource = me.getSource(); - }; - - /** - * Overrides double click handling to add the tolerance and inserting text. - */ - Graph.prototype.dblClick = function(evt, cell) - { - if (this.isEnabled()) - { - cell = this.insertTextForEvent(evt, cell); - mxGraph.prototype.dblClick.call(this, evt, cell); - } - }; - - /** - * Overrides double click handling to add the tolerance and inserting text. - */ - Graph.prototype.insertTextForEvent = function(evt, cell) - { - var pt = mxUtils.convertPoint(this.container, mxEvent.getClientX(evt), mxEvent.getClientY(evt)); - - // Automatically adds new child cells to edges on double click - if (evt != null && !this.model.isVertex(cell)) - { - var state = (this.model.isEdge(cell)) ? this.view.getState(cell) : null; - var src = mxEvent.getSource(evt); - - if ((this.firstClickState == state && this.firstClickSource == src) && - (state == null || (state.text == null || state.text.node == null || - state.text.boundingBox == null || (!mxUtils.contains(state.text.boundingBox, - pt.x, pt.y) && !mxUtils.isAncestorNode(state.text.node, mxEvent.getSource(evt))))) && - ((state == null && !this.isCellLocked(this.getDefaultParent())) || - (state != null && !this.isCellLocked(state.cell))) && - (state != null || (mxClient.IS_VML && src == this.view.getCanvas()) || - (mxClient.IS_SVG && src == this.view.getCanvas().ownerSVGElement))) - { - if (state == null) - { - state = this.view.getState(this.getCellAt(pt.x, pt.y)); - } - - cell = this.addText(pt.x, pt.y, state); - } - } - - return cell; - }; - - /** - * Returns a point that specifies the location for inserting cells. - */ - Graph.prototype.getInsertPoint = function() - { - var gs = this.getGridSize(); - var dx = this.container.scrollLeft / this.view.scale - this.view.translate.x; - var dy = this.container.scrollTop / this.view.scale - this.view.translate.y; - - if (this.pageVisible) - { - var layout = this.getPageLayout(); - var page = this.getPageSize(); - dx = Math.max(dx, layout.x * page.width); - dy = Math.max(dy, layout.y * page.height); - } - - return new mxPoint(this.snap(dx + gs), this.snap(dy + gs)); - }; - - /** - * - */ - Graph.prototype.getFreeInsertPoint = function() - { - var view = this.view; - var bds = this.getGraphBounds(); - var pt = this.getInsertPoint(); - - // Places at same x-coord and 2 grid sizes below existing graph - var x = this.snap(Math.round(Math.max(pt.x, bds.x / view.scale - view.translate.x + - ((bds.width == 0) ? 2 * this.gridSize : 0)))); - var y = this.snap(Math.round(Math.max(pt.y, (bds.y + bds.height) / view.scale - view.translate.y + - 2 * this.gridSize))); - - return new mxPoint(x, y); - }; - - /** - * - */ - Graph.prototype.getCenterInsertPoint = function(bbox) - { - bbox = (bbox != null) ? bbox : new mxRectangle(); - - if (mxUtils.hasScrollbars(this.container)) - { - return new mxPoint( - this.snap(Math.round((this.container.scrollLeft + this.container.clientWidth / 2) / - this.view.scale - this.view.translate.x - bbox.width / 2)), - this.snap(Math.round((this.container.scrollTop + this.container.clientHeight / 2) / - this.view.scale - this.view.translate.y - bbox.height / 2))); - } - else - { - return new mxPoint( - this.snap(Math.round(this.container.clientWidth / 2 / this.view.scale - - this.view.translate.x - bbox.width / 2)), - this.snap(Math.round(this.container.clientHeight / 2 / this.view.scale - - this.view.translate.y - bbox.height / 2))); - } - }; - - /** - * Hook for subclassers to return true if the current insert point was defined - * using a mouse hover event. - */ - Graph.prototype.isMouseInsertPoint = function() - { - return false; - }; - - /** - * Adds a new label at the given position and returns the new cell. State is - * an optional edge state to be used as the parent for the label. Vertices - * are not allowed currently as states. - */ - Graph.prototype.addText = function(x, y, state) - { - // Creates a new edge label with a predefined text - var label = new mxCell(); - label.value = 'Text'; - label.geometry = new mxGeometry(0, 0, 0, 0); - label.vertex = true; - var style = 'html=1;align=center;verticalAlign=middle;resizable=0;points=[];'; - - if (state != null && this.model.isEdge(state.cell)) - { - label.style = 'edgeLabel;' + style; - label.geometry.relative = true; - label.connectable = false; - - // Resets the relative location stored inside the geometry - var pt2 = this.view.getRelativePoint(state, x, y); - label.geometry.x = Math.round(pt2.x * 10000) / 10000; - label.geometry.y = Math.round(pt2.y); - - // Resets the offset inside the geometry to find the offset from the resulting point - label.geometry.offset = new mxPoint(0, 0); - pt2 = this.view.getPoint(state, label.geometry); - - var scale = this.view.scale; - label.geometry.offset = new mxPoint(Math.round((x - pt2.x) / scale), Math.round((y - pt2.y) / scale)); - } - else - { - var tr = this.view.translate; - label.style = 'text;' + style; - label.geometry.width = 40; - label.geometry.height = 20; - label.geometry.x = Math.round(x / this.view.scale) - - tr.x - ((state != null) ? state.origin.x : 0); - label.geometry.y = Math.round(y / this.view.scale) - - tr.y - ((state != null) ? state.origin.y : 0); - label.style += 'autosize=1;' - } - - this.getModel().beginUpdate(); - try - { - this.addCells([label], (state != null) ? state.cell : null); - this.fireEvent(new mxEventObject('textInserted', 'cells', [label])); - - // Updates size of text after possible change of style via event - this.autoSizeCell(label); - } - finally - { - this.getModel().endUpdate(); - } - - return label; - }; - - /** - * Adds a handler for clicking on shapes with links. This replaces all links in labels. - */ - Graph.prototype.addClickHandler = function(highlight, beforeClick, onClick) - { - // Replaces links in labels for consistent right-clicks - var checkLinks = mxUtils.bind(this, function() - { - var links = this.container.getElementsByTagName('a'); - - if (links != null) - { - for (var i = 0; i < links.length; i++) - { - var href = this.getAbsoluteUrl(links[i].getAttribute('href')); - - if (href != null) - { - links[i].setAttribute('rel', this.linkRelation); - links[i].setAttribute('href', href); - - if (beforeClick != null) - { - mxEvent.addGestureListeners(links[i], null, null, beforeClick); - } - } - } - } - }); - - this.model.addListener(mxEvent.CHANGE, checkLinks); - checkLinks(); - - var cursor = this.container.style.cursor; - var tol = this.getTolerance(); - var graph = this; - - var mouseListener = - { - currentState: null, - currentLink: null, - highlight: (highlight != null && highlight != '' && highlight != mxConstants.NONE) ? - new mxCellHighlight(graph, highlight, 4) : null, - startX: 0, - startY: 0, - scrollLeft: 0, - scrollTop: 0, - updateCurrentState: function(me) - { - var tmp = me.sourceState; - - // Gets topmost intersecting cell with link - if (tmp == null || graph.getLinkForCell(tmp.cell) == null) - { - var cell = graph.getCellAt(me.getGraphX(), me.getGraphY(), null, null, null, function(state, x, y) - { - return graph.getLinkForCell(state.cell) == null; - }); - - tmp = graph.view.getState(cell); - } - - if (tmp != this.currentState) - { - if (this.currentState != null) - { - this.clear(); - } - - this.currentState = tmp; - - if (this.currentState != null) - { - this.activate(this.currentState); - } - } - }, - mouseDown: function(sender, me) - { - this.startX = me.getGraphX(); - this.startY = me.getGraphY(); - this.scrollLeft = graph.container.scrollLeft; - this.scrollTop = graph.container.scrollTop; - - if (this.currentLink == null && graph.container.style.overflow == 'auto') - { - graph.container.style.cursor = 'move'; - } - - this.updateCurrentState(me); - }, - mouseMove: function(sender, me) - { - if (graph.isMouseDown) - { - if (this.currentLink != null) - { - var dx = Math.abs(this.startX - me.getGraphX()); - var dy = Math.abs(this.startY - me.getGraphY()); - - if (dx > tol || dy > tol) - { - this.clear(); - } - } - } - else - { - // Checks for parent link - var linkNode = me.getSource(); - - while (linkNode != null && linkNode.nodeName.toLowerCase() != 'a') - { - linkNode = linkNode.parentNode; - } - - if (linkNode != null) - { - this.clear(); - } - else - { - if (graph.tooltipHandler != null && this.currentLink != null && this.currentState != null) - { - graph.tooltipHandler.reset(me, true, this.currentState); - } - - if (this.currentState != null && (me.getState() == this.currentState || me.sourceState == null) && - graph.intersects(this.currentState, me.getGraphX(), me.getGraphY())) - { - return; - } - - this.updateCurrentState(me); - } - } - }, - mouseUp: function(sender, me) - { - var source = me.getSource(); - var evt = me.getEvent(); - - // Checks for parent link - var linkNode = source; - - while (linkNode != null && linkNode.nodeName.toLowerCase() != 'a') - { - linkNode = linkNode.parentNode; - } - - // Ignores clicks on links and collapse/expand icon - if (linkNode == null && - (((Math.abs(this.scrollLeft - graph.container.scrollLeft) < tol && - Math.abs(this.scrollTop - graph.container.scrollTop) < tol) && - (me.sourceState == null || !me.isSource(me.sourceState.control))) && - (((mxEvent.isLeftMouseButton(evt) || mxEvent.isMiddleMouseButton(evt)) && - !mxEvent.isPopupTrigger(evt)) || mxEvent.isTouchEvent(evt)))) - { - if (this.currentLink != null) - { - var blank = graph.isBlankLink(this.currentLink); - - if ((this.currentLink.substring(0, 5) === 'data:' || - !blank) && beforeClick != null) - { - beforeClick(evt, this.currentLink); - } - - if (!mxEvent.isConsumed(evt)) - { - var target = (mxEvent.isMiddleMouseButton(evt)) ? '_blank' : - ((blank) ? graph.linkTarget : '_top'); - graph.openLink(this.currentLink, target); - me.consume(); - } - } - else if (onClick != null && !me.isConsumed() && - (Math.abs(this.scrollLeft - graph.container.scrollLeft) < tol && - Math.abs(this.scrollTop - graph.container.scrollTop) < tol) && - (Math.abs(this.startX - me.getGraphX()) < tol && - Math.abs(this.startY - me.getGraphY()) < tol)) - { - onClick(me.getEvent()); - } - } - - this.clear(); - }, - activate: function(state) - { - this.currentLink = graph.getAbsoluteUrl(graph.getLinkForCell(state.cell)); - - if (this.currentLink != null) - { - graph.container.style.cursor = 'pointer'; - - if (this.highlight != null) - { - this.highlight.highlight(state); - } - } - }, - clear: function() - { - if (graph.container != null) - { - graph.container.style.cursor = cursor; - } - - this.currentState = null; - this.currentLink = null; - - if (this.highlight != null) - { - this.highlight.hide(); - } - - if (graph.tooltipHandler != null) - { - graph.tooltipHandler.hide(); - } - } - }; - - // Ignores built-in click handling - graph.click = function(me) {}; - graph.addMouseListener(mouseListener); - - mxEvent.addListener(document, 'mouseleave', function(evt) - { - mouseListener.clear(); - }); - }; - - /** - * Duplicates the given cells and returns the duplicates. - */ - Graph.prototype.duplicateCells = function(cells, append) - { - cells = (cells != null) ? cells : this.getSelectionCells(); - append = (append != null) ? append : true; - - // Duplicates rows for table cells - for (var i = 0; i < cells.length; i++) - { - if (this.isTableCell(cells[i])) - { - cells[i] = this.model.getParent(cells[i]); - } - } - - cells = this.model.getTopmostCells(cells); - - var model = this.getModel(); - var s = this.gridSize; - var select = []; - - model.beginUpdate(); - try - { - var clones = this.cloneCells(cells, false, null, true); - - for (var i = 0; i < cells.length; i++) - { - var parent = model.getParent(cells[i]); - var child = this.moveCells([clones[i]], s, s, false)[0]; - select.push(child); - - if (append) - { - model.add(parent, clones[i]); - } - else - { - // Maintains child index by inserting after clone in parent - var index = parent.getIndex(cells[i]); - model.add(parent, clones[i], index + 1); - } - - // Extends tables - if (this.isTable(parent)) - { - var row = this.getCellGeometry(clones[i]); - var table = this.getCellGeometry(parent); - - if (row != null && table != null) - { - table = table.clone(); - table.height += row.height; - model.setGeometry(parent, table); - } - } - } - } - finally - { - model.endUpdate(); - } - - return select; - }; - - /** - * Inserts the given image at the cursor in a content editable text box using - * the insertimage command on the document instance. - */ - Graph.prototype.insertImage = function(newValue, w, h) - { - // To find the new image, we create a list of all existing links first - if (newValue != null && this.cellEditor.textarea != null) - { - var tmp = this.cellEditor.textarea.getElementsByTagName('img'); - var oldImages = []; - - for (var i = 0; i < tmp.length; i++) - { - oldImages.push(tmp[i]); - } - - // LATER: Fix inserting link/image in IE8/quirks after focus lost - document.execCommand('insertimage', false, newValue); - - // Sets size of new image - var newImages = this.cellEditor.textarea.getElementsByTagName('img'); - - if (newImages.length == oldImages.length + 1) - { - // Inverse order in favor of appended images - for (var i = newImages.length - 1; i >= 0; i--) - { - if (i == 0 || newImages[i] != oldImages[i - 1]) - { - // Workaround for lost styles during undo and redo is using attributes - newImages[i].setAttribute('width', w); - newImages[i].setAttribute('height', h); - - break; - } - } - } - } - }; - - /** - * Inserts the given image at the cursor in a content editable text box using - * the insertimage command on the document instance. - */ - Graph.prototype.insertLink = function(value) - { - if (this.cellEditor.textarea != null) - { - if (value.length == 0) - { - document.execCommand('unlink', false); - } - else if (mxClient.IS_FF) - { - // Workaround for Firefox that adds a new link and removes - // the href from the inner link if its parent is a span is - // to remove all inner links inside the new outer link - var tmp = this.cellEditor.textarea.getElementsByTagName('a'); - var oldLinks = []; - - for (var i = 0; i < tmp.length; i++) - { - oldLinks.push(tmp[i]); - } - - document.execCommand('createlink', false, mxUtils.trim(value)); - - // Finds the new link element - var newLinks = this.cellEditor.textarea.getElementsByTagName('a'); - - if (newLinks.length == oldLinks.length + 1) - { - // Inverse order in favor of appended links - for (var i = newLinks.length - 1; i >= 0; i--) - { - if (newLinks[i] != oldLinks[i - 1]) - { - // Removes all inner links from the new link and - // moves the children to the inner link parent - var tmp = newLinks[i].getElementsByTagName('a'); - - while (tmp.length > 0) - { - var parent = tmp[0].parentNode; - - while (tmp[0].firstChild != null) - { - parent.insertBefore(tmp[0].firstChild, tmp[0]); - } - - parent.removeChild(tmp[0]); - } - - break; - } - } - } - } - else - { - // LATER: Fix inserting link/image in IE8/quirks after focus lost - document.execCommand('createlink', false, mxUtils.trim(value)); - } - } - }; - - /** - * - * @param cell - * @returns {Boolean} - */ - Graph.prototype.isCellResizable = function(cell) - { - var result = mxGraph.prototype.isCellResizable.apply(this, arguments); - var style = this.getCurrentCellStyle(cell); - - return !this.isTableCell(cell) && !this.isTableRow(cell) && (result || - (mxUtils.getValue(style, mxConstants.STYLE_RESIZABLE, '1') != '0' && - style[mxConstants.STYLE_WHITE_SPACE] == 'wrap')); - }; - - /** - * Function: distributeCells - * - * Distribuets the centers of the given cells equally along the available - * horizontal or vertical space. - * - * Parameters: - * - * horizontal - Boolean that specifies the direction of the distribution. - * cells - Optional array of to be distributed. Edges are ignored. - */ - Graph.prototype.distributeCells = function(horizontal, cells) - { - if (cells == null) - { - cells = this.getSelectionCells(); - } - - if (cells != null && cells.length > 1) - { - var vertices = []; - var max = null; - var min = null; - - for (var i = 0; i < cells.length; i++) - { - if (this.getModel().isVertex(cells[i])) - { - var state = this.view.getState(cells[i]); - - if (state != null) - { - var tmp = (horizontal) ? state.getCenterX() : state.getCenterY(); - max = (max != null) ? Math.max(max, tmp) : tmp; - min = (min != null) ? Math.min(min, tmp) : tmp; - - vertices.push(state); - } - } - } - - if (vertices.length > 2) - { - vertices.sort(function(a, b) - { - return (horizontal) ? a.x - b.x : a.y - b.y; - }); - - var t = this.view.translate; - var s = this.view.scale; - - min = min / s - ((horizontal) ? t.x : t.y); - max = max / s - ((horizontal) ? t.x : t.y); - - this.getModel().beginUpdate(); - try - { - var dt = (max - min) / (vertices.length - 1); - var t0 = min; - - for (var i = 1; i < vertices.length - 1; i++) - { - var pstate = this.view.getState(this.model.getParent(vertices[i].cell)); - var geo = this.getCellGeometry(vertices[i].cell); - t0 += dt; - - if (geo != null && pstate != null) - { - geo = geo.clone(); - - if (horizontal) - { - geo.x = Math.round(t0 - geo.width / 2) - pstate.origin.x; - } - else - { - geo.y = Math.round(t0 - geo.height / 2) - pstate.origin.y; - } - - this.getModel().setGeometry(vertices[i].cell, geo); - } - } - } - finally - { - this.getModel().endUpdate(); - } - } - } - - return cells; - }; - - /** - * Adds meta-drag an Mac. - * @param evt - * @returns - */ - Graph.prototype.isCloneEvent = function(evt) - { - return (mxClient.IS_MAC && mxEvent.isMetaDown(evt)) || mxEvent.isControlDown(evt); - }; - - /** - * Translates this point by the given vector. - * - * @param {number} dx X-coordinate of the translation. - * @param {number} dy Y-coordinate of the translation. - */ - Graph.prototype.createSvgImageExport = function() - { - var exp = new mxImageExport(); - - // Adds hyperlinks (experimental) - exp.getLinkForCellState = mxUtils.bind(this, function(state, canvas) - { - return this.getLinkForCell(state.cell); - }); - - return exp; - }; - - /** - * Translates this point by the given vector. - * - * @param {number} dx X-coordinate of the translation. - * @param {number} dy Y-coordinate of the translation. - */ - Graph.prototype.getSvg = function(background, scale, border, nocrop, crisp, - ignoreSelection, showText, imgExport, linkTarget, hasShadow, incExtFonts, - keepTheme, exportType) - { - //Disable Css Transforms if it is used - var origUseCssTrans = this.useCssTransforms; - - if (origUseCssTrans) - { - this.useCssTransforms = false; - this.view.revalidate(); - this.sizeDidChange(); - } - - try - { - scale = (scale != null) ? scale : 1; - border = (border != null) ? border : 0; - crisp = (crisp != null) ? crisp : true; - ignoreSelection = (ignoreSelection != null) ? ignoreSelection : true; - showText = (showText != null) ? showText : true; - - var bounds = (exportType == 'page') ? this.view.getBackgroundPageBounds() : - ((ignoreSelection || nocrop || exportType == 'diagram') ? - this.getGraphBounds() : this.getBoundingBox( - this.getSelectionCells())); - - if (bounds == null) - { - throw Error(mxResources.get('drawingEmpty')); - } - - var vs = this.view.scale; - - // Prepares SVG document that holds the output - var svgDoc = mxUtils.createXmlDocument(); - var root = (svgDoc.createElementNS != null) ? - svgDoc.createElementNS(mxConstants.NS_SVG, 'svg') : svgDoc.createElement('svg'); - - if (background != null) - { - if (root.style != null) - { - root.style.backgroundColor = background; - } - else - { - root.setAttribute('style', 'background-color:' + background); - } - } - - if (svgDoc.createElementNS == null) - { - root.setAttribute('xmlns', mxConstants.NS_SVG); - root.setAttribute('xmlns:xlink', mxConstants.NS_XLINK); - } - else - { - // KNOWN: Ignored in IE9-11, adds namespace for each image element instead. No workaround. - root.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', mxConstants.NS_XLINK); - } - - var s = scale / vs; - var w = Math.max(1, Math.ceil(bounds.width * s) + 2 * border) + ((hasShadow) ? 5 : 0); - var h = Math.max(1, Math.ceil(bounds.height * s) + 2 * border) + ((hasShadow) ? 5 : 0); - - root.setAttribute('version', '1.1'); - root.setAttribute('width', w + 'px'); - root.setAttribute('height', h + 'px'); - root.setAttribute('viewBox', ((crisp) ? '-0.5 -0.5' : '0 0') + ' ' + w + ' ' + h); - svgDoc.appendChild(root); - - // Renders graph. Offset will be multiplied with state's scale when painting state. - // TextOffset only seems to affect FF output but used everywhere for consistency. - var group = (svgDoc.createElementNS != null) ? - svgDoc.createElementNS(mxConstants.NS_SVG, 'g') : svgDoc.createElement('g'); - root.appendChild(group); - - var svgCanvas = this.createSvgCanvas(group); - svgCanvas.foOffset = (crisp) ? -0.5 : 0; - svgCanvas.textOffset = (crisp) ? -0.5 : 0; - svgCanvas.imageOffset = (crisp) ? -0.5 : 0; - svgCanvas.translate(Math.floor((border / scale - bounds.x) / vs), - Math.floor((border / scale - bounds.y) / vs)); - - // Convert HTML entities - var htmlConverter = document.createElement('div'); - - // Adds simple text fallback for viewers with no support for foreignObjects - var getAlternateText = svgCanvas.getAlternateText; - svgCanvas.getAlternateText = function(fo, x, y, w, h, str, align, valign, wrap, format, overflow, clip, rotation) - { - // Assumes a max character width of 0.5em - if (str != null && this.state.fontSize > 0) - { - try - { - if (mxUtils.isNode(str)) - { - str = str.innerText; - } - else - { - htmlConverter.innerHTML = str; - str = mxUtils.extractTextWithWhitespace(htmlConverter.childNodes); - } - - // Workaround for substring breaking double byte UTF - var exp = Math.ceil(2 * w / this.state.fontSize); - var result = []; - var length = 0; - var index = 0; - - while ((exp == 0 || length < exp) && index < str.length) - { - var char = str.charCodeAt(index); - - if (char == 10 || char == 13) - { - if (length > 0) - { - break; - } - } - else - { - result.push(str.charAt(index)); - - if (char < 255) - { - length++; - } - } - - index++; - } - - // Uses result and adds ellipsis if more than 1 char remains - if (result.length < str.length && str.length - result.length > 1) - { - str = mxUtils.trim(result.join('')) + '...'; - } - - return str; - } - catch (e) - { - return getAlternateText.apply(this, arguments); - } - } - else - { - return getAlternateText.apply(this, arguments); - } - }; - - // Paints background image - var bgImg = this.backgroundImage; - - if (bgImg != null) - { - var s2 = vs / scale; - var tr = this.view.translate; - var tmp = new mxRectangle(tr.x * s2, tr.y * s2, bgImg.width * s2, bgImg.height * s2); - - // Checks if visible - if (mxUtils.intersects(bounds, tmp)) - { - svgCanvas.image(tr.x, tr.y, bgImg.width, bgImg.height, bgImg.src, true); - } - } - - svgCanvas.scale(s); - svgCanvas.textEnabled = showText; - - imgExport = (imgExport != null) ? imgExport : this.createSvgImageExport(); - var imgExportDrawCellState = imgExport.drawCellState; - - // Ignores custom links - var imgExportGetLinkForCellState = imgExport.getLinkForCellState; - - imgExport.getLinkForCellState = function(state, canvas) - { - var result = imgExportGetLinkForCellState.apply(this, arguments); - - return (result != null && !state.view.graph.isCustomLink(result)) ? result : null; - }; - - // Implements ignoreSelection flag - imgExport.drawCellState = function(state, canvas) - { - var graph = state.view.graph; - var selected = graph.isCellSelected(state.cell); - var parent = graph.model.getParent(state.cell); - - // Checks if parent cell is selected - while (!ignoreSelection && !selected && parent != null) - { - selected = graph.isCellSelected(parent); - parent = graph.model.getParent(parent); - } - - if (ignoreSelection || selected) - { - imgExportDrawCellState.apply(this, arguments); - } - }; - - imgExport.drawState(this.getView().getState(this.model.root), svgCanvas); - this.updateSvgLinks(root, linkTarget, true); - this.addForeignObjectWarning(svgCanvas, root); - - return root; - } - finally - { - if (origUseCssTrans) - { - this.useCssTransforms = true; - this.view.revalidate(); - this.sizeDidChange(); - } - } - }; - - /** - * Adds warning for truncated labels in older viewers. - */ - Graph.prototype.addForeignObjectWarning = function(canvas, root) - { - if (urlParams['svg-warning'] != '0' && root.getElementsByTagName('foreignObject').length > 0) - { - var sw = canvas.createElement('switch'); - var g1 = canvas.createElement('g'); - g1.setAttribute('requiredFeatures', 'http://www.w3.org/TR/SVG11/feature#Extensibility'); - var a = canvas.createElement('a'); - a.setAttribute('transform', 'translate(0,-5)'); - - // Workaround for implicit namespace handling in HTML5 export, IE adds NS1 namespace so use code below - // in all IE versions except quirks mode. KNOWN: Adds xlink namespace to each image tag in output. - if (a.setAttributeNS == null || (root.ownerDocument != document && document.documentMode == null)) - { - a.setAttribute('xlink:href', Graph.foreignObjectWarningLink); - a.setAttribute('target', '_blank'); - } - else - { - a.setAttributeNS(mxConstants.NS_XLINK, 'xlink:href', Graph.foreignObjectWarningLink); - a.setAttributeNS(mxConstants.NS_XLINK, 'target', '_blank'); - } - - var text = canvas.createElement('text'); - text.setAttribute('text-anchor', 'middle'); - text.setAttribute('font-size', '10px'); - text.setAttribute('x', '50%'); - text.setAttribute('y', '100%'); - mxUtils.write(text, Graph.foreignObjectWarningText); - - sw.appendChild(g1); - a.appendChild(text); - sw.appendChild(a); - root.appendChild(sw); - } - }; - - /** - * Hook for creating the canvas used in getSvg. - */ - Graph.prototype.updateSvgLinks = function(node, target, removeCustom) - { - var links = node.getElementsByTagName('a'); - - for (var i = 0; i < links.length; i++) - { - var href = links[i].getAttribute('href'); - - if (href == null) - { - href = links[i].getAttribute('xlink:href'); - } - - if (href != null) - { - if (target != null && /^https?:\/\//.test(href)) - { - links[i].setAttribute('target', target); - } - else if (removeCustom && this.isCustomLink(href)) - { - links[i].setAttribute('href', 'javascript:void(0);'); - } - } - } - }; - - /** - * Hook for creating the canvas used in getSvg. - */ - Graph.prototype.createSvgCanvas = function(node) - { - var canvas = new mxSvgCanvas2D(node); - - canvas.pointerEvents = true; - - return canvas; - }; - - /** - * Returns the first ancestor of the current selection with the given name. - */ - Graph.prototype.getSelectedElement = function() - { - var node = null; - - if (window.getSelection) - { - var sel = window.getSelection(); - - if (sel.getRangeAt && sel.rangeCount) - { - var range = sel.getRangeAt(0); - node = range.commonAncestorContainer; - } - } - else if (document.selection) - { - node = document.selection.createRange().parentElement(); - } - - return node; - }; - - /** - * Returns the text editing element. - */ - Graph.prototype.getSelectedEditingElement = function() - { - var node = this.getSelectedElement(); - - while (node != null && node.nodeType != mxConstants.NODETYPE_ELEMENT) - { - node = node.parentNode; - } - - if (node != null) - { - // Workaround for commonAncestor on range in IE11 returning parent of common ancestor - if (node == this.cellEditor.textarea && this.cellEditor.textarea.children.length == 1 && - this.cellEditor.textarea.firstChild.nodeType == mxConstants.NODETYPE_ELEMENT) - { - node = this.cellEditor.textarea.firstChild; - } - } - - return node; - }; - - /** - * Returns the first ancestor of the current selection with the given name. - */ - Graph.prototype.getParentByName = function(node, name, stopAt) - { - while (node != null) - { - if (node.nodeName == name) - { - return node; - } - - if (node == stopAt) - { - return null; - } - - node = node.parentNode; - } - - return node; - }; - - /** - * Returns the first ancestor of the current selection with the given name. - */ - Graph.prototype.getParentByNames = function(node, names, stopAt) - { - while (node != null) - { - if (mxUtils.indexOf(names, node.nodeName) >= 0) - { - return node; - } - - if (node == stopAt) - { - return null; - } - - node = node.parentNode; - } - - return node; - }; - - /** - * Selects the given node. - */ - Graph.prototype.selectNode = function(node) - { - var sel = null; - - // IE9 and non-IE - if (window.getSelection) - { - sel = window.getSelection(); - - if (sel.getRangeAt && sel.rangeCount) - { - var range = document.createRange(); - range.selectNode(node); - sel.removeAllRanges(); - sel.addRange(range); - } - } - // IE < 9 - else if ((sel = document.selection) && sel.type != 'Control') - { - var originalRange = sel.createRange(); - originalRange.collapse(true); - var range = sel.createRange(); - range.setEndPoint('StartToStart', originalRange); - range.select(); - } - }; - - /** - * Deletes the given cells and returns the cells to be selected. - */ - Graph.prototype.deleteCells = function(cells, includeEdges) - { - var select = null; - - if (cells != null && cells.length > 0) - { - this.model.beginUpdate(); - try - { - // Shrinks tables - for (var i = 0; i < cells.length; i++) - { - var parent = this.model.getParent(cells[i]); - - if (this.isTable(parent)) - { - var row = this.getCellGeometry(cells[i]); - var table = this.getCellGeometry(parent); - - if (row != null && table != null) - { - table = table.clone(); - table.height -= row.height; - this.model.setGeometry(parent, table); - } - } - } - - var parents = (this.selectParentAfterDelete) ? this.model.getParents(cells) : null; - this.removeCells(cells, includeEdges); - } - finally - { - this.model.endUpdate(); - } - - // Selects parents for easier editing of groups - if (parents != null) - { - select = []; - - for (var i = 0; i < parents.length; i++) - { - if (this.model.contains(parents[i]) && - (this.model.isVertex(parents[i]) || - this.model.isEdge(parents[i]))) - { - select.push(parents[i]); - } - } - } - } - - return select; - }; - - /** - * Inserts a column in the table for the given cell. - */ - Graph.prototype.insertTableColumn = function(cell, before) - { - var model = this.getModel(); - model.beginUpdate(); - - try - { - var table = cell; - var index = 0; - - if (this.isTableCell(cell)) - { - var row = model.getParent(cell); - table = model.getParent(row); - index = mxUtils.indexOf(model.getChildCells(row, true), cell); - } - else - { - if (this.isTableRow(cell)) - { - table = model.getParent(cell); - } - else - { - cell = model.getChildCells(table, true)[0]; - } - - if (!before) - { - index = model.getChildCells(cell, true).length - 1; - } - } - - var rows = model.getChildCells(table, true); - var dw = Graph.minTableColumnWidth; - - for (var i = 0; i < rows.length; i++) - { - var child = model.getChildCells(rows[i], true)[index]; - var clone = model.cloneCell(child, false); - var geo = this.getCellGeometry(clone); - clone.value = null; - - if (geo != null) - { - dw = geo.width; - var rowGeo = this.getCellGeometry(rows[i]); - - if (rowGeo != null) - { - geo.height = rowGeo.height; - } - } - - model.add(rows[i], clone, index + ((before) ? 0 : 1)); - } - - var tableGeo = this.getCellGeometry(table); - - if (tableGeo != null) - { - tableGeo = tableGeo.clone(); - tableGeo.width += dw; - - model.setGeometry(table, tableGeo); - } - } - finally - { - model.endUpdate(); - } - }; - - /** - * Inserts a row in the table for the given cell. - */ - Graph.prototype.insertTableRow = function(cell, before) - { - var model = this.getModel(); - model.beginUpdate(); - - try - { - var table = cell; - var row = cell; - - if (this.isTableCell(cell)) - { - row = model.getParent(cell); - table = model.getParent(row); - } - else if (this.isTableRow(cell)) - { - table = model.getParent(cell); - } - else - { - var rows = model.getChildCells(table, true); - row = rows[(before) ? 0 : rows.length - 1]; - } - - var cells = model.getChildCells(row, true); - var index = table.getIndex(row); - row = model.cloneCell(row, false); - row.value = null; - - var rowGeo = this.getCellGeometry(row); - - if (rowGeo != null) - { - for (var i = 0; i < cells.length; i++) - { - var cell = model.cloneCell(cells[i], false); - row.insert(cell); - cell.value = null; - - var geo = this.getCellGeometry(cell); - - if (geo != null) - { - geo.height = rowGeo.height; - } - } - - model.add(table, row, index + ((before) ? 0 : 1)); - - var tableGeo = this.getCellGeometry(table); - - if (tableGeo != null) - { - tableGeo = tableGeo.clone(); - tableGeo.height += rowGeo.height; - - model.setGeometry(table, tableGeo); - } - } - } - finally - { - model.endUpdate(); - } - }; - - /** - * - */ - Graph.prototype.deleteTableColumn = function(cell) - { - var model = this.getModel(); - model.beginUpdate(); - - try - { - var table = cell; - var row = cell; - - if (this.isTableCell(cell)) - { - row = model.getParent(cell); - } - - if (this.isTableRow(row)) - { - table = model.getParent(row); - } - - var rows = model.getChildCells(table, true); - - if (rows.length == 0) - { - model.remove(table); - } - else - { - if (!this.isTableRow(row)) - { - row = rows[0]; - } - - var cells = model.getChildCells(row, true); - - if (cells.length <= 1) - { - model.remove(table); - } - else - { - var index = cells.length - 1; - - if (this.isTableCell(cell)) - { - index = mxUtils.indexOf(cells, cell); - } - - var width = 0; - - for (var i = 0; i < rows.length; i++) - { - var child = model.getChildCells(rows[i], true)[index]; - model.remove(child); - - var geo = this.getCellGeometry(child); - - if (geo != null) - { - width = Math.max(width, geo.width); - } - } - - var tableGeo = this.getCellGeometry(table); - - if (tableGeo != null) - { - tableGeo = tableGeo.clone(); - tableGeo.width -= width; - - model.setGeometry(table, tableGeo); - } - } - } - } - finally - { - model.endUpdate(); - } - }; - - /** - * - */ - Graph.prototype.deleteTableRow = function(cell) - { - var model = this.getModel(); - model.beginUpdate(); - - try - { - var table = cell; - var row = cell; - - if (this.isTableCell(cell)) - { - row = model.getParent(cell); - cell = row; - } - - if (this.isTableRow(cell)) - { - table = model.getParent(row); - } - - var rows = model.getChildCells(table, true); - - if (rows.length <= 1) - { - model.remove(table); - } - else - { - if (!this.isTableRow(row)) - { - row = rows[rows.length - 1]; - } - - model.remove(row); - var height = 0; - - var geo = this.getCellGeometry(row); - - if (geo != null) - { - height = geo.height; - } - - var tableGeo = this.getCellGeometry(table); - - if (tableGeo != null) - { - tableGeo = tableGeo.clone(); - tableGeo.height -= height; - - model.setGeometry(table, tableGeo); - } - } - } - finally - { - model.endUpdate(); - } - }; - - /** - * Inserts a new row into the given table. - */ - Graph.prototype.insertRow = function(table, index) - { - var bd = table.tBodies[0]; - var cells = bd.rows[0].cells; - var cols = 0; - - // Counts columns including colspans - for (var i = 0; i < cells.length; i++) - { - var colspan = cells[i].getAttribute('colspan'); - cols += (colspan != null) ? parseInt(colspan) : 1; - } - - var row = bd.insertRow(index); - - for (var i = 0; i < cols; i++) - { - mxUtils.br(row.insertCell(-1)); - } - - return row.cells[0]; - }; - - /** - * Deletes the given column. - */ - Graph.prototype.deleteRow = function(table, index) - { - table.tBodies[0].deleteRow(index); - }; - - /** - * Deletes the given column. - */ - Graph.prototype.insertColumn = function(table, index) - { - var hd = table.tHead; - - if (hd != null) - { - // TODO: use colIndex - for (var h = 0; h < hd.rows.length; h++) - { - var th = document.createElement('th'); - hd.rows[h].appendChild(th); - mxUtils.br(th); - } - } - - var bd = table.tBodies[0]; - - for (var i = 0; i < bd.rows.length; i++) - { - var cell = bd.rows[i].insertCell(index); - mxUtils.br(cell); - } - - return bd.rows[0].cells[(index >= 0) ? index : bd.rows[0].cells.length - 1]; - }; - - /** - * Deletes the given column. - */ - Graph.prototype.deleteColumn = function(table, index) - { - if (index >= 0) - { - var bd = table.tBodies[0]; - var rows = bd.rows; - - for (var i = 0; i < rows.length; i++) - { - if (rows[i].cells.length > index) - { - rows[i].deleteCell(index); - } - } - } - }; - - /** - * Inserts the given HTML at the caret position (no undo). - */ - Graph.prototype.pasteHtmlAtCaret = function(html) - { - var sel, range; - - // IE9 and non-IE - if (window.getSelection) - { - sel = window.getSelection(); - - if (sel.getRangeAt && sel.rangeCount) - { - range = sel.getRangeAt(0); - range.deleteContents(); - - // Range.createContextualFragment() would be useful here but is - // only relatively recently standardized and is not supported in - // some browsers (IE9, for one) - var el = document.createElement("div"); - el.innerHTML = html; - var frag = document.createDocumentFragment(), node; - - while ((node = el.firstChild)) - { - lastNode = frag.appendChild(node); - } - - range.insertNode(frag); - } - } - // IE < 9 - else if ((sel = document.selection) && sel.type != "Control") - { - // FIXME: Does not work if selection is empty - sel.createRange().pasteHTML(html); - } - }; - - /** - * Creates an anchor elements for handling the given link in the - * hint that is shown when the cell is selected. - */ - Graph.prototype.createLinkForHint = function(link, label) - { - link = (link != null) ? link : 'javascript:void(0);'; - - if (label == null || label.length == 0) - { - if (this.isCustomLink(link)) - { - label = this.getLinkTitle(link); - } - else - { - label = link; - } - } - - // Helper function to shorten strings - function short(str, max) - { - if (str.length > max) - { - str = str.substring(0, Math.round(max / 2)) + '...' + - str.substring(str.length - Math.round(max / 4)); - } - - return str; - }; - - var a = document.createElement('a'); - a.setAttribute('rel', this.linkRelation); - a.setAttribute('href', this.getAbsoluteUrl(link)); - a.setAttribute('title', short((this.isCustomLink(link)) ? - this.getLinkTitle(link) : link, 80)); - - if (this.linkTarget != null) - { - a.setAttribute('target', this.linkTarget); - } - - // Adds shortened label to link - mxUtils.write(a, short(label, 40)); - - // Handles custom links - if (this.isCustomLink(link)) - { - mxEvent.addListener(a, 'click', mxUtils.bind(this, function(evt) - { - this.customLinkClicked(link); - mxEvent.consume(evt); - })); - } - - return a; - }; - - /** - * Customized graph for touch devices. - */ - Graph.prototype.initTouch = function() - { - // Disables new connections via "hotspot" - this.connectionHandler.marker.isEnabled = function() - { - return this.graph.connectionHandler.first != null; - }; - - // Hides menu when editing starts - this.addListener(mxEvent.START_EDITING, function(sender, evt) - { - this.popupMenuHandler.hideMenu(); - }); - - // Adds custom hit detection if native hit detection found no cell - var graphUpdateMouseEvent = this.updateMouseEvent; - this.updateMouseEvent = function(me) - { - me = graphUpdateMouseEvent.apply(this, arguments); - - if (mxEvent.isTouchEvent(me.getEvent()) && me.getState() == null) - { - var cell = this.getCellAt(me.graphX, me.graphY); - - if (cell != null && this.isSwimlane(cell) && this.hitsSwimlaneContent(cell, me.graphX, me.graphY)) - { - cell = null; - } - else - { - me.state = this.view.getState(cell); - - if (me.state != null && me.state.shape != null) - { - this.container.style.cursor = me.state.shape.node.style.cursor; - } - } - } - - if (me.getState() == null && this.isEnabled()) - { - this.container.style.cursor = 'default'; - } - - return me; - }; - - // Context menu trigger implementation depending on current selection state - // combined with support for normal popup trigger. - var cellSelected = false; - var selectionEmpty = false; - var menuShowing = false; - - var oldFireMouseEvent = this.fireMouseEvent; - - this.fireMouseEvent = function(evtName, me, sender) - { - if (evtName == mxEvent.MOUSE_DOWN) - { - // For hit detection on edges - me = this.updateMouseEvent(me); - - cellSelected = this.isCellSelected(me.getCell()); - selectionEmpty = this.isSelectionEmpty(); - menuShowing = this.popupMenuHandler.isMenuShowing(); - } - - oldFireMouseEvent.apply(this, arguments); - }; - - // Shows popup menu if cell was selected or selection was empty and background was clicked - // FIXME: Conflicts with mxPopupMenuHandler.prototype.getCellForPopupEvent in Editor.js by - // selecting parent for selected children in groups before this check can be made. - this.popupMenuHandler.mouseUp = mxUtils.bind(this, function(sender, me) - { - this.popupMenuHandler.popupTrigger = !this.isEditing() && this.isEnabled() && - (me.getState() == null || !me.isSource(me.getState().control)) && - (this.popupMenuHandler.popupTrigger || (!menuShowing && !mxEvent.isMouseEvent(me.getEvent()) && - ((selectionEmpty && me.getCell() == null && this.isSelectionEmpty()) || - (cellSelected && this.isCellSelected(me.getCell()))))); - mxPopupMenuHandler.prototype.mouseUp.apply(this.popupMenuHandler, arguments); - }); - }; - - /** - * HTML in-place editor - */ - mxCellEditor.prototype.isContentEditing = function() - { - var state = this.graph.view.getState(this.editingCell); - - return state != null && state.style['html'] == 1; - }; - - /** - * Returns true if all selected text is inside a table element. - */ - mxCellEditor.prototype.isTableSelected = function() - { - return this.graph.getParentByName( - this.graph.getSelectedElement(), - 'TABLE', this.textarea) != null; - }; - - /** - * Sets the alignment of the current selected cell. This sets the - * alignment in the cell style, removes all alignment within the - * text and invokes the built-in alignment function. - * - * Only the built-in function is invoked if shift is pressed or - * if table cells are selected and shift is not pressed. - */ - mxCellEditor.prototype.alignText = function(align, evt) - { - var shiftPressed = evt != null && mxEvent.isShiftDown(evt); - - if (shiftPressed || (window.getSelection != null && window.getSelection().containsNode != null)) - { - var allSelected = true; - - this.graph.processElements(this.textarea, function(node) - { - if (shiftPressed || window.getSelection().containsNode(node, true)) - { - node.removeAttribute('align'); - node.style.textAlign = null; - } - else - { - allSelected = false; - } - }); - - if (allSelected) - { - this.graph.cellEditor.setAlign(align); - } - } - - document.execCommand('justify' + align.toLowerCase(), false, null); - }; - - /** - * Creates the keyboard event handler for the current graph and history. - */ - mxCellEditor.prototype.saveSelection = function() - { - if (window.getSelection) - { - var sel = window.getSelection(); - - if (sel.getRangeAt && sel.rangeCount) - { - var ranges = []; - - for (var i = 0, len = sel.rangeCount; i < len; ++i) - { - ranges.push(sel.getRangeAt(i)); - } - - return ranges; - } - } - else if (document.selection && document.selection.createRange) - { - return document.selection.createRange(); - } - - return null; - }; - - /** - * Creates the keyboard event handler for the current graph and history. - */ - mxCellEditor.prototype.restoreSelection = function(savedSel) - { - try - { - if (savedSel) - { - if (window.getSelection) - { - sel = window.getSelection(); - sel.removeAllRanges(); - - for (var i = 0, len = savedSel.length; i < len; ++i) - { - sel.addRange(savedSel[i]); - } - } - else if (document.selection && savedSel.select) - { - savedSel.select(); - } - } - } - catch (e) - { - // ignore - } - }; - - /** - * Handling of special nl2Br style for not converting newlines to breaks in HTML labels. - * NOTE: Since it's easier to set this when the label is created we assume that it does - * not change during the lifetime of the mxText instance. - */ - var mxCellRendererInitializeLabel = mxCellRenderer.prototype.initializeLabel; - mxCellRenderer.prototype.initializeLabel = function(state) - { - if (state.text != null) - { - state.text.replaceLinefeeds = mxUtils.getValue(state.style, 'nl2Br', '1') != '0'; - } - - mxCellRendererInitializeLabel.apply(this, arguments); - }; - - var mxConstraintHandlerUpdate = mxConstraintHandler.prototype.update; - mxConstraintHandler.prototype.update = function(me, source) - { - if (this.isKeepFocusEvent(me) || !mxEvent.isAltDown(me.getEvent())) - { - mxConstraintHandlerUpdate.apply(this, arguments); - } - else - { - this.reset(); - } - }; - - /** - * No dashed shapes. - */ - mxGuide.prototype.createGuideShape = function(horizontal) - { - var guide = new mxPolyline([], mxConstants.GUIDE_COLOR, mxConstants.GUIDE_STROKEWIDTH); - - return guide; - }; - - /** - * HTML in-place editor - */ - mxCellEditor.prototype.escapeCancelsEditing = false; - - /** - * Overridden to set CSS classes. - */ - var mxCellEditorStartEditing = mxCellEditor.prototype.startEditing; - mxCellEditor.prototype.startEditing = function(cell, trigger) - { - cell = this.graph.getStartEditingCell(cell, trigger); - - mxCellEditorStartEditing.apply(this, arguments); - - // Overrides class in case of HTML content to add - // dashed borders for divs and table cells - var state = this.graph.view.getState(cell); - - if (state != null && state.style['html'] == 1) - { - this.textarea.className = 'mxCellEditor geContentEditable'; - } - else - { - this.textarea.className = 'mxCellEditor mxPlainTextEditor'; - } - - // Toggles markup vs wysiwyg mode - this.codeViewMode = false; - - // Stores current selection range when switching between markup and code - this.switchSelectionState = null; - - // Selects editing cell - this.graph.setSelectionCell(cell); - - // Enables focus outline for edges and edge labels - var parent = this.graph.getModel().getParent(cell); - var geo = this.graph.getCellGeometry(cell); - - if ((this.graph.getModel().isEdge(parent) && geo != null && geo.relative) || - this.graph.getModel().isEdge(cell)) - { - // Quirks does not support outline at all so use border instead - if (mxClient.IS_QUIRKS) - { - this.textarea.style.border = 'gray dotted 1px'; - } - // IE>8 and FF on Windows uses outline default of none - else if (mxClient.IS_IE || mxClient.IS_IE11 || (mxClient.IS_FF && mxClient.IS_WIN)) - { - this.textarea.style.outline = 'gray dotted 1px'; - } - else - { - this.textarea.style.outline = ''; - } - } - else if (mxClient.IS_QUIRKS) - { - this.textarea.style.outline = 'none'; - this.textarea.style.border = ''; - } - } - - /** - * HTML in-place editor - */ - var cellEditorInstallListeners = mxCellEditor.prototype.installListeners; - mxCellEditor.prototype.installListeners = function(elt) - { - cellEditorInstallListeners.apply(this, arguments); - - // Adds a reference from the clone to the original node, recursively - function reference(node, clone) - { - clone.originalNode = node; - - node = node.firstChild; - var child = clone.firstChild; - - while (node != null && child != null) - { - reference(node, child); - node = node.nextSibling; - child = child.nextSibling; - } - - return clone; - }; - - // Checks the given node for new nodes, recursively - function checkNode(node, clone) - { - if (node != null) - { - if (clone.originalNode != node) - { - cleanNode(node); - } - else - { - node = node.firstChild; - clone = clone.firstChild; - - while (node != null) - { - var nextNode = node.nextSibling; - - if (clone == null) - { - cleanNode(node); - } - else - { - checkNode(node, clone); - clone = clone.nextSibling; - } - - node = nextNode; - } - } - } - }; - - // Removes unused DOM nodes and attributes, recursively - function cleanNode(node) - { - var child = node.firstChild; - - while (child != null) - { - var next = child.nextSibling; - cleanNode(child); - child = next; - } - - if ((node.nodeType != 1 || (node.nodeName !== 'BR' && node.firstChild == null)) && - (node.nodeType != 3 || mxUtils.trim(mxUtils.getTextContent(node)).length == 0)) - { - node.parentNode.removeChild(node); - } - else - { - // Removes linefeeds - if (node.nodeType == 3) - { - mxUtils.setTextContent(node, mxUtils.getTextContent(node).replace(/\n|\r/g, '')); - } - - // Removes CSS classes and styles (for Word and Excel) - if (node.nodeType == 1) - { - node.removeAttribute('style'); - node.removeAttribute('class'); - node.removeAttribute('width'); - node.removeAttribute('cellpadding'); - node.removeAttribute('cellspacing'); - node.removeAttribute('border'); - } - } - }; - - // Handles paste from Word, Excel etc by removing styles, classnames and unused nodes - // LATER: Fix undo/redo for paste - if (!mxClient.IS_QUIRKS && document.documentMode !== 7 && document.documentMode !== 8) - { - mxEvent.addListener(this.textarea, 'paste', mxUtils.bind(this, function(evt) - { - var clone = reference(this.textarea, this.textarea.cloneNode(true)); - - window.setTimeout(mxUtils.bind(this, function() - { - if (this.textarea != null) - { - // Paste from Word or Excel - if (this.textarea.innerHTML.indexOf('') >= 0 || - this.textarea.innerHTML.indexOf('