From 51f6b3e00872863945e6b75b86293f9903379534 Mon Sep 17 00:00:00 2001 From: Nate Mielnik Date: Fri, 5 Jun 2015 09:51:13 -0400 Subject: [PATCH] 5.0.0-alpha.0 --- bower.json | 2 +- dist/css/medium-editor.css | 263 ++-- dist/css/medium-editor.min.css | 2 +- dist/css/themes/bootstrap.css | 34 +- dist/css/themes/bootstrap.min.css | 2 +- dist/css/themes/default.css | 46 +- dist/css/themes/default.min.css | 2 +- dist/js/medium-editor.js | 2062 +++++++++-------------------- dist/js/medium-editor.min.js | 8 +- package.json | 2 +- src/js/version.js | 2 +- 11 files changed, 815 insertions(+), 1610 deletions(-) diff --git a/bower.json b/bower.json index c841eed5a..197613d05 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "medium-editor", - "version": "4.12.0", + "version": "5.0.0-alpha.0", "homepage": "http://yabwe.github.io/medium-editor/", "authors": [ "Davi Ferreira ", diff --git a/dist/css/medium-editor.css b/dist/css/medium-editor.css index 9c8a19bfe..037068333 100644 --- a/dist/css/medium-editor.css +++ b/dist/css/medium-editor.css @@ -1,140 +1,158 @@ -.clearfix:after { - display: block; - visibility: hidden; - clear: both; - height: 0; - content: " "; - font-size: 0; } +@-webkit-keyframes medium-editor-image-loading { + 0% { + -webkit-transform: scale(0); + transform: scale(0); } + 100% { + -webkit-transform: scale(1); + transform: scale(1); } } + +@keyframes medium-editor-image-loading { + 0% { + -webkit-transform: scale(0); + transform: scale(0); } + 100% { + -webkit-transform: scale(1); + transform: scale(1); } } -@-webkit-keyframes pop-upwards { +@-webkit-keyframes medium-editor-pop-upwards { 0% { + opacity: 0; -webkit-transform: matrix(0.97, 0, 0, 1, 0, 12); - transform: matrix(0.97, 0, 0, 1, 0, 12); - opacity: 0; } + transform: matrix(0.97, 0, 0, 1, 0, 12); } 20% { + opacity: .7; -webkit-transform: matrix(0.99, 0, 0, 1, 0, 2); - transform: matrix(0.99, 0, 0, 1, 0, 2); - opacity: .7; } + transform: matrix(0.99, 0, 0, 1, 0, 2); } 40% { + opacity: 1; -webkit-transform: matrix(1, 0, 0, 1, 0, -1); - transform: matrix(1, 0, 0, 1, 0, -1); - opacity: 1; } - 70% { - -webkit-transform: matrix(1, 0, 0, 1, 0, 0); - transform: matrix(1, 0, 0, 1, 0, 0); - opacity: 1; } + transform: matrix(1, 0, 0, 1, 0, -1); } 100% { -webkit-transform: matrix(1, 0, 0, 1, 0, 0); - transform: matrix(1, 0, 0, 1, 0, 0); - opacity: 1; } } + transform: matrix(1, 0, 0, 1, 0, 0); } } -@keyframes pop-upwards { +@keyframes medium-editor-pop-upwards { 0% { + opacity: 0; -webkit-transform: matrix(0.97, 0, 0, 1, 0, 12); - transform: matrix(0.97, 0, 0, 1, 0, 12); - opacity: 0; } + transform: matrix(0.97, 0, 0, 1, 0, 12); } 20% { + opacity: .7; -webkit-transform: matrix(0.99, 0, 0, 1, 0, 2); - transform: matrix(0.99, 0, 0, 1, 0, 2); - opacity: .7; } + transform: matrix(0.99, 0, 0, 1, 0, 2); } 40% { + opacity: 1; -webkit-transform: matrix(1, 0, 0, 1, 0, -1); - transform: matrix(1, 0, 0, 1, 0, -1); - opacity: 1; } - 70% { - -webkit-transform: matrix(1, 0, 0, 1, 0, 0); - transform: matrix(1, 0, 0, 1, 0, 0); - opacity: 1; } + transform: matrix(1, 0, 0, 1, 0, -1); } 100% { -webkit-transform: matrix(1, 0, 0, 1, 0, 0); - transform: matrix(1, 0, 0, 1, 0, 0); - opacity: 1; } } + transform: matrix(1, 0, 0, 1, 0, 0); } } -.data-medium-element sup { - vertical-align: super; } +.medium-editor-anchor-preview { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 16px; + left: 0; + line-height: 1.4; + max-width: 280px; + position: absolute; + text-align: center; + top: 0; + word-break: break-all; + word-wrap: break-word; + visibility: hidden; + z-index: 2000; } + .medium-editor-anchor-preview a { + color: #fff; + display: inline-block; + margin: 5px 5px 10px; } -.data-medium-element sub { - vertical-align: sub; } +.medium-editor-anchor-preview-active { + visibility: visible; } -.data-medium-element img { - max-width: 100%; } +.medium-editor-dragover { + background: #ddd; } -.medium-editor-hidden { - display: none; } +.medium-editor-image-loading { + -webkit-animation: medium-editor-image-loading 1s infinite ease-in-out; + animation: medium-editor-image-loading 1s infinite ease-in-out; + background-color: #333; + border-radius: 100%; + display: inline-block; + height: 40px; + width: 40px; } + +.medium-editor-placeholder { + position: relative; } + .medium-editor-placeholder:after { + content: attr(data-placeholder) !important; + font-style: italic; + left: 0; + position: absolute; + top: 0; + white-space: pre; } .medium-toolbar-arrow-under:after, .medium-toolbar-arrow-over:before { - position: absolute; - left: 50%; + border-style: solid; + content: ''; display: block; - margin-left: -8px; - width: 0; height: 0; - border-style: solid; - content: ""; } + left: 50%; + margin-left: -8px; + position: absolute; + width: 0; } .medium-toolbar-arrow-under:after { border-width: 8px 8px 0 8px; } .medium-toolbar-arrow-over:before { - top: -8px; - border-width: 0 8px 8px 8px; } + border-width: 0 8px 8px 8px; + top: -8px; } -.medium-editor-toolbar, .medium-editor-anchor-preview { +.medium-editor-toolbar { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 16px; + left: 0; position: absolute; top: 0; - left: 0; - z-index: 2000; visibility: hidden; - font-size: 16px; - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; } - .medium-editor-toolbar ul, .medium-editor-anchor-preview ul { + z-index: 2000; } + .medium-editor-toolbar ul { margin: 0; padding: 0; } - .medium-editor-toolbar li, .medium-editor-anchor-preview li { + .medium-editor-toolbar li { float: left; + list-style: none; margin: 0; - padding: 0; - list-style: none; } - .medium-editor-toolbar li button, .medium-editor-anchor-preview li button { - display: block; - margin: 0; - padding: 15px; + padding: 0; } + .medium-editor-toolbar li button { + box-sizing: border-box; cursor: pointer; + display: block; font-size: 14px; line-height: 1.33; - text-decoration: none; - box-sizing: border-box; } - .medium-editor-toolbar li button:focus, .medium-editor-anchor-preview li button:focus { + margin: 0; + padding: 15px; + text-decoration: none; } + .medium-editor-toolbar li button:focus { outline: none; } - .medium-editor-toolbar li .medium-editor-action-underline, .medium-editor-anchor-preview li .medium-editor-action-underline { + .medium-editor-toolbar li .medium-editor-action-underline { text-decoration: underline; } - .medium-editor-toolbar li .medium-editor-action-pre, .medium-editor-anchor-preview li .medium-editor-action-pre { - padding: 15px 0; - font-weight: 100; + .medium-editor-toolbar li .medium-editor-action-pre { + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 12px; - font-family: 'Menlo', monospace; } - -.medium-editor-anchor-preview { - max-width: 280px; - word-break: break-all; - word-wrap: break-word; - text-align: center; - line-height: 1.4; } - .medium-editor-anchor-preview a { - display: inline-block; - margin: 5px 5px 5px 10px; - color: #fff; } + font-weight: 100; + padding: 15px 0; } -.medium-editor-toolbar-active, .medium-editor-anchor-preview-active { +.medium-editor-toolbar-active { visibility: visible; } -.sticky-toolbar { +.medium-editor-sticky-toolbar { position: fixed; top: 1px; } -.medium-editor-toolbar-active.stalker-toolbar { - -webkit-animation: pop-upwards 160ms forwards linear; - animation: pop-upwards 160ms forwards linear; } +.medium-editor-toolbar-active.medium-editor-stalker-toolbar { + -webkit-animation: medium-editor-pop-upwards 160ms forwards linear; + animation: medium-editor-pop-upwards 160ms forwards linear; } .medium-editor-action-bold { font-weight: bolder; } @@ -146,64 +164,43 @@ display: none; } .medium-editor-toolbar-form input, .medium-editor-toolbar-form a { - font-family: HelveticaNeue, Helvetica, Arial, sans-serif; } - .medium-editor-toolbar-form .medium-editor-toolbar-input, .medium-editor-toolbar-form label { - margin: 0; - padding: 6px; - width: 316px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } + .medium-editor-toolbar-form .medium-editor-toolbar-input, + .medium-editor-toolbar-form label { border: none; + box-sizing: border-box; font-size: 14px; - box-sizing: border-box; } - .medium-editor-toolbar-form .medium-editor-toolbar-input:focus, .medium-editor-toolbar-form label:focus { - outline: 0; + margin: 0; + padding: 6px; + width: 316px; } + .medium-editor-toolbar-form .medium-editor-toolbar-input:focus, + .medium-editor-toolbar-form label:focus { + appearance: none; border: none; box-shadow: none; - appearance: none; } + outline: 0; } .medium-editor-toolbar-form label { display: block; } .medium-editor-toolbar-form a { display: inline-block; - margin: 0 10px; - text-decoration: none; + font-size: 24px; font-weight: bolder; - font-size: 24px; } + margin: 0 10px; + text-decoration: none; } -.medium-editor-placeholder { - position: relative; } - .medium-editor-placeholder:after { - position: absolute; - top: 0; - left: 0; - content: attr(data-placeholder) !important; - font-style: italic; - white-space: pre; } +.medium-editor-toolbar-actions:after { + clear: both; + content: ""; + display: table; } -.medium-editor-dragover { - background: #ddd; } +[data-medium-editor-element] img { + max-width: 100%; } -.medium-image-loading { - width: 40px; - height: 40px; - background-color: #333; - display: inline-block; - border-radius: 100%; - -webkit-animation: medium-image-loading-animation 1s infinite ease-in-out; - animation: medium-image-loading-animation 1s infinite ease-in-out; } +[data-medium-editor-element] sub { + vertical-align: sub; } -@-webkit-keyframes medium-image-loading-animation { - 0% { - -webkit-transform: scale(0); - transform: scale(0); } - 100% { - -webkit-transform: scale(1); - transform: scale(1); - opacity: 0; } } +[data-medium-editor-element] sup { + vertical-align: super; } -@keyframes medium-image-loading-animation { - 0% { - -webkit-transform: scale(0); - transform: scale(0); } - 100% { - -webkit-transform: scale(1); - transform: scale(1); - opacity: 0; } } +.medium-editor-hidden { + display: none; } diff --git a/dist/css/medium-editor.min.css b/dist/css/medium-editor.min.css index 935717caa..40b90b634 100644 --- a/dist/css/medium-editor.min.css +++ b/dist/css/medium-editor.min.css @@ -1 +1 @@ -.clearfix:after{display:block;visibility:hidden;clear:both;height:0;content:" ";font-size:0}@-webkit-keyframes pop-upwards{0%{-webkit-transform:matrix(.97,0,0,1,0,12);transform:matrix(.97,0,0,1,0,12);opacity:0}20%{-webkit-transform:matrix(.99,0,0,1,0,2);transform:matrix(.99,0,0,1,0,2);opacity:.7}40%{-webkit-transform:matrix(1,0,0,1,0,-1);transform:matrix(1,0,0,1,0,-1);opacity:1}100%,70%{-webkit-transform:matrix(1,0,0,1,0,0);transform:matrix(1,0,0,1,0,0);opacity:1}}@keyframes pop-upwards{0%{-webkit-transform:matrix(.97,0,0,1,0,12);transform:matrix(.97,0,0,1,0,12);opacity:0}20%{-webkit-transform:matrix(.99,0,0,1,0,2);transform:matrix(.99,0,0,1,0,2);opacity:.7}40%{-webkit-transform:matrix(1,0,0,1,0,-1);transform:matrix(1,0,0,1,0,-1);opacity:1}100%,70%{-webkit-transform:matrix(1,0,0,1,0,0);transform:matrix(1,0,0,1,0,0);opacity:1}}.data-medium-element sup{vertical-align:super}.data-medium-element sub{vertical-align:sub}.data-medium-element img{max-width:100%}.medium-editor-hidden{display:none}.medium-toolbar-arrow-over:before,.medium-toolbar-arrow-under:after{position:absolute;left:50%;display:block;margin-left:-8px;width:0;height:0;border-style:solid;content:""}.medium-toolbar-arrow-under:after{border-width:8px 8px 0}.medium-toolbar-arrow-over:before{top:-8px;border-width:0 8px 8px}.medium-editor-anchor-preview,.medium-editor-toolbar{position:absolute;top:0;left:0;z-index:2000;visibility:hidden;font-size:16px;font-family:HelveticaNeue,Helvetica,Arial,sans-serif}.medium-editor-anchor-preview ul,.medium-editor-toolbar ul{margin:0;padding:0}.medium-editor-anchor-preview li,.medium-editor-toolbar li{float:left;margin:0;padding:0;list-style:none}.medium-editor-anchor-preview li button,.medium-editor-toolbar li button{display:block;margin:0;padding:15px;cursor:pointer;font-size:14px;line-height:1.33;text-decoration:none;box-sizing:border-box}.medium-editor-anchor-preview li button:focus,.medium-editor-toolbar li button:focus{outline:0}.medium-editor-anchor-preview li .medium-editor-action-underline,.medium-editor-toolbar li .medium-editor-action-underline{text-decoration:underline}.medium-editor-anchor-preview li .medium-editor-action-pre,.medium-editor-toolbar li .medium-editor-action-pre{padding:15px 0;font-weight:100;font-size:12px;font-family:Menlo,monospace}.medium-editor-anchor-preview{max-width:280px;word-break:break-all;word-wrap:break-word;text-align:center;line-height:1.4}.medium-editor-anchor-preview a{display:inline-block;margin:5px 5px 5px 10px;color:#fff}.medium-editor-anchor-preview-active,.medium-editor-toolbar-active{visibility:visible}.sticky-toolbar{position:fixed;top:1px}.medium-editor-toolbar-active.stalker-toolbar{-webkit-animation:pop-upwards 160ms forwards linear;animation:pop-upwards 160ms forwards linear}.medium-editor-action-bold{font-weight:bolder}.medium-editor-action-italic{font-style:italic}.medium-editor-toolbar-form{display:none}.medium-editor-toolbar-form a,.medium-editor-toolbar-form input{font-family:HelveticaNeue,Helvetica,Arial,sans-serif}.medium-editor-toolbar-form .medium-editor-toolbar-input,.medium-editor-toolbar-form label{margin:0;padding:6px;width:316px;border:none;font-size:14px;box-sizing:border-box}.medium-editor-toolbar-form .medium-editor-toolbar-input:focus,.medium-editor-toolbar-form label:focus{outline:0;border:none;box-shadow:none;appearance:none}.medium-editor-toolbar-form label{display:block}.medium-editor-toolbar-form a{display:inline-block;margin:0 10px;text-decoration:none;font-weight:bolder;font-size:24px}.medium-editor-placeholder{position:relative}.medium-editor-placeholder:after{position:absolute;top:0;left:0;content:attr(data-placeholder)!important;font-style:italic;white-space:pre}.medium-editor-dragover{background:#ddd}.medium-image-loading{width:40px;height:40px;background-color:#333;display:inline-block;border-radius:100%;-webkit-animation:medium-image-loading-animation 1s infinite ease-in-out;animation:medium-image-loading-animation 1s infinite ease-in-out}@-webkit-keyframes medium-image-loading-animation{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1);opacity:0}}@keyframes medium-image-loading-animation{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1);opacity:0}} \ No newline at end of file +.medium-editor-anchor-preview,.medium-editor-toolbar{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:16px;z-index:2000}@-webkit-keyframes medium-editor-image-loading{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes medium-editor-image-loading{0%{-webkit-transform:scale(0);transform:scale(0)}100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes medium-editor-pop-upwards{0%{opacity:0;-webkit-transform:matrix(.97,0,0,1,0,12);transform:matrix(.97,0,0,1,0,12)}20%{opacity:.7;-webkit-transform:matrix(.99,0,0,1,0,2);transform:matrix(.99,0,0,1,0,2)}40%{opacity:1;-webkit-transform:matrix(1,0,0,1,0,-1);transform:matrix(1,0,0,1,0,-1)}100%{-webkit-transform:matrix(1,0,0,1,0,0);transform:matrix(1,0,0,1,0,0)}}@keyframes medium-editor-pop-upwards{0%{opacity:0;-webkit-transform:matrix(.97,0,0,1,0,12);transform:matrix(.97,0,0,1,0,12)}20%{opacity:.7;-webkit-transform:matrix(.99,0,0,1,0,2);transform:matrix(.99,0,0,1,0,2)}40%{opacity:1;-webkit-transform:matrix(1,0,0,1,0,-1);transform:matrix(1,0,0,1,0,-1)}100%{-webkit-transform:matrix(1,0,0,1,0,0);transform:matrix(1,0,0,1,0,0)}}.medium-editor-anchor-preview{left:0;line-height:1.4;max-width:280px;position:absolute;text-align:center;top:0;word-break:break-all;word-wrap:break-word;visibility:hidden}.medium-editor-anchor-preview a{color:#fff;display:inline-block;margin:5px 5px 10px}.medium-editor-anchor-preview-active{visibility:visible}.medium-editor-dragover{background:#ddd}.medium-editor-image-loading{-webkit-animation:medium-editor-image-loading 1s infinite ease-in-out;animation:medium-editor-image-loading 1s infinite ease-in-out;background-color:#333;border-radius:100%;display:inline-block;height:40px;width:40px}.medium-editor-placeholder{position:relative}.medium-editor-placeholder:after{content:attr(data-placeholder)!important;font-style:italic;left:0;position:absolute;top:0;white-space:pre}.medium-toolbar-arrow-over:before,.medium-toolbar-arrow-under:after{border-style:solid;content:'';display:block;height:0;left:50%;margin-left:-8px;position:absolute;width:0}.medium-toolbar-arrow-under:after{border-width:8px 8px 0}.medium-toolbar-arrow-over:before{border-width:0 8px 8px;top:-8px}.medium-editor-toolbar{left:0;position:absolute;top:0;visibility:hidden}.medium-editor-toolbar ul{margin:0;padding:0}.medium-editor-toolbar li{float:left;list-style:none;margin:0;padding:0}.medium-editor-toolbar li button{box-sizing:border-box;cursor:pointer;display:block;font-size:14px;line-height:1.33;margin:0;padding:15px;text-decoration:none}.medium-editor-toolbar li button:focus{outline:0}.medium-editor-toolbar li .medium-editor-action-underline{text-decoration:underline}.medium-editor-toolbar li .medium-editor-action-pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px;font-weight:100;padding:15px 0}.medium-editor-toolbar-active{visibility:visible}.medium-editor-sticky-toolbar{position:fixed;top:1px}.medium-editor-toolbar-active.medium-editor-stalker-toolbar{-webkit-animation:medium-editor-pop-upwards 160ms forwards linear;animation:medium-editor-pop-upwards 160ms forwards linear}.medium-editor-action-bold{font-weight:bolder}.medium-editor-action-italic{font-style:italic}.medium-editor-toolbar-form{display:none}.medium-editor-toolbar-form a,.medium-editor-toolbar-form input{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.medium-editor-toolbar-form .medium-editor-toolbar-input,.medium-editor-toolbar-form label{border:none;box-sizing:border-box;font-size:14px;margin:0;padding:6px;width:316px}.medium-editor-toolbar-form .medium-editor-toolbar-input:focus,.medium-editor-toolbar-form label:focus{appearance:none;border:none;box-shadow:none;outline:0}.medium-editor-toolbar-form label{display:block}.medium-editor-toolbar-form a{display:inline-block;font-size:24px;font-weight:bolder;margin:0 10px;text-decoration:none}.medium-editor-toolbar-actions:after{clear:both;content:"";display:table}[data-medium-editor-element] img{max-width:100%}[data-medium-editor-element] sub{vertical-align:sub}[data-medium-editor-element] sup{vertical-align:super}.medium-editor-hidden{display:none} \ No newline at end of file diff --git a/dist/css/themes/bootstrap.css b/dist/css/themes/bootstrap.css index f4ec973f3..ca4931951 100644 --- a/dist/css/themes/bootstrap.css +++ b/dist/css/themes/bootstrap.css @@ -1,46 +1,46 @@ .medium-toolbar-arrow-under:after { - top: 60px; - border-color: #428bca transparent transparent transparent; } + border-color: #428bca transparent transparent transparent; + top: 60px; } .medium-toolbar-arrow-over:before { border-color: transparent transparent #428bca transparent; } .medium-editor-toolbar { - border: 1px solid #357ebd; background-color: #428bca; + border: 1px solid #357ebd; border-radius: 4px; } .medium-editor-toolbar li button { - min-width: 60px; - height: 60px; + background-color: transparent; border: none; border-right: 1px solid #357ebd; - background-color: transparent; - color: #fff; box-sizing: border-box; + color: #fff; + height: 60px; + min-width: 60px; -webkit-transition: background-color 0.2s ease-in, color 0.2s ease-in; transition: background-color 0.2s ease-in, color 0.2s ease-in; } .medium-editor-toolbar li button:hover { background-color: #3276b1; color: #fff; } .medium-editor-toolbar li .medium-editor-button-first { - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; } + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; } .medium-editor-toolbar li .medium-editor-button-last { + border-bottom-right-radius: 4px; border-right: none; - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; } + border-top-right-radius: 4px; } .medium-editor-toolbar li .medium-editor-button-active { background-color: #3276b1; color: #fff; } .medium-editor-toolbar-form { background: #428bca; - color: #fff; - border-radius: 4px; } + border-radius: 4px; + color: #fff; } .medium-editor-toolbar-form .medium-editor-toolbar-input { - height: 60px; background: #428bca; - color: #fff; } + color: #fff; + height: 60px; } .medium-editor-toolbar-form .medium-editor-toolbar-input::-webkit-input-placeholder { color: #fff; color: rgba(255, 255, 255, 0.8); } @@ -60,8 +60,8 @@ .medium-editor-toolbar-anchor-preview { background: #428bca; - color: #fff; - border-radius: 4px; } + border-radius: 4px; + color: #fff; } .medium-editor-placeholder:after { color: #357ebd; } diff --git a/dist/css/themes/bootstrap.min.css b/dist/css/themes/bootstrap.min.css index d914a8aa7..d0970422d 100644 --- a/dist/css/themes/bootstrap.min.css +++ b/dist/css/themes/bootstrap.min.css @@ -1 +1 @@ -.medium-toolbar-arrow-under:after{top:60px;border-color:#428bca transparent transparent}.medium-toolbar-arrow-over:before{border-color:transparent transparent #428bca}.medium-editor-toolbar{border:1px solid #357ebd;background-color:#428bca;border-radius:4px}.medium-editor-toolbar li button{min-width:60px;height:60px;border:none;border-right:1px solid #357ebd;background-color:transparent;color:#fff;box-sizing:border-box;-webkit-transition:background-color .2s ease-in,color .2s ease-in;transition:background-color .2s ease-in,color .2s ease-in}.medium-editor-toolbar li .medium-editor-button-active,.medium-editor-toolbar li button:hover{color:#fff;background-color:#3276b1}.medium-editor-toolbar li .medium-editor-button-first{border-top-left-radius:4px;border-bottom-left-radius:4px}.medium-editor-toolbar li .medium-editor-button-last{border-right:none;border-top-right-radius:4px;border-bottom-right-radius:4px}.medium-editor-toolbar-form{background:#428bca;color:#fff;border-radius:4px}.medium-editor-toolbar-form .medium-editor-toolbar-input{height:60px;background:#428bca;color:#fff}.medium-editor-toolbar-form .medium-editor-toolbar-input::-webkit-input-placeholder{color:#fff;color:rgba(255,255,255,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input:-moz-placeholder{color:#fff;color:rgba(255,255,255,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input::-moz-placeholder{color:#fff;color:rgba(255,255,255,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input:-ms-input-placeholder{color:#fff;color:rgba(255,255,255,.8)}.medium-editor-toolbar-form a{color:#fff}.medium-editor-toolbar-anchor-preview{background:#428bca;color:#fff;border-radius:4px}.medium-editor-placeholder:after{color:#357ebd} \ No newline at end of file +.medium-toolbar-arrow-under:after{border-color:#428bca transparent transparent;top:60px}.medium-toolbar-arrow-over:before{border-color:transparent transparent #428bca}.medium-editor-toolbar{background-color:#428bca;border:1px solid #357ebd;border-radius:4px}.medium-editor-toolbar li button{background-color:transparent;border:none;border-right:1px solid #357ebd;box-sizing:border-box;color:#fff;height:60px;min-width:60px;-webkit-transition:background-color .2s ease-in,color .2s ease-in;transition:background-color .2s ease-in,color .2s ease-in}.medium-editor-toolbar li .medium-editor-button-active,.medium-editor-toolbar li button:hover{color:#fff;background-color:#3276b1}.medium-editor-toolbar li .medium-editor-button-first{border-bottom-left-radius:4px;border-top-left-radius:4px}.medium-editor-toolbar li .medium-editor-button-last{border-bottom-right-radius:4px;border-right:none;border-top-right-radius:4px}.medium-editor-toolbar-form{background:#428bca;border-radius:4px;color:#fff}.medium-editor-toolbar-form .medium-editor-toolbar-input{background:#428bca;color:#fff;height:60px}.medium-editor-toolbar-form .medium-editor-toolbar-input::-webkit-input-placeholder{color:#fff;color:rgba(255,255,255,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input:-moz-placeholder{color:#fff;color:rgba(255,255,255,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input::-moz-placeholder{color:#fff;color:rgba(255,255,255,.8)}.medium-editor-toolbar-form .medium-editor-toolbar-input:-ms-input-placeholder{color:#fff;color:rgba(255,255,255,.8)}.medium-editor-toolbar-form a{color:#fff}.medium-editor-toolbar-anchor-preview{background:#428bca;border-radius:4px;color:#fff}.medium-editor-placeholder:after{color:#357ebd} \ No newline at end of file diff --git a/dist/css/themes/default.css b/dist/css/themes/default.css index 624f3d574..c1f1ecf5b 100644 --- a/dist/css/themes/default.css +++ b/dist/css/themes/default.css @@ -1,63 +1,63 @@ .medium-toolbar-arrow-under:after { - top: 50px; - border-color: #242424 transparent transparent transparent; } + border-color: #242424 transparent transparent transparent; + top: 50px; } .medium-toolbar-arrow-over:before { - top: -8px; - border-color: transparent transparent #242424 transparent; } + border-color: transparent transparent #242424 transparent; + top: -8px; } .medium-editor-toolbar { - border: 1px solid #000; background-color: #242424; background: -webkit-linear-gradient(top, #242424, rgba(36, 36, 36, 0.75)); background: linear-gradient(to bottom, #242424, rgba(36, 36, 36, 0.75)); + border: 1px solid #000; border-radius: 5px; box-shadow: 0 0 3px #000; } .medium-editor-toolbar li button { - min-width: 50px; - height: 50px; + background-color: #242424; + background: -webkit-linear-gradient(top, #242424, rgba(36, 36, 36, 0.89)); + background: linear-gradient(to bottom, #242424, rgba(36, 36, 36, 0.89)); border: 0; border-right: 1px solid #000; border-left: 1px solid #333; border-left: 1px solid rgba(255, 255, 255, 0.1); - background-color: #242424; - color: #fff; - background: -webkit-linear-gradient(top, #242424, rgba(36, 36, 36, 0.89)); - background: linear-gradient(to bottom, #242424, rgba(36, 36, 36, 0.89)); box-shadow: 0 2px 2px rgba(0, 0, 0, 0.3); + color: #fff; + height: 50px; + min-width: 50px; -webkit-transition: background-color 0.2s ease-in; transition: background-color 0.2s ease-in; } .medium-editor-toolbar li button:hover { background-color: #000; color: yellow; } .medium-editor-toolbar li .medium-editor-button-first { - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; } + border-bottom-left-radius: 5px; + border-top-left-radius: 5px; } .medium-editor-toolbar li .medium-editor-button-last { - border-top-right-radius: 5px; - border-bottom-right-radius: 5px; } + border-bottom-right-radius: 5px; + border-top-right-radius: 5px; } .medium-editor-toolbar li .medium-editor-button-active { background-color: #000; - color: #fff; background: -webkit-linear-gradient(top, #242424, rgba(0, 0, 0, 0.89)); - background: linear-gradient(to bottom, #242424, rgba(0, 0, 0, 0.89)); } + background: linear-gradient(to bottom, #242424, rgba(0, 0, 0, 0.89)); + color: #fff; } .medium-editor-toolbar-form { background: #242424; - color: #999; - border-radius: 5px; } + border-radius: 5px; + color: #999; } .medium-editor-toolbar-form .medium-editor-toolbar-input { - height: 50px; background: #242424; + box-sizing: border-box; color: #ccc; - box-sizing: border-box; } + height: 50px; } .medium-editor-toolbar-form a { color: #fff; } .medium-editor-toolbar-anchor-preview { background: #242424; - color: #fff; - border-radius: 5px; } + border-radius: 5px; + color: #fff; } .medium-editor-placeholder:after { color: #b3b3b1; } diff --git a/dist/css/themes/default.min.css b/dist/css/themes/default.min.css index 06c5ba840..bd238b1d8 100644 --- a/dist/css/themes/default.min.css +++ b/dist/css/themes/default.min.css @@ -1 +1 @@ -.medium-toolbar-arrow-under:after{top:50px;border-color:#242424 transparent transparent}.medium-toolbar-arrow-over:before{top:-8px;border-color:transparent transparent #242424}.medium-editor-toolbar{border:1px solid #000;background:-webkit-linear-gradient(top,#242424,rgba(36,36,36,.75));background:linear-gradient(to bottom,#242424,rgba(36,36,36,.75));border-radius:5px;box-shadow:0 0 3px #000}.medium-editor-toolbar li button{min-width:50px;height:50px;border:0;border-right:1px solid #000;border-left:1px solid #333;border-left:1px solid rgba(255,255,255,.1);color:#fff;background:-webkit-linear-gradient(top,#242424,rgba(36,36,36,.89));background:linear-gradient(to bottom,#242424,rgba(36,36,36,.89));box-shadow:0 2px 2px rgba(0,0,0,.3);-webkit-transition:background-color .2s ease-in;transition:background-color .2s ease-in}.medium-editor-toolbar li button:hover{background-color:#000;color:#ff0}.medium-editor-toolbar li .medium-editor-button-first{border-top-left-radius:5px;border-bottom-left-radius:5px}.medium-editor-toolbar li .medium-editor-button-last{border-top-right-radius:5px;border-bottom-right-radius:5px}.medium-editor-toolbar li .medium-editor-button-active{color:#fff;background:-webkit-linear-gradient(top,#242424,rgba(0,0,0,.89));background:linear-gradient(to bottom,#242424,rgba(0,0,0,.89))}.medium-editor-toolbar-form{background:#242424;color:#999;border-radius:5px}.medium-editor-toolbar-form .medium-editor-toolbar-input{height:50px;background:#242424;color:#ccc;box-sizing:border-box}.medium-editor-toolbar-form a{color:#fff}.medium-editor-toolbar-anchor-preview{background:#242424;color:#fff;border-radius:5px}.medium-editor-placeholder:after{color:#b3b3b1} \ No newline at end of file +.medium-toolbar-arrow-under:after{border-color:#242424 transparent transparent;top:50px}.medium-toolbar-arrow-over:before{border-color:transparent transparent #242424;top:-8px}.medium-editor-toolbar{background:-webkit-linear-gradient(top,#242424,rgba(36,36,36,.75));background:linear-gradient(to bottom,#242424,rgba(36,36,36,.75));border:1px solid #000;border-radius:5px;box-shadow:0 0 3px #000}.medium-editor-toolbar li button{background:-webkit-linear-gradient(top,#242424,rgba(36,36,36,.89));background:linear-gradient(to bottom,#242424,rgba(36,36,36,.89));border:0;border-right:1px solid #000;border-left:1px solid #333;border-left:1px solid rgba(255,255,255,.1);box-shadow:0 2px 2px rgba(0,0,0,.3);color:#fff;height:50px;min-width:50px;-webkit-transition:background-color .2s ease-in;transition:background-color .2s ease-in}.medium-editor-toolbar li button:hover{background-color:#000;color:#ff0}.medium-editor-toolbar li .medium-editor-button-first{border-bottom-left-radius:5px;border-top-left-radius:5px}.medium-editor-toolbar li .medium-editor-button-last{border-bottom-right-radius:5px;border-top-right-radius:5px}.medium-editor-toolbar li .medium-editor-button-active{background:-webkit-linear-gradient(top,#242424,rgba(0,0,0,.89));background:linear-gradient(to bottom,#242424,rgba(0,0,0,.89));color:#fff}.medium-editor-toolbar-form{background:#242424;border-radius:5px;color:#999}.medium-editor-toolbar-form .medium-editor-toolbar-input{background:#242424;box-sizing:border-box;color:#ccc;height:50px}.medium-editor-toolbar-form a{color:#fff}.medium-editor-toolbar-anchor-preview{background:#242424;border-radius:5px;color:#fff}.medium-editor-placeholder:after{color:#b3b3b1} \ No newline at end of file diff --git a/dist/js/medium-editor.js b/dist/js/medium-editor.js index 2a33df527..ed717d398 100644 --- a/dist/js/medium-editor.js +++ b/dist/js/medium-editor.js @@ -403,31 +403,6 @@ var Util; (function (window) { 'use strict'; - // Params: Array, Boolean, Object - function getProp(parts, create, context) { - if (!context) { - context = window; - } - - try { - for (var i = 0; i < parts.length; i++) { - var p = parts[i]; - if (!(p in context)) { - if (create) { - context[p] = {}; - } else { - return; - } - } - context = context[p]; - } - return context; - } catch (e) { - // 'p in context' throws an exception when context is a number, boolean, etc. rather than an object, - // so in that corner case just return undefined (by having no return statement) - } - } - function copyInto(overwrite, dest) { var prop, sources = Array.prototype.slice.call(arguments, 2); @@ -463,7 +438,8 @@ var Util; ENTER: 13, ESCAPE: 27, SPACE: 32, - DELETE: 46 + DELETE: 46, + K: 107 }, /** @@ -485,12 +461,7 @@ var Util; * @see : http://stackoverflow.com/q/4471582/569101 */ isKey: function (event, keys) { - var keyCode = event.which; - - // getting the key code from event - if (null === keyCode) { - keyCode = event.charCode !== null ? event.charCode : event.keyCode; - } + var keyCode = this.getKeyCode(event); // it's not an array let's just compare strings! if (false === Array.isArray(keys)) { @@ -504,6 +475,17 @@ var Util; return true; }, + getKeyCode: function (event) { + var keyCode = event.which; + + // getting the key code from event + if (null === keyCode) { + keyCode = event.charCode !== null ? event.charCode : event.keyCode; + } + + return keyCode; + }, + parentElements: ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre'], extend: function extend(/* dest, source1, source2, ...*/) { @@ -516,16 +498,6 @@ var Util; return copyInto.apply(this, args); }, - derives: function derives(base, derived) { - var origPrototype = derived.prototype; - function Proto() { } - Proto.prototype = base.prototype; - derived.prototype = new Proto(); - derived.prototype.constructor = base; - derived.prototype = copyInto(false, derived.prototype, origPrototype); - return derived; - }, - // Find the next node in the DOM tree that represents any text that is being // displayed directly next to the targetNode (passed as an argument) // Text that appears directly next to the current node can be: @@ -634,7 +606,7 @@ var Util; return current; } // do not traverse upwards past the nearest containing editor - if (current.getAttribute('data-medium-element')) { + if (current.getAttribute('data-medium-editor-element')) { return false; } } @@ -671,7 +643,7 @@ var Util; (toReplace.nodeType !== 3 && toReplace.innerHTML === range.toString())) { while (toReplace.parentNode && toReplace.parentNode.childNodes.length === 1 && - !toReplace.parentNode.getAttribute('data-medium-element')) { + !toReplace.parentNode.getAttribute('data-medium-editor-element')) { toReplace = toReplace.parentNode; } range.selectNode(toReplace); @@ -698,24 +670,6 @@ var Util; } }, - getSelectionRange: function (ownerDocument) { - this.deprecated('Util.getSelectionRange', 'Selection.getSelectionRange', 'v5.0.0'); - - return Selection.getSelectionRange(ownerDocument); - }, - - getSelectionStart: function (ownerDocument) { - this.deprecated('Util.getSelectionStart', 'Selection.getSelectionStart', 'v5.0.0'); - - return Selection.getSelectionStart(ownerDocument); - }, - - getSelectionData: function (el) { - this.deprecated('Util.getSelectionData', 'Selection.getSelectionData', 'v5.0.0'); - - return Selection.getSelectionData(el); - }, - execFormatBlock: function (doc, tagName) { var selectionData = Selection.getSelectionData(Selection.getSelectionStart(doc)); // FF handles blockquote differently on formatBlock @@ -824,12 +778,6 @@ var Util; } }, - unwrapElement: function (element) { - this.deprecated('unwrapElement', 'unwrap', 'v5.0.0'); - - this.unwrap(element, element.ownerDocument); - }, - /* splitDOMTree * * Given a root element some descendant element, split the root element @@ -1113,31 +1061,15 @@ var Util; } else { el.parentNode.removeChild(el); } - }, - - setObject: function (name, value, context) { - // summary: - // Set a property from a dot-separated string, such as 'A.B.C' - var parts = name.split('.'), - p = parts.pop(), - obj = getProp(parts, true, context); - return obj && p ? (obj[p] = value) : undefined; // Object - }, - - getObject: function (name, create, context) { - // summary: - // Get a property from a dot-separated string, such as 'A.B.C' - return getProp(name ? name.split('.') : [], create, context); // Object } - }; }(window)); -var ButtonsData; +var buttonDefaults; (function () { 'use strict'; - ButtonsData = { + buttonDefaults = { 'bold': { name: 'bold', action: 'bold', @@ -1149,8 +1081,7 @@ var ButtonsData; }, useQueryState: true, contentDefault: 'B', - contentFA: '', - key: 'b' + contentFA: '' }, 'italic': { name: 'italic', @@ -1163,8 +1094,7 @@ var ButtonsData; }, useQueryState: true, contentDefault: 'I', - contentFA: '', - key: 'i' + contentFA: '' }, 'underline': { name: 'underline', @@ -1177,8 +1107,7 @@ var ButtonsData; }, useQueryState: true, contentDefault: 'U', - contentFA: '', - key: 'u' + contentFA: '' }, 'strikethrough': { name: 'strikethrough', @@ -1364,30 +1293,21 @@ var editorDefaults; // summary: The default options hash used by the Editor editorDefaults = { + activeButtonClass: 'medium-editor-button-active', allowMultiParagraphSelection: true, - buttons: ['bold', 'italic', 'underline', 'anchor', 'header1', 'header2', 'quote'], buttonLabels: false, delay: 0, - diffLeft: 0, - diffTop: -10, disableReturn: false, disableDoubleReturn: false, - disableToolbar: false, disableEditing: false, autoLink: false, - toolbarAlign: 'center', elementsContainer: false, - imageDragging: true, - standardizeSelectionStart: false, contentWindow: window, ownerDocument: document, firstHeader: 'h3', secondHeader: 'h4', targetBlank: false, extensions: {}, - activeButtonClass: 'medium-editor-button-active', - firstButtonClass: 'medium-editor-button-first', - lastButtonClass: 'medium-editor-button-last', spellcheck: true }; })(); @@ -1643,7 +1563,8 @@ var Extension; // event handling 'on', 'off', - 'subscribe' + 'subscribe', + 'trigger' ].forEach(function (helper) { Extension.prototype[helper] = function () { @@ -1675,7 +1596,7 @@ var Selection; getSelectionElement: function (contentWindow) { return this.findMatchingSelectionParent(function (el) { - return el.getAttribute('data-medium-element'); + return el.getAttribute('data-medium-editor-element'); }, contentWindow); }, @@ -1730,14 +1651,14 @@ var Selection; // http://stackoverflow.com/questions/4176923/html-of-selected-text // by Tim Down - getSelectionHtml: function getSelectionHtml() { + getSelectionHtml: function getSelectionHtml(doc) { var i, html = '', - sel = this.options.contentWindow.getSelection(), + sel = doc.getSelection(), len, container; if (sel.rangeCount) { - container = this.options.ownerDocument.createElement('div'); + container = doc.createElement('div'); for (i = 0, len = sel.rangeCount; i < len; i += 1) { container.appendChild(sel.getRangeAt(i).cloneContents()); } @@ -1862,7 +1783,7 @@ var Selection; getSelectionRange: function (ownerDocument) { var selection = ownerDocument.getSelection(); - if (selection.rangeCount === 0 || true === selection.isCollapsed) { + if (selection.rangeCount === 0) { return null; } return selection.getRangeAt(0); @@ -2212,7 +2133,8 @@ var Events; }, updateFocus: function (target, eventObj) { - var toolbarEl = this.base.toolbar ? this.base.toolbar.getToolbarElement() : null, + var toolbar = this.base.getExtensionByName('toolbar'), + toolbarEl = toolbar ? toolbar.getToolbarElement() : null, anchorPreview = this.base.getExtensionByName('anchor-preview'), previewEl = (anchorPreview && anchorPreview.getPreviewElement) ? anchorPreview.getPreviewElement() : null, hadFocus = this.base.getFocusedElement(), @@ -2392,47 +2314,138 @@ var Events; }; }()); -/* istanbul ignore next */ -var DefaultButton; - -/* istanbul ignore next */ +var Button; (function () { 'use strict'; - DefaultButton = function (options, instance) { - Util.deprecated('MediumEditor.statics.DefaultButton', 'MediumEditor.extensions.button', 'v5.0.0'); + /*global Extension, buttonDefaults */ - this.options = options; - this.name = options.name; - this.init(instance); - }; + Button = Extension.extend({ - DefaultButton.prototype = { - init: function (instance) { - this.base = instance; + /* Button Options */ - this.button = this.createButton(); - this.base.on(this.button, 'click', this.handleClick.bind(this)); - if (this.options.key) { - this.base.subscribe('editableKeydown', this.handleKeydown.bind(this)); + /* action: [string] + * The action argument to pass to MediumEditor.execAction() + * when the button is clicked + */ + action: undefined, + + /* aria: [string] + * The value to add as the aria-label attribute of the button + * element displayed in the toolbar. + * This is also used as the tooltip for the button + */ + aria: undefined, + + /* tagNames: [Array] + * NOTE: This is not used if useQueryState is set to true. + * + * Array of element tag names that would indicate that this + * button has already been applied. If this action has already + * been applied, the button will be displayed as 'active' in the toolbar + * + * Example: + * For 'bold', if the text is ever within a or + * tag that indicates the text is already bold. So the array + * of tagNames for bold would be: ['b', 'strong'] + */ + tagNames: undefined, + + /* style: [Object] + * NOTE: This is not used if useQueryState is set to true. + * + * A pair of css property & value(s) that indicate that this + * button has already been applied. If this action has already + * been applied, the button will be displayed as 'active' in the toolbar + * Properties of the object: + * prop [String]: name of the css property + * value [String]: value(s) of the css property + * multiple values can be separated by a '|' + * + * Example: + * For 'bold', if the text is ever within an element with a 'font-weight' + * style property set to '700' or 'bold', that indicates the text + * is already bold. So the style object for bold would be: + * { prop: 'font-weight', value: '700|bold' } + */ + style: undefined, + + /* useQueryState: [boolean] + * Enables/disables whether this button should use the built-in + * document.queryCommandState() method to determine whether + * the action has already been applied. If the action has already + * been applied, the button will be displayed as 'active' in the toolbar + * + * Example: + * For 'bold', if this is set to true, the code will call: + * document.queryCommandState('bold') which will return true if the + * browser thinks the text is already bold, and false otherwise + */ + useQueryState: undefined, + + /* contentDefault: [string] + * Default innerHTML to put inside the button + */ + contentDefault: undefined, + + /* contentFA: [string] + * The innerHTML to use for the content of the button + * if the `buttonLabels` option for MediumEditor is set to 'fontawesome' + */ + contentFA: undefined, + + /* buttonDefaults: [Object] + * Set of default config options for all of the built-in MediumEditor buttons + */ + defaults: buttonDefaults, + + // The button constructor can optionally accept the name of a built-in button + // (ie 'bold', 'italic', etc.) + // When the name of a button is passed, it will initialize itself with the + // configuration for that button + constructor: function (options) { + if (Button.isBuiltInButton(options)) { + Extension.call(this, this.defaults[options]); + } else { + Extension.call(this, options); } }, + + init: function () { + Extension.prototype.init.apply(this, arguments); + + this.button = this.createButton(); + this.on(this.button, 'click', this.handleClick.bind(this)); + }, + + /* getButton: [function ()] + * + * If implemented, this function will be called when + * the toolbar is being created. The DOM Element returned + * by this function will be appended to the toolbar along + * with any other buttons. + */ getButton: function () { return this.button; }, + getAction: function () { - return (typeof this.options.action === 'function') ? this.options.action(this.base.options) : this.options.action; + return (typeof this.action === 'function') ? this.action(this.base.options) : this.action; }, + getAria: function () { - return (typeof this.options.aria === 'function') ? this.options.aria(this.base.options) : this.options.aria; + return (typeof this.aria === 'function') ? this.aria(this.base.options) : this.aria; }, + getTagNames: function () { - return (typeof this.options.tagNames === 'function') ? this.options.tagNames(this.base.options) : this.options.tagNames; + return (typeof this.tagNames === 'function') ? this.tagNames(this.base.options) : this.tagNames; }, + createButton: function () { - var button = this.base.options.ownerDocument.createElement('button'), - content = this.options.contentDefault, - ariaLabel = this.getAria(); + var button = this.document.createElement('button'), + content = this.contentDefault, + ariaLabel = this.getAria(), + buttonLabels = this.getEditorOption('buttonLabels'); button.classList.add('medium-editor-action'); button.classList.add('medium-editor-action-' + this.name); button.setAttribute('data-action', this.getAction()); @@ -2440,58 +2453,50 @@ var DefaultButton; button.setAttribute('title', ariaLabel); button.setAttribute('aria-label', ariaLabel); } - if (this.base.options.buttonLabels) { - if (this.base.options.buttonLabels === 'fontawesome' && this.options.contentFA) { - content = this.options.contentFA; - } else if (typeof this.base.options.buttonLabels === 'object' && this.base.options.buttonLabels[this.name]) { - content = this.base.options.buttonLabels[this.options.name]; + if (buttonLabels) { + if (buttonLabels === 'fontawesome' && this.contentFA) { + content = this.contentFA; + } else if (typeof buttonLabels === 'object' && buttonLabels[this.name]) { + content = buttonLabels[this.name]; } } button.innerHTML = content; return button; }, - handleKeydown: function (evt) { - var key = String.fromCharCode(evt.which || evt.keyCode).toLowerCase(), - action; - if (this.options.key === key && Util.isMetaCtrlKey(evt)) { - evt.preventDefault(); - evt.stopPropagation(); - - action = this.getAction(); - if (action) { - this.base.execAction(action); - } - } - }, - handleClick: function (evt) { - evt.preventDefault(); - evt.stopPropagation(); + handleClick: function (event) { + event.preventDefault(); + event.stopPropagation(); var action = this.getAction(); if (action) { - this.base.execAction(action); + this.execAction(action); } }, + isActive: function () { - return this.button.classList.contains(this.base.options.activeButtonClass); + return this.button.classList.contains(this.getEditorOption('activeButtonClass')); }, + setInactive: function () { - this.button.classList.remove(this.base.options.activeButtonClass); + this.button.classList.remove(this.getEditorOption('activeButtonClass')); delete this.knownState; }, + setActive: function () { - this.button.classList.add(this.base.options.activeButtonClass); + this.button.classList.add(this.getEditorOption('activeButtonClass')); delete this.knownState; }, + queryCommandState: function () { var queryState = null; - if (this.options.useQueryState) { + if (this.useQueryState) { queryState = this.base.queryCommandState(this.getAction()); } return queryState; }, + isAlreadyApplied: function (node) { var isMatch = false, tagNames = this.getTagNames(), @@ -2506,16 +2511,16 @@ var DefaultButton; isMatch = tagNames.indexOf(node.tagName.toLowerCase()) !== -1; } - if (!isMatch && this.options.style) { - styleVals = this.options.style.value.split('|'); - computedStyle = this.base.options.contentWindow.getComputedStyle(node, null).getPropertyValue(this.options.style.prop); + if (!isMatch && this.style) { + styleVals = this.style.value.split('|'); + computedStyle = this.window.getComputedStyle(node, null).getPropertyValue(this.style.prop); styleVals.forEach(function (val) { if (!this.knownState) { isMatch = (computedStyle.indexOf(val) !== -1); // text-decoration is not inherited by default // so if the computed style for text-decoration doesn't match // don't write to knownState so we can fallback to other checks - if (isMatch || this.options.style.prop !== 'text-decoration') { + if (isMatch || this.style.prop !== 'text-decoration') { this.knownState = isMatch; } } @@ -2524,859 +2529,30 @@ var DefaultButton; return isMatch; } + }); + + Button.isBuiltInButton = function (name) { + return (typeof name === 'string') && Button.prototype.defaults.hasOwnProperty(name); }; }()); -/* istanbul ignore next */ -var AnchorExtension; -/* istanbul ignore next */ +var FormExtension; (function () { 'use strict'; - function AnchorDerived() { - Util.deprecated('MediumEditor.statics.AnchorExtension', 'MediumEditor.extensions.anchor', 'v5.0.0'); - this.parent = true; - this.options = { - name: 'anchor', - action: 'createLink', - aria: 'link', - tagNames: ['a'], - contentDefault: '#', - contentFA: '', - key: 'k' - }; - this.name = 'anchor'; - this.hasForm = true; - } - - AnchorDerived.prototype = { - - // Button and Extension handling - - // labels for the anchor-edit form buttons - formSaveLabel: '✓', - formCloseLabel: '×', - - // Called when the button the toolbar is clicked - // Overrides DefaultButton.handleClick - handleClick: function (evt) { - evt.preventDefault(); - evt.stopPropagation(); - - var selectedParentElement = Selection.getSelectedParentElement(Selection.getSelectionRange(this.base.options.ownerDocument)); - if (selectedParentElement.tagName && - selectedParentElement.tagName.toLowerCase() === 'a') { - return this.base.execAction('unlink'); - } - - if (!this.isDisplayed()) { - this.showForm(); - } - - return false; - }, - - // Called when user hits the defined shortcut (CTRL / COMMAND + K) - // Overrides DefaultButton.handleKeydown - handleKeydown: function (evt) { - var key = String.fromCharCode(evt.which || evt.keyCode).toLowerCase(); - - if (this.options.key === key && Util.isMetaCtrlKey(evt)) { - evt.preventDefault(); - evt.stopPropagation(); - - this.handleClick(evt); - } - }, - - // Called by medium-editor to append form to the toolbar - getForm: function () { - if (!this.form) { - this.form = this.createForm(); - } - return this.form; - }, - - getTemplate: function () { - - var template = [ - '' - ]; - - template.push( - '', - this.base.options.buttonLabels === 'fontawesome' ? '' : this.formSaveLabel, - '' - ); - - template.push('', - this.base.options.buttonLabels === 'fontawesome' ? '' : this.formCloseLabel, - ''); - - // both of these options are slightly moot with the ability to - // override the various form buildup/serialize functions. - - if (this.base.options.anchorTarget) { - // fixme: ideally, this options.anchorInputCheckboxLabel would be a formLabel too, - // figure out how to deprecate? also consider `fa-` icon default implcations. - template.push( - '', - '' - ); - } - - if (this.base.options.anchorButton) { - // fixme: expose this `Button` text as a formLabel property, too - // and provide similar access to a `fa-` icon default. - template.push( - '', - '' - ); - } - - return template.join(''); - - }, - - // Used by medium-editor when the default toolbar is to be displayed - isDisplayed: function () { - return this.getForm().style.display === 'block'; - }, - - hideForm: function () { - this.getForm().style.display = 'none'; - this.getInput().value = ''; - }, - - showForm: function (linkValue) { - var input = this.getInput(); - - this.base.saveSelection(); - this.base.hideToolbarDefaultActions(); - this.getForm().style.display = 'block'; - this.base.setToolbarPosition(); - - input.value = linkValue || ''; - input.focus(); - }, - - // Called by core when tearing down medium-editor (deactivate) - deactivate: function () { - if (!this.form) { - return false; - } - - if (this.form.parentNode) { - this.form.parentNode.removeChild(this.form); - } - - delete this.form; - }, + /* global Button */ - // core methods + var noop = function () {}; - getFormOpts: function () { - // no notion of private functions? wanted `_getFormOpts` - var targetCheckbox = this.getForm().querySelector('.medium-editor-toolbar-anchor-target'), - buttonCheckbox = this.getForm().querySelector('.medium-editor-toolbar-anchor-button'), - opts = { - url: this.getInput().value - }; + /* Base functionality for an extension whcih will display + * a 'form' inside the toolbar + */ + FormExtension = Button.extend({ - if (this.base.options.checkLinkFormat) { - opts.url = this.checkLinkFormat(opts.url); - } - - if (targetCheckbox && targetCheckbox.checked) { - opts.target = '_blank'; - } else { - opts.target = '_self'; - } - - if (buttonCheckbox && buttonCheckbox.checked) { - opts.buttonClass = this.base.options.anchorButtonClass; - } - - return opts; - }, - - doFormSave: function () { - var opts = this.getFormOpts(); - this.completeFormSave(opts); - }, - - completeFormSave: function (opts) { - this.base.restoreSelection(); - this.base.createLink(opts); - this.base.checkSelection(); - }, - - checkLinkFormat: function (value) { - var re = /^(https?|ftps?|rtmpt?):\/\/|mailto:/; - return (re.test(value) ? '' : 'http://') + value; - }, - - doFormCancel: function () { - this.base.restoreSelection(); - this.base.checkSelection(); - }, - - // form creation and event handling - - attachFormEvents: function (form) { - var close = form.querySelector('.medium-editor-toolbar-close'), - save = form.querySelector('.medium-editor-toolbar-save'), - input = form.querySelector('.medium-editor-toolbar-input'); - - // Handle clicks on the form itself - this.base.on(form, 'click', this.handleFormClick.bind(this)); - - // Handle typing in the textbox - this.base.on(input, 'keyup', this.handleTextboxKeyup.bind(this)); - - // Handle close button clicks - this.base.on(close, 'click', this.handleCloseClick.bind(this)); - - // Handle save button clicks (capture) - this.base.on(save, 'click', this.handleSaveClick.bind(this), true); - - }, - - createForm: function () { - var doc = this.base.options.ownerDocument, - form = doc.createElement('div'); - - // Anchor Form (div) - form.className = 'medium-editor-toolbar-form'; - form.id = 'medium-editor-toolbar-form-anchor-' + this.base.id; - form.innerHTML = this.getTemplate(); - this.attachFormEvents(form); - - return form; - }, - - getInput: function () { - return this.getForm().querySelector('input.medium-editor-toolbar-input'); - }, - - handleTextboxKeyup: function (event) { - // For ENTER -> create the anchor - if (event.keyCode === Util.keyCode.ENTER) { - event.preventDefault(); - this.doFormSave(); - return; - } - - // For ESCAPE -> close the form - if (event.keyCode === Util.keyCode.ESCAPE) { - event.preventDefault(); - this.doFormCancel(); - } - }, - - handleFormClick: function (event) { - // make sure not to hide form when clicking inside the form - event.stopPropagation(); - }, - - handleSaveClick: function (event) { - // Clicking Save -> create the anchor - event.preventDefault(); - this.doFormSave(); - }, - - handleCloseClick: function (event) { - // Click Close -> close the form - event.preventDefault(); - this.doFormCancel(); - } - }; - - AnchorExtension = Util.derives(DefaultButton, AnchorDerived); - -}()); -/* istanbul ignore next */ -var AnchorPreviewDeprecated; - -/* istanbul ignore next */ -(function () { - 'use strict'; - - AnchorPreviewDeprecated = function () { - Util.deprecated('MediumEditor.statics.AnchorPreview', 'MediumEditor.extensions.anchorPreview', 'v5.0.0'); - this.parent = true; - this.name = 'anchor-preview'; - }; - - AnchorPreviewDeprecated.prototype = { - - // the default selector to locate where to - // put the activeAnchor value in the preview - previewValueSelector: 'a', - - init: function () { - - this.anchorPreview = this.createPreview(); - this.base.options.elementsContainer.appendChild(this.anchorPreview); - - this.attachToEditables(); - }, - - getPreviewElement: function () { - return this.anchorPreview; - }, - - createPreview: function () { - var el = this.base.options.ownerDocument.createElement('div'); - - el.id = 'medium-editor-anchor-preview-' + this.base.id; - el.className = 'medium-editor-anchor-preview'; - el.innerHTML = this.getTemplate(); - - this.base.on(el, 'click', this.handleClick.bind(this)); - - return el; - }, - - getTemplate: function () { - return '
' + - ' ' + - '
'; - }, - - deactivate: function () { - if (this.anchorPreview) { - if (this.anchorPreview.parentNode) { - this.anchorPreview.parentNode.removeChild(this.anchorPreview); - } - delete this.anchorPreview; - } - }, - - hidePreview: function () { - this.anchorPreview.classList.remove('medium-editor-anchor-preview-active'); - this.activeAnchor = null; - }, - - showPreview: function (anchorEl) { - if (this.anchorPreview.classList.contains('medium-editor-anchor-preview-active') || - anchorEl.getAttribute('data-disable-preview')) { - return true; - } - - if (this.previewValueSelector) { - this.anchorPreview.querySelector(this.previewValueSelector).textContent = anchorEl.attributes.href.value; - this.anchorPreview.querySelector(this.previewValueSelector).href = anchorEl.attributes.href.value; - } - - this.anchorPreview.classList.add('medium-toolbar-arrow-over'); - this.anchorPreview.classList.remove('medium-toolbar-arrow-under'); - - if (!this.anchorPreview.classList.contains('medium-editor-anchor-preview-active')) { - this.anchorPreview.classList.add('medium-editor-anchor-preview-active'); - } - - this.activeAnchor = anchorEl; - - this.positionPreview(); - this.attachPreviewHandlers(); - - return this; - }, - - positionPreview: function () { - var buttonHeight = this.anchorPreview.offsetHeight, - boundary = this.activeAnchor.getBoundingClientRect(), - middleBoundary = (boundary.left + boundary.right) / 2, - halfOffsetWidth, - defaultLeft; - - halfOffsetWidth = this.anchorPreview.offsetWidth / 2; - defaultLeft = this.base.options.diffLeft - halfOffsetWidth; - - this.anchorPreview.style.top = Math.round(buttonHeight + boundary.bottom - this.base.options.diffTop + this.base.options.contentWindow.pageYOffset - this.anchorPreview.offsetHeight) + 'px'; - if (middleBoundary < halfOffsetWidth) { - this.anchorPreview.style.left = defaultLeft + halfOffsetWidth + 'px'; - } else if ((this.base.options.contentWindow.innerWidth - middleBoundary) < halfOffsetWidth) { - this.anchorPreview.style.left = this.base.options.contentWindow.innerWidth + defaultLeft - halfOffsetWidth + 'px'; - } else { - this.anchorPreview.style.left = defaultLeft + middleBoundary + 'px'; - } - }, - - attachToEditables: function () { - this.base.subscribe('editableMouseover', this.handleEditableMouseover.bind(this)); - }, - - handleClick: function (event) { - var anchorExtension = this.base.getExtensionByName('anchor'), - activeAnchor = this.activeAnchor; - - if (anchorExtension && activeAnchor) { - event.preventDefault(); - - this.base.selectElement(this.activeAnchor); - - // Using setTimeout + options.delay because: - // We may actually be displaying the anchor form, which should be controlled by options.delay - this.base.delay(function () { - if (activeAnchor) { - anchorExtension.showForm(activeAnchor.attributes.href.value); - activeAnchor = null; - } - }.bind(this)); - } - - this.hidePreview(); - }, - - handleAnchorMouseout: function () { - this.anchorToPreview = null; - this.base.off(this.activeAnchor, 'mouseout', this.instanceHandleAnchorMouseout); - this.instanceHandleAnchorMouseout = null; - }, - - handleEditableMouseover: function (event) { - var target = Util.getClosestTag(event.target, 'a'); - - if (target) { - - // Detect empty href attributes - // The browser will make href="" or href="#top" - // into absolute urls when accessed as event.targed.href, so check the html - if (!/href=["']\S+["']/.test(target.outerHTML) || /href=["']#\S+["']/.test(target.outerHTML)) { - return true; - } - - // only show when hovering on anchors - if (this.base.toolbar && this.base.toolbar.isDisplayed()) { - // only show when toolbar is not present - return true; - } - - // detach handler for other anchor in case we hovered multiple anchors quickly - if (this.activeAnchor && this.activeAnchor !== target) { - this.detachPreviewHandlers(); - } - - this.anchorToPreview = target; - - this.instanceHandleAnchorMouseout = this.handleAnchorMouseout.bind(this); - this.base.on(this.anchorToPreview, 'mouseout', this.instanceHandleAnchorMouseout); - // Using setTimeout + options.delay because: - // - We're going to show the anchor preview according to the configured delay - // if the mouse has not left the anchor tag in that time - this.base.delay(function () { - if (this.anchorToPreview) { - //this.activeAnchor = this.anchorToPreview; - this.showPreview(this.anchorToPreview); - } - }.bind(this)); - } - }, - - handlePreviewMouseover: function () { - this.lastOver = (new Date()).getTime(); - this.hovering = true; - }, - - handlePreviewMouseout: function (event) { - if (!event.relatedTarget || !/anchor-preview/.test(event.relatedTarget.className)) { - this.hovering = false; - } - }, - - updatePreview: function () { - if (this.hovering) { - return true; - } - var durr = (new Date()).getTime() - this.lastOver; - if (durr > this.base.options.anchorPreviewHideDelay) { - // hide the preview 1/2 second after mouse leaves the link - this.detachPreviewHandlers(); - } - }, - - detachPreviewHandlers: function () { - // cleanup - clearInterval(this.intervalTimer); - if (this.instanceHandlePreviewMouseover) { - this.base.off(this.anchorPreview, 'mouseover', this.instanceHandlePreviewMouseover); - this.base.off(this.anchorPreview, 'mouseout', this.instanceHandlePreviewMouseout); - if (this.activeAnchor) { - this.base.off(this.activeAnchor, 'mouseover', this.instanceHandlePreviewMouseover); - this.base.off(this.activeAnchor, 'mouseout', this.instanceHandlePreviewMouseout); - } - } - - this.hidePreview(); - - this.hovering = this.instanceHandlePreviewMouseover = this.instanceHandlePreviewMouseout = null; - }, - - // TODO: break up method and extract out handlers - attachPreviewHandlers: function () { - this.lastOver = (new Date()).getTime(); - this.hovering = true; - - this.instanceHandlePreviewMouseover = this.handlePreviewMouseover.bind(this); - this.instanceHandlePreviewMouseout = this.handlePreviewMouseout.bind(this); - - this.intervalTimer = setInterval(this.updatePreview.bind(this), 200); - - this.base.on(this.anchorPreview, 'mouseover', this.instanceHandlePreviewMouseover); - this.base.on(this.anchorPreview, 'mouseout', this.instanceHandlePreviewMouseout); - this.base.on(this.activeAnchor, 'mouseover', this.instanceHandlePreviewMouseover); - this.base.on(this.activeAnchor, 'mouseout', this.instanceHandlePreviewMouseout); - } - }; -}()); - -/* istanbul ignore next */ -var FontSizeExtension; - -/* istanbul ignore next */ -(function () { - 'use strict'; - - function FontSizeDerived() { - Util.deprecated('MediumEditor.statics.FontSizeExtension', 'MediumEditor.extensions.fontSize', 'v5.0.0'); - this.parent = true; - this.options = { - name: 'fontsize', - action: 'fontSize', - aria: 'increase/decrease font size', - contentDefault: '±', // ± - contentFA: '' - }; - this.name = 'fontsize'; - this.hasForm = true; - } - - FontSizeDerived.prototype = { - - // Button and Extension handling - - // Called when the button the toolbar is clicked - // Overrides DefaultButton.handleClick - handleClick: function (evt) { - evt.preventDefault(); - evt.stopPropagation(); - - if (!this.isDisplayed()) { - // Get fontsize of current selection (convert to string since IE returns this as number) - var fontSize = this.base.options.ownerDocument.queryCommandValue('fontSize') + ''; - this.showForm(fontSize); - } - - return false; - }, - - // Called by medium-editor to append form to the toolbar - getForm: function () { - if (!this.form) { - this.form = this.createForm(); - } - return this.form; - }, - - // Used by medium-editor when the default toolbar is to be displayed - isDisplayed: function () { - return this.getForm().style.display === 'block'; - }, - - hideForm: function () { - this.getForm().style.display = 'none'; - this.getInput().value = ''; - }, - - showForm: function (fontSize) { - var input = this.getInput(); - - this.base.saveSelection(); - this.base.hideToolbarDefaultActions(); - this.getForm().style.display = 'block'; - this.base.setToolbarPosition(); - - input.value = fontSize || ''; - input.focus(); - }, - - // Called by core when tearing down medium-editor (deactivate) - deactivate: function () { - if (!this.form) { - return false; - } - - if (this.form.parentNode) { - this.form.parentNode.removeChild(this.form); - } - - delete this.form; - }, - - // core methods - - doFormSave: function () { - this.base.restoreSelection(); - this.base.checkSelection(); - }, - - doFormCancel: function () { - this.base.restoreSelection(); - this.clearFontSize(); - this.base.checkSelection(); - }, - - // form creation and event handling - - createForm: function () { - var doc = this.base.options.ownerDocument, - form = doc.createElement('div'), - input = doc.createElement('input'), - close = doc.createElement('a'), - save = doc.createElement('a'); - - // Font Size Form (div) - form.className = 'medium-editor-toolbar-form'; - form.id = 'medium-editor-toolbar-form-fontsize-' + this.base.id; - - // Handle clicks on the form itself - this.base.on(form, 'click', this.handleFormClick.bind(this)); - - // Add font size slider - input.setAttribute('type', 'range'); - input.setAttribute('min', '1'); - input.setAttribute('max', '7'); - input.className = 'medium-editor-toolbar-input'; - form.appendChild(input); - - // Handle typing in the textbox - this.base.on(input, 'change', this.handleSliderChange.bind(this)); - - // Add save buton - save.setAttribute('href', '#'); - save.className = 'medium-editor-toobar-save'; - save.innerHTML = this.base.options.buttonLabels === 'fontawesome' ? - '' : - '✓'; - form.appendChild(save); - - // Handle save button clicks (capture) - this.base.on(save, 'click', this.handleSaveClick.bind(this), true); - - // Add close button - close.setAttribute('href', '#'); - close.className = 'medium-editor-toobar-close'; - close.innerHTML = this.base.options.buttonLabels === 'fontawesome' ? - '' : - '×'; - form.appendChild(close); - - // Handle close button clicks - this.base.on(close, 'click', this.handleCloseClick.bind(this)); - - return form; - }, - - getInput: function () { - return this.getForm().querySelector('input.medium-editor-toolbar-input'); - }, - - clearFontSize: function () { - Selection.getSelectedElements(this.base.options.ownerDocument).forEach(function (el) { - if (el.tagName === 'FONT' && el.hasAttribute('size')) { - el.removeAttribute('size'); - } - }); - }, - - handleSliderChange: function () { - var size = this.getInput().value; - if (size === '4') { - this.clearFontSize(); - } else { - this.base.execAction('fontSize', { size: size }); - } - }, - - handleFormClick: function (event) { - // make sure not to hide form when clicking inside the form - event.stopPropagation(); - }, - - handleSaveClick: function (event) { - // Clicking Save -> create the font size - event.preventDefault(); - this.doFormSave(); - }, - - handleCloseClick: function (event) { - // Click Close -> close the form - event.preventDefault(); - this.doFormCancel(); - } - }; - - FontSizeExtension = Util.derives(DefaultButton, FontSizeDerived); -}()); -var Button; -(function () { - 'use strict'; - - /*global Util, Extension */ - - Button = Extension.extend({ init: function () { - this.button = this.createButton(); - this.on(this.button, 'click', this.handleClick.bind(this)); - if (this.key) { - this.subscribe('editableKeydown', this.handleKeydown.bind(this)); - } - }, - - /* getButton: [function ()] - * - * If implemented, this function will be called when - * the toolbar is being created. The DOM Element returned - * by this function will be appended to the toolbar along - * with any other buttons. - */ - getButton: function () { - return this.button; - }, - - getAction: function () { - return (typeof this.action === 'function') ? this.action(this.base.options) : this.action; - }, - - getAria: function () { - return (typeof this.aria === 'function') ? this.aria(this.base.options) : this.aria; - }, - - getTagNames: function () { - return (typeof this.tagNames === 'function') ? this.tagNames(this.base.options) : this.tagNames; - }, - - createButton: function () { - var button = this.document.createElement('button'), - content = this.contentDefault, - ariaLabel = this.getAria(), - buttonLabels = this.getEditorOption('buttonLabels'); - button.classList.add('medium-editor-action'); - button.classList.add('medium-editor-action-' + this.name); - button.setAttribute('data-action', this.getAction()); - if (ariaLabel) { - button.setAttribute('title', ariaLabel); - button.setAttribute('aria-label', ariaLabel); - } - if (buttonLabels) { - if (buttonLabels === 'fontawesome' && this.contentFA) { - content = this.contentFA; - } else if (typeof buttonLabels === 'object' && buttonLabels[this.name]) { - content = buttonLabels[this.name]; - } - } - button.innerHTML = content; - return button; - }, - - handleKeydown: function (event) { - var action; - - if (Util.isKey(event, this.key.charCodeAt(0)) && Util.isMetaCtrlKey(event) && !event.shiftKey) { - event.preventDefault(); - event.stopPropagation(); - - action = this.getAction(); - if (action) { - this.execAction(action); - } - } - }, - - handleClick: function (event) { - event.preventDefault(); - event.stopPropagation(); - - var action = this.getAction(); - - if (action) { - this.execAction(action); - } - }, - - isActive: function () { - return this.button.classList.contains(this.getEditorOption('activeButtonClass')); - }, - - setInactive: function () { - this.button.classList.remove(this.getEditorOption('activeButtonClass')); - delete this.knownState; - }, - - setActive: function () { - this.button.classList.add(this.getEditorOption('activeButtonClass')); - delete this.knownState; - }, - - queryCommandState: function () { - var queryState = null; - if (this.useQueryState) { - queryState = this.base.queryCommandState(this.getAction()); - } - return queryState; - }, - - isAlreadyApplied: function (node) { - var isMatch = false, - tagNames = this.getTagNames(), - styleVals, - computedStyle; - - if (this.knownState === false || this.knownState === true) { - return this.knownState; - } - - if (tagNames && tagNames.length > 0 && node.tagName) { - isMatch = tagNames.indexOf(node.tagName.toLowerCase()) !== -1; - } - - if (!isMatch && this.style) { - styleVals = this.style.value.split('|'); - computedStyle = this.window.getComputedStyle(node, null).getPropertyValue(this.style.prop); - styleVals.forEach(function (val) { - if (!this.knownState) { - isMatch = (computedStyle.indexOf(val) !== -1); - // text-decoration is not inherited by default - // so if the computed style for text-decoration doesn't match - // don't write to knownState so we can fallback to other checks - if (isMatch || this.style.prop !== 'text-decoration') { - this.knownState = isMatch; - } - } - }, this); - } - - return isMatch; - } - }); -}()); - -var FormExtension; -(function () { - 'use strict'; - - /* global Button */ - - var noop = function () {}; - - /* Base functionality for an extension whcih will display - * a 'form' inside the toolbar - */ - FormExtension = Button.extend({ + Button.prototype.init.apply(this, arguments); + }, + // default labels for the form buttons formSaveLabel: '✓', formCloseLabel: '×', @@ -3410,7 +2586,40 @@ var FormExtension; * This function should hide the form element inside * the toolbar container */ - hideForm: noop + hideForm: noop, + + /************************ Helpers ************************ + * The following are helpers that are either set by MediumEditor + * during initialization, or are helper methods which either + * route calls to the MediumEditor instance or provide common + * functionality for all form extensions + *********************************************************/ + + /* hideToolbarDefaultActions: [function ()] + * + * Helper function which will hide the default contents of the + * toolbar, but leave the toolbar container in the same state + * to allow a form to display its custom contents inside the toolbar + */ + hideToolbarDefaultActions: function () { + var toolbar = this.base.getExtensionByName('toolbar'); + if (toolbar) { + toolbar.hideToolbarDefaultActions(); + } + }, + + /* setToolbarPosition: [function ()] + * + * Helper function which will update the size and position + * of the toolbar based on the toolbar content and the current + * position of the user's selection + */ + setToolbarPosition: function () { + var toolbar = this.base.getExtensionByName('toolbar'); + if (toolbar) { + toolbar.setToolbarPosition(); + } + } }); })(); var AnchorForm; @@ -3462,7 +2671,12 @@ var AnchorForm; tagNames: ['a'], contentDefault: '#', contentFA: '', - key: 'k', + + init: function () { + FormExtension.prototype.init.apply(this, arguments); + + this.subscribe('editableKeydown', this.handleKeydown.bind(this)); + }, // Called when the button the toolbar is clicked // Overrides ButtonExtension.handleClick @@ -3484,9 +2698,8 @@ var AnchorForm; }, // Called when user hits the defined shortcut (CTRL / COMMAND + K) - // Overrides Button.handleKeydown handleKeydown: function (event) { - if (Util.isKey(event, this.key.charCodeAt(0)) && Util.isMetaCtrlKey(event)) { + if (Util.isKey(event, Util.keyCode.K) && Util.isMetaCtrlKey(event) && !event.shiftKey) { this.handleClick(event); } }, @@ -3557,9 +2770,9 @@ var AnchorForm; var input = this.getInput(); this.base.saveSelection(); - this.base.hideToolbarDefaultActions(); + this.hideToolbarDefaultActions(); this.getForm().style.display = 'block'; - this.base.setToolbarPosition(); + this.setToolbarPosition(); input.value = linkValue || ''; input.focus(); @@ -3578,11 +2791,6 @@ var AnchorForm; delete this.form; }, - // TODO: deprecate - deactivate: function () { - Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0'); - }, - // core methods getFormOpts: function () { @@ -3721,18 +2929,10 @@ var AnchorPreview; */ previewValueSelector: 'a', - /* ----- internal options needed from base ----- */ - diffLeft: 0, // deprecated (should use .getEditorOption() instead) - diffTop: -10, // deprecated (should use .getEditorOption() instead) - elementsContainer: false, // deprecated (should use .getEditorOption() instead) - init: function () { this.anchorPreview = this.createPreview(); - if (!this.elementsContainer) { - this.elementsContainer = this.document.body; - } - this.elementsContainer.appendChild(this.anchorPreview); + this.getEditorOption('elementsContainer').appendChild(this.anchorPreview); this.attachToEditables(); }, @@ -3768,11 +2968,6 @@ var AnchorPreview; } }, - // TODO: deprecate - deactivate: function () { - Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0'); - }, - hidePreview: function () { this.anchorPreview.classList.remove('medium-editor-anchor-preview-active'); this.activeAnchor = null; @@ -3808,13 +3003,20 @@ var AnchorPreview; var buttonHeight = this.anchorPreview.offsetHeight, boundary = this.activeAnchor.getBoundingClientRect(), middleBoundary = (boundary.left + boundary.right) / 2, + diffLeft = this.diffLeft, + diffTop = this.diffTop, halfOffsetWidth, defaultLeft; halfOffsetWidth = this.anchorPreview.offsetWidth / 2; - defaultLeft = this.diffLeft - halfOffsetWidth; + var toolbarExtension = this.base.getExtensionByName('toolbar'); + if (toolbarExtension) { + diffLeft = toolbarExtension.diffLeft; + diffTop = toolbarExtension.diffTop; + } + defaultLeft = diffLeft - halfOffsetWidth; - this.anchorPreview.style.top = Math.round(buttonHeight + boundary.bottom - this.diffTop + this.window.pageYOffset - this.anchorPreview.offsetHeight) + 'px'; + this.anchorPreview.style.top = Math.round(buttonHeight + boundary.bottom - diffTop + this.window.pageYOffset - this.anchorPreview.offsetHeight) + 'px'; if (middleBoundary < halfOffsetWidth) { this.anchorPreview.style.left = defaultLeft + halfOffsetWidth + 'px'; } else if ((this.window.innerWidth - middleBoundary) < halfOffsetWidth) { @@ -3890,7 +3092,6 @@ var AnchorPreview; // if the mouse has not left the anchor tag in that time this.base.delay(function () { if (this.anchorToPreview) { - //this.activeAnchor = this.anchorToPreview; this.showPreview(this.anchorToPreview); } }.bind(this)); @@ -3983,6 +3184,8 @@ LINK_REGEXP_TEXT = AutoLink = Extension.extend({ init: function () { + Extension.prototype.init.apply(this, arguments); + this.disableEventHandling = false; this.subscribe('editableKeypress', this.onKeypress.bind(this)); this.subscribe('editableBlur', this.onBlur.bind(this)); @@ -4199,6 +3402,8 @@ var ImageDragging; ImageDragging = Extension.extend({ init: function () { + Extension.prototype.init.apply(this, arguments); + this.subscribe('editableDrag', this.handleDrag.bind(this)); this.subscribe('editableDrop', this.handleDrop.bind(this)); }, @@ -4232,7 +3437,7 @@ var ImageDragging; fileReader.readAsDataURL(file); id = 'medium-img-' + (+new Date()); - Util.insertHTMLCommand(this.document, ''); + Util.insertHTMLCommand(this.document, ''); fileReader.onload = function () { var img = this.document.getElementById(id); @@ -4250,11 +3455,85 @@ var ImageDragging; }); }()); +var KeyboardCommands; +(function () { + 'use strict'; + + /*global Extension, Util */ + + KeyboardCommands = Extension.extend({ + name: 'keyboard-commands', + + /* KeyboardCommands Options */ + + /* commands: [Array] + * Array of objects describing each command and the combination of keys that will trigger it + * Required for each object: + * command [String] (argument passed to editor.execAction()) + * key [String] (keyboard character that triggers this command) + * meta [boolean] (whether the ctrl/meta key has to be active or inactive) + * shift [boolean] (whether the shift key has to be active or inactive) + */ + commands: [ + { + command: 'bold', + key: 'b', + meta: true, + shift: false + }, + { + command: 'italic', + key: 'i', + meta: true, + shift: false + }, + { + command: 'underline', + key: 'u', + meta: true, + shift: false + } + ], + + init: function () { + Extension.prototype.init.apply(this, arguments); + + this.subscribe('editableKeydown', this.handleKeydown.bind(this)); + this.keys = {}; + this.commands.forEach(function (command) { + var keyCode = command.key.charCodeAt(0); + if (!this.keys[keyCode]) { + this.keys[keyCode] = []; + } + this.keys[keyCode].push(command); + }, this); + }, + + handleKeydown: function (event) { + var keyCode = Util.getKeyCode(event); + if (!this.keys[keyCode]) { + return; + } + + var isMeta = Util.isMetaCtrlKey(event), + isShift = !!event.shiftKey; + this.keys[keyCode].forEach(function (data) { + if (data.meta === isMeta && + data.shift === isShift) { + event.preventDefault(); + event.stopPropagation(); + this.execAction(data.command); + } + }, this); + } + }); +}()); + var FontSizeForm; (function () { 'use strict'; - /*global FormExtension, Selection, Util */ + /*global FormExtension, Selection */ FontSizeForm = FormExtension.extend({ @@ -4264,6 +3543,10 @@ var FontSizeForm; contentDefault: '±', // ± contentFA: '', + init: function () { + FormExtension.prototype.init.apply(this, arguments); + }, + // Called when the button the toolbar is clicked // Overrides ButtonExtension.handleClick handleClick: function (evt) { @@ -4301,9 +3584,9 @@ var FontSizeForm; var input = this.getInput(); this.base.saveSelection(); - this.base.hideToolbarDefaultActions(); + this.hideToolbarDefaultActions(); this.getForm().style.display = 'block'; - this.base.setToolbarPosition(); + this.setToolbarPosition(); input.value = fontSize || ''; input.focus(); @@ -4322,11 +3605,6 @@ var FontSizeForm; delete this.form; }, - // TODO: deprecate - deactivate: function () { - Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0'); - }, - // core methods doFormSave: function () { @@ -4508,11 +3786,9 @@ var PasteHandler; */ cleanTags: ['meta'], - /* ----- internal options needed from base ----- */ - targetBlank: false, // deprecated (should use .getEditorOption() instead) - disableReturn: false, // deprecated (should use .getEditorOption() instead) - init: function () { + Extension.prototype.init.apply(this, arguments); + if (this.forcePlainText || this.cleanPastedHTML) { this.subscribe('editablePaste', this.handlePaste.bind(this)); } @@ -4550,7 +3826,7 @@ var PasteHandler; return this.cleanPaste(pastedHTML); } - if (!(this.disableReturn || element.getAttribute('data-disable-return'))) { + if (!(this.getEditorOption('disableReturn') || element.getAttribute('data-disable-return'))) { paragraphs = pastedPlain.split(/[\r\n]+/g); // If there are no \r\n in data, don't wrap in

if (paragraphs.length > 1) { @@ -4634,7 +3910,7 @@ var PasteHandler; for (i = 0; i < elList.length; i += 1) { workEl = elList[i]; - if ('a' === workEl.tagName.toLowerCase() && this.targetBlank) { + if ('a' === workEl.tagName.toLowerCase() && this.getEditorOption('targetBlank')) { Util.setTargetBlank(workEl); } @@ -4740,6 +4016,8 @@ var Placeholder; hideOnClick: true, init: function () { + Extension.prototype.init.apply(this, arguments); + this.initPlaceholders(); this.attachEventHandlers(); }, @@ -4819,36 +4097,108 @@ var Placeholder; }()); var Toolbar; - (function () { 'use strict'; - Toolbar = function (instance) { - this.base = instance; - this.options = instance.options; + /*global Util, Selection, Extension */ - this.initThrottledMethods(); - }; + Toolbar = Extension.extend({ + name: 'toolbar', + + /* Toolbar Options */ + + /* align: ['left'|'center'|'right'] + * When the __static__ option is true, this aligns the static toolbar + * relative to the medium-editor element. + */ + align: 'center', + + /* buttons: [Array] + * the names of the set of buttons to display on the toolbar. + */ + buttons: ['bold', 'italic', 'underline', 'anchor', 'header1', 'header2', 'quote'], + + /* diffLeft: [Number] + * value in pixels to be added to the X axis positioning of the toolbar. + */ + diffLeft: 0, + + /* diffTop: [Number] + * value in pixels to be added to the Y axis positioning of the toolbar. + */ + diffTop: -10, + + /* firstButtonClass: [string] + * CSS class added to the first button in the toolbar. + */ + firstButtonClass: 'medium-editor-button-first', + + /* lastButtonClass: [string] + * CSS class added to the last button in the toolbar. + */ + lastButtonClass: 'medium-editor-button-last', + + /* standardizeSelectionStart: [boolean] + * enables/disables standardizing how the beginning of a range is decided + * between browsers whenever the selected text is analyzed for updating toolbar buttons status. + */ + standardizeSelectionStart: false, + + /* static: [boolean] + * enable/disable the toolbar always displaying in the same location + * relative to the medium-editor element. + */ + static: false, + + /* sticky: [boolean] + * When the __static__ option is true, this enables/disables the toolbar + * "sticking" to the viewport and staying visible on the screen while + * the page scrolls. + */ + sticky: false, + + /* updateOnEmptySelection: [boolean] + * When the __static__ option is true, this enables/disables updating + * the state of the toolbar buttons even when the selection is collapsed + * (there is no selection, just a cursor). + */ + updateOnEmptySelection: false, + + init: function () { + Extension.prototype.init.apply(this, arguments); + + this.initThrottledMethods(); + this.getEditorOption('elementsContainer').appendChild(this.getToolbarElement()); + }, + + // Helper method to execute method for every extension, but ignoring the toolbar extension + forEachExtension: function (iterator, context) { + return this.base.extensions.forEach(function (command) { + if (command === this) { + return; + } + return iterator.apply(context || this, arguments); + }, this); + }, - Toolbar.prototype = { // Toolbar creation/deletion createToolbar: function () { - var toolbar = this.base.options.ownerDocument.createElement('div'); + var toolbar = this.document.createElement('div'); - toolbar.id = 'medium-editor-toolbar-' + this.base.id; + toolbar.id = 'medium-editor-toolbar-' + this.getEditorId(); toolbar.className = 'medium-editor-toolbar'; - if (this.options.staticToolbar) { + if (this.static) { toolbar.className += ' static-toolbar'; } else { - toolbar.className += ' stalker-toolbar'; + toolbar.className += ' medium-editor-stalker-toolbar'; } toolbar.appendChild(this.createToolbarButtons()); // Add any forms that extensions may have - this.base.commands.forEach(function (extension) { + this.forEachExtension(function (extension) { if (extension.hasForm) { toolbar.appendChild(extension.getForm()); } @@ -4860,21 +4210,27 @@ var Toolbar; }, createToolbarButtons: function () { - var ul = this.base.options.ownerDocument.createElement('ul'), + var ul = this.document.createElement('ul'), li, btn, buttons, extension; - ul.id = 'medium-editor-toolbar-actions' + this.base.id; - ul.className = 'medium-editor-toolbar-actions clearfix'; + ul.id = 'medium-editor-toolbar-actions' + this.getEditorId(); + ul.className = 'medium-editor-toolbar-actions'; ul.style.display = 'block'; - this.base.options.buttons.forEach(function (button) { + this.buttons.forEach(function (button) { extension = this.base.getExtensionByName(button); - if (typeof extension.getButton === 'function') { + + if (!extension) { + // If button hasn't been passed as an extension, create it + extension = this.base.addBuiltInExtension(button); + } + + if (extension && typeof extension.getButton === 'function') { btn = extension.getButton(this.base); - li = this.base.options.ownerDocument.createElement('li'); + li = this.document.createElement('li'); if (Util.isElement(btn)) { li.appendChild(btn); } else { @@ -4882,12 +4238,12 @@ var Toolbar; } ul.appendChild(li); } - }.bind(this)); + }, this); buttons = ul.querySelectorAll('button'); if (buttons.length > 0) { - buttons[0].classList.add(this.options.firstButtonClass); - buttons[buttons.length - 1].classList.add(this.options.lastButtonClass); + buttons[0].classList.add(this.firstButtonClass); + buttons[buttons.length - 1].classList.add(this.lastButtonClass); } return ul; @@ -4902,11 +4258,6 @@ var Toolbar; } }, - // TODO: deprecate - deactivate: function () { - Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0'); - }, - // Toolbar accessors getToolbarElement: function () { @@ -4936,24 +4287,24 @@ var Toolbar; attachEventHandlers: function () { // MediumEditor custom events for when user beings and ends interaction with a contenteditable and its elements - this.base.subscribe('blur', this.handleBlur.bind(this)); - this.base.subscribe('focus', this.handleFocus.bind(this)); + this.subscribe('blur', this.handleBlur.bind(this)); + this.subscribe('focus', this.handleFocus.bind(this)); // Updating the state of the toolbar as things change - this.base.subscribe('editableClick', this.handleEditableClick.bind(this)); - this.base.subscribe('editableKeyup', this.handleEditableKeyup.bind(this)); + this.subscribe('editableClick', this.handleEditableClick.bind(this)); + this.subscribe('editableKeyup', this.handleEditableKeyup.bind(this)); // Handle mouseup on document for updating the selection in the toolbar - this.base.on(this.options.ownerDocument.documentElement, 'mouseup', this.handleDocumentMouseup.bind(this)); + this.on(this.document.documentElement, 'mouseup', this.handleDocumentMouseup.bind(this)); // Add a scroll event for sticky toolbar - if (this.options.staticToolbar && this.options.stickyToolbar) { + if (this.static && this.sticky) { // On scroll (capture), re-position the toolbar - this.base.on(this.options.contentWindow, 'scroll', this.handleWindowScroll.bind(this), true); + this.on(this.window, 'scroll', this.handleWindowScroll.bind(this), true); } // On resize, re-position the toolbar - this.base.on(this.options.contentWindow, 'resize', this.handleWindowResize.bind(this)); + this.on(this.window, 'resize', this.handleWindowResize.bind(this)); }, handleWindowScroll: function () { @@ -5014,31 +4365,14 @@ var Toolbar; clearTimeout(this.hideTimeout); if (!this.isDisplayed()) { this.getToolbarElement().classList.add('medium-editor-toolbar-active'); - this.base.trigger('showToolbar', {}, this.base.getFocusedElement()); - - if (typeof this.options.onShowToolbar === 'function') { - Util.deprecated('onShowToolbar', 'the showToolbar custom event', 'v5.0.0'); - this.options.onShowToolbar(); - } + this.trigger('showToolbar', {}, this.base.getFocusedElement()); } }, hideToolbar: function () { if (this.isDisplayed()) { this.getToolbarElement().classList.remove('medium-editor-toolbar-active'); - this.base.trigger('hideToolbar', {}, this.base.getFocusedElement()); - - this.base.commands.forEach(function (extension) { - if (typeof extension.onHide === 'function') { - Util.deprecated('onHide', 'the hideToolbar custom event', 'v5.0.0'); - extension.onHide(); - } - }); - - if (typeof this.options.onHideToolbar === 'function') { - Util.deprecated('onHideToolbar', 'the hideToolbar custom event', 'v5.0.0'); - this.options.onHideToolbar(); - } + this.trigger('hideToolbar', {}, this.base.getFocusedElement()); } }, @@ -5068,7 +4402,7 @@ var Toolbar; hideExtensionForms: function () { // Hide all extension forms - this.base.commands.forEach(function (extension) { + this.forEachExtension(function (extension) { if (extension.hasForm && extension.isDisplayed()) { extension.hideForm(); } @@ -5080,7 +4414,7 @@ var Toolbar; // Checks for existance of multiple block elements in the current selection multipleBlockElementsSelected: function () { /*jslint regexp: true*/ - var selectionHtml = Selection.getSelectionHtml.call(this).replace(/<[\S]+><\/[\S]+>/gim, ''), + var selectionHtml = Selection.getSelectionHtml(this.document).replace(/<[\S]+><\/[\S]+>/gim, ''), hasMultiParagraphs = selectionHtml.match(/<(p|h[1-6]|blockquote)[^>]*>/g); /*jslint regexp: false*/ @@ -5088,7 +4422,7 @@ var Toolbar; }, modifySelection: function () { - var selection = this.options.contentWindow.getSelection(), + var selection = this.window.getSelection(), selectionRange = selection.getRangeAt(0); /* @@ -5107,16 +4441,16 @@ var Toolbar; * So, for cases where the selectionRange start is at the end of an element/node, find the next * adjacent text node that actually has content in it, and move the selectionRange start there. */ - if (this.options.standardizeSelectionStart && + if (this.standardizeSelectionStart && selectionRange.startContainer.nodeValue && (selectionRange.startOffset === selectionRange.startContainer.nodeValue.length)) { - var adjacentNode = Util.findAdjacentTextNodeWithContent(Selection.getSelectionElement(this.options.contentWindow), selectionRange.startContainer, this.options.ownerDocument); + var adjacentNode = Util.findAdjacentTextNodeWithContent(Selection.getSelectionElement(this.window), selectionRange.startContainer, this.document); if (adjacentNode) { var offset = 0; while (adjacentNode.nodeValue.substr(offset, 1).trim().length === 0) { offset = offset + 1; } - var newRange = this.options.ownerDocument.createRange(); + var newRange = this.document.createRange(); newRange.setStart(adjacentNode, offset); newRange.setEnd(selectionRange.endContainer, selectionRange.endOffset); selection.removeAllRanges(); @@ -5134,16 +4468,16 @@ var Toolbar; // If no editable has focus OR selection is inside contenteditable = false // hide toolbar if (!this.base.getFocusedElement() || - Selection.selectionInContentEditableFalse(this.options.contentWindow)) { + Selection.selectionInContentEditableFalse(this.window)) { return this.hideToolbar(); } // If there's no selection element, selection element doesn't belong to this editor // or toolbar is disabled for this selection element // hide toolbar - var selectionElement = Selection.getSelectionElement(this.options.contentWindow); + var selectionElement = Selection.getSelectionElement(this.window); if (!selectionElement || - this.base.elements.indexOf(selectionElement) === -1 || + this.getEditorElements().indexOf(selectionElement) === -1 || selectionElement.getAttribute('data-disable-toolbar')) { return this.hideToolbar(); } @@ -5151,41 +4485,36 @@ var Toolbar; // Now we know there's a focused editable with a selection // If the updateOnEmptySelection option is true, show the toolbar - if (this.options.updateOnEmptySelection && this.options.staticToolbar) { + if (this.updateOnEmptySelection && this.static) { return this.showAndUpdateToolbar(); } // If we don't have a 'valid' selection -> hide toolbar - if (this.options.contentWindow.getSelection().toString().trim() === '' || - (this.options.allowMultiParagraphSelection === false && this.multipleBlockElementsSelected())) { + if (this.window.getSelection().toString().trim() === '' || + (this.getEditorOption('allowMultiParagraphSelection') === false && this.multipleBlockElementsSelected())) { return this.hideToolbar(); } this.showAndUpdateToolbar(); }, - // leaving here backward compatibility / statics - getFocusedElement: function () { - return this.base.getFocusedElement(); - }, - // Updating the toolbar showAndUpdateToolbar: function () { this.modifySelection(); this.setToolbarButtonStates(); - this.base.trigger('positionToolbar', {}, this.base.getFocusedElement()); + this.trigger('positionToolbar', {}, this.base.getFocusedElement()); this.showToolbarDefaultActions(); this.setToolbarPosition(); }, setToolbarButtonStates: function () { - this.base.commands.forEach(function (extension) { + this.forEachExtension(function (extension) { if (typeof extension.isActive === 'function' && typeof extension.setInactive === 'function') { extension.setInactive(); } - }.bind(this)); + }); this.checkActiveButtons(); }, @@ -5193,7 +4522,7 @@ var Toolbar; checkActiveButtons: function () { var manualStateChecks = [], queryState = null, - selectionRange = Selection.getSelectionRange(this.options.ownerDocument), + selectionRange = Selection.getSelectionRange(this.document), parentNode, updateExtensionState = function (extension) { if (typeof extension.checkState === 'function') { @@ -5213,30 +4542,30 @@ var Toolbar; parentNode = Selection.getSelectedParentElement(selectionRange); - // Loop through all commands - this.base.commands.forEach(function (command) { - // For those commands where we can use document.queryCommandState(), do so - if (typeof command.queryCommandState === 'function') { - queryState = command.queryCommandState(); + // Loop through all extensions + this.forEachExtension(function (extension) { + // For those extensions where we can use document.queryCommandState(), do so + if (typeof extension.queryCommandState === 'function') { + queryState = extension.queryCommandState(); // If queryCommandState returns a valid value, we can trust the browser // and don't need to do our manual checks if (queryState !== null) { - if (queryState && typeof command.setActive === 'function') { - command.setActive(); + if (queryState && typeof extension.setActive === 'function') { + extension.setActive(); } return; } } - // We can't use queryCommandState for this command, so add to manualStateChecks - manualStateChecks.push(command); + // We can't use queryCommandState for this extension, so add to manualStateChecks + manualStateChecks.push(extension); }); - // Climb up the DOM and do manual checks for whether a certain command is currently enabled for this node + // Climb up the DOM and do manual checks for whether a certain extension is currently enabled for this node while (parentNode.tagName !== undefined && Util.parentElements.indexOf(parentNode.tagName.toLowerCase) === -1) { manualStateChecks.forEach(updateExtensionState); // we can abort the search upwards if we leave the contentEditable element - if (this.base.elements.indexOf(parentNode) !== -1) { + if (this.getEditorElements().indexOf(parentNode) !== -1) { break; } parentNode = parentNode.parentNode; @@ -5253,7 +4582,7 @@ var Toolbar; setToolbarPosition: function () { var container = this.base.getFocusedElement(), - selection = this.options.contentWindow.getSelection(), + selection = this.window.getSelection(), anchorPreview; // If there isn't a valid selection, bail @@ -5261,7 +4590,7 @@ var Toolbar; return this; } - if (this.options.staticToolbar) { + if (this.static) { this.showToolbar(); this.positionStaticToolbar(container); } else if (!selection.isCollapsed) { @@ -5281,8 +4610,8 @@ var Toolbar; this.getToolbarElement().style.left = '0'; // document.documentElement for IE 9 - var scrollTop = (this.options.ownerDocument.documentElement && this.options.ownerDocument.documentElement.scrollTop) || this.options.ownerDocument.body.scrollTop, - windowWidth = this.options.contentWindow.innerWidth, + var scrollTop = (this.document.documentElement && this.document.documentElement.scrollTop) || this.document.body.scrollTop, + windowWidth = this.window.innerWidth, toolbarElement = this.getToolbarElement(), containerRect = container.getBoundingClientRect(), containerTop = containerRect.top + scrollTop, @@ -5292,27 +4621,27 @@ var Toolbar; halfOffsetWidth = toolbarWidth / 2, targetLeft; - if (this.options.stickyToolbar) { + if (this.sticky) { // If it's beyond the height of the editor, position it at the bottom of the editor if (scrollTop > (containerTop + container.offsetHeight - toolbarHeight)) { toolbarElement.style.top = (containerTop + container.offsetHeight - toolbarHeight) + 'px'; - toolbarElement.classList.remove('sticky-toolbar'); + toolbarElement.classList.remove('medium-editor-sticky-toolbar'); // Stick the toolbar to the top of the window } else if (scrollTop > (containerTop - toolbarHeight)) { - toolbarElement.classList.add('sticky-toolbar'); + toolbarElement.classList.add('medium-editor-sticky-toolbar'); toolbarElement.style.top = '0px'; // Normal static toolbar position } else { - toolbarElement.classList.remove('sticky-toolbar'); + toolbarElement.classList.remove('medium-editor-sticky-toolbar'); toolbarElement.style.top = containerTop - toolbarHeight + 'px'; } } else { toolbarElement.style.top = containerTop - toolbarHeight + 'px'; } - switch (this.options.toolbarAlign) { + switch (this.align) { case 'left': targetLeft = containerRect.left; break; @@ -5339,7 +4668,7 @@ var Toolbar; // position the toolbar at left 0, so we can get the real width of the toolbar this.getToolbarElement().style.left = '0'; - var windowWidth = this.options.contentWindow.innerWidth, + var windowWidth = this.window.innerWidth, range = selection.getRangeAt(0), boundary = range.getBoundingClientRect(), middleBoundary = (boundary.left + boundary.right) / 2, @@ -5348,16 +4677,16 @@ var Toolbar; toolbarWidth = toolbarElement.offsetWidth, halfOffsetWidth = toolbarWidth / 2, buttonHeight = 50, - defaultLeft = this.options.diffLeft - halfOffsetWidth; + defaultLeft = this.diffLeft - halfOffsetWidth; if (boundary.top < buttonHeight) { toolbarElement.classList.add('medium-toolbar-arrow-over'); toolbarElement.classList.remove('medium-toolbar-arrow-under'); - toolbarElement.style.top = buttonHeight + boundary.bottom - this.options.diffTop + this.options.contentWindow.pageYOffset - toolbarHeight + 'px'; + toolbarElement.style.top = buttonHeight + boundary.bottom - this.diffTop + this.window.pageYOffset - toolbarHeight + 'px'; } else { toolbarElement.classList.add('medium-toolbar-arrow-under'); toolbarElement.classList.remove('medium-toolbar-arrow-over'); - toolbarElement.style.top = boundary.top + this.options.diffTop + this.options.contentWindow.pageYOffset - toolbarHeight + 'px'; + toolbarElement.style.top = boundary.top + this.diffTop + this.window.pageYOffset - toolbarHeight + 'px'; } if (middleBoundary < halfOffsetWidth) { @@ -5368,7 +4697,7 @@ var Toolbar; toolbarElement.style.left = defaultLeft + middleBoundary + 'px'; } } - }; + }); }()); var extensionDefaults; @@ -5384,8 +4713,10 @@ var extensionDefaults; autoLink: AutoLink, fontSize: FontSizeForm, imageDragging: ImageDragging, + keyboardCommands: KeyboardCommands, paste: PasteHandler, - placeholder: Placeholder + placeholder: Placeholder, + toolbar: Toolbar }; })(); @@ -5526,7 +4857,7 @@ function MediumEditor(elements, options) { return; } - if (node.getAttribute('data-medium-element') && node.children.length === 0) { + if (node.getAttribute('data-medium-editor-element') && node.children.length === 0) { this.options.ownerDocument.execCommand('formatBlock', false, 'p'); } @@ -5546,6 +4877,37 @@ function MediumEditor(elements, options) { // Internal helper methods which shouldn't be exposed externally + function addToEditors(win) { + if (!win._mediumEditors) { + // To avoid breaking users who are assuming that the unique id on + // medium-editor elements will start at 1, inserting a 'null' in the + // array so the unique-id can always map to the index of the editor instance + win._mediumEditors = [null]; + } + + // If this already has a unique id, re-use it + if (!this.id) { + this.id = win._mediumEditors.length; + } + + win._mediumEditors[this.id] = this; + } + + function removeFromEditors(win) { + if (!win._mediumEditors || !win._mediumEditors[this.id]) { + return; + } + + /* Setting the instance to null in the array instead of deleting it allows: + * 1) Each instance to preserve its own unique-id, even after being destroyed + * and initialized again + * 2) The unique-id to always correspond to an index in the array of medium-editor + * instances. Thus, we will be able to look at a contenteditable, and determine + * which instance it belongs to, by indexing into the global array. + */ + win._mediumEditors[this.id] = null; + } + function createElementsArray(selector) { if (!selector) { selector = []; @@ -5582,25 +4944,18 @@ function MediumEditor(elements, options) { } function initExtension(extension, name, instance) { - if (typeof extension.parent !== 'undefined') { - Util.warn('Extension .parent property has been deprecated. ' + - 'The .base property for extensions will always be set to MediumEditor in version 5.0.0'); - } var extensionDefaults = { 'window': instance.options.contentWindow, - 'document': instance.options.ownerDocument + 'document': instance.options.ownerDocument, + 'base': instance }; - // TODO: Deprecated (Remove .parent check in v5.0.0) - if (extension.parent !== false) { - extensionDefaults.base = instance; - } + // Add default options into the extension extension = setExtensionDefaults(extension, extensionDefaults); // Call init on the extension if (typeof extension.init === 'function') { - // Passing instance into init() will be deprecated in v5.0.0 - extension.init(instance); + extension.init(); } // Set extension name (if not already set) @@ -5610,67 +4965,43 @@ function MediumEditor(elements, options) { return extension; } - function shouldAddDefaultAnchorPreview() { - var i, - shouldAdd = false; - - // TODO: deprecated - // If anchor-preview is disabled, don't add - if (this.options.disableAnchorPreview) { - return false; - } - // If anchor-preview is disabled, don't add - if (this.options.anchorPreview === false) { - return false; - } - // If anchor-preview extension has been overriden, don't add - if (this.options.extensions['anchor-preview']) { - return false; - } - // If toolbar is disabled, don't add - if (this.options.disableToolbar) { + function isToolbarEnabled() { + // If any of the elements don't have the toolbar disabled + // We need a toolbar + if (this.elements.every(function (element) { + return !!element.getAttribute('data-disable-toolbar'); + })) { return false; } - // If all elements have 'data-disable-toolbar' attribute, don't add - for (i = 0; i < this.elements.length; i += 1) { - if (!this.elements[i].getAttribute('data-disable-toolbar')) { - shouldAdd = true; - break; - } - } - return shouldAdd; + return this.options.toolbar !== false; } - function shouldAddDefaultPlaceholder() { - if (this.options.extensions['placeholder']) { + function isAnchorPreviewEnabled() { + // If toolbar is disabled, don't add + if (!isToolbarEnabled.call(this)) { return false; } - // TODO: deprecated - if (this.options.disablePlaceholders) { - return false; - } + return this.options.anchorPreview !== false; + } + function isPlaceholderEnabled() { return this.options.placeholder !== false; } - function shouldAddDefaultAutoLink() { - if (this.options.extensions['auto-link']) { - return false; - } - + function isAutoLinkEnabled() { return this.options.autoLink !== false; } - function shouldAddDefaultImageDragging() { - if (this.options.extensions['image-dragging']) { - return false; - } - + function isImageDraggingEnabled() { return this.options.imageDragging !== false; } + function isKeyboardCommandsEnabled() { + return this.options.keyboardCommands !== false; + } + function createContentEditable(textarea) { var div = this.options.ownerDocument.createElement('div'), id = (+new Date()), @@ -5710,7 +5041,7 @@ function MediumEditor(elements, options) { element.setAttribute('contentEditable', true); element.setAttribute('spellcheck', this.options.spellcheck); } - element.setAttribute('data-medium-element', true); + element.setAttribute('data-medium-editor-element', true); element.setAttribute('role', 'textbox'); element.setAttribute('aria-multiline', true); element.setAttribute('medium-editor-index', index); @@ -5727,21 +5058,6 @@ function MediumEditor(elements, options) { }, this); } - function initToolbar() { - if (this.toolbar || this.options.disableToolbar) { - return false; - } - - var addToolbar = this.elements.some(function (element) { - return !element.getAttribute('data-disable-toolbar'); - }); - - if (addToolbar) { - this.toolbar = new Toolbar(this); - this.options.elementsContainer.appendChild(this.toolbar.getToolbarElement()); - } - } - function attachHandlers() { var i; @@ -5775,141 +5091,59 @@ function MediumEditor(elements, options) { } } - function initPlaceholder(options) { - // Backwards compatability - var defaultsBC = { - text: (typeof this.options.placeholder === 'string') ? this.options.placeholder : undefined // deprecated - }; - - return new MediumEditor.extensions.placeholder( - Util.extend({}, options, defaultsBC) - ); - } - - function initAnchorPreview(options) { - // Backwards compatability - var defaultsBC = { - hideDelay: this.options.anchorPreviewHideDelay, // deprecated - diffLeft: this.options.diffLeft, // deprecated (should use .getEditorOption() instead) - diffTop: this.options.diffTop, // deprecated (should use .getEditorOption() instead) - elementsContainer: this.options.elementsContainer // deprecated (should use .getEditorOption() instead) - }; - - return new MediumEditor.extensions.anchorPreview( - Util.extend({}, options, defaultsBC) - ); - } - - function initAnchorForm(options) { - // Backwards compatability - var defaultsBC = { - customClassOption: this.options.anchorButton ? (this.options.anchorButtonClass || 'btn') : undefined, // deprecated - linkValidation: this.options.checkLinkFormat, //deprecated - placeholderText: this.options.anchorInputPlaceholder, // deprecated - targetCheckbox: this.options.anchorTarget, // deprecated - targetCheckboxText: this.options.anchorInputCheckboxLabel // deprecated - }; - - return new MediumEditor.extensions.anchor( - Util.extend({}, options, defaultsBC) - ); - } - - function initPasteHandler(options) { - // Backwards compatability - var defaultsBC = { - forcePlainText: this.options.forcePlainText, // deprecated - cleanPastedHTML: this.options.cleanPastedHTML, // deprecated - disableReturn: this.options.disableReturn, // deprecated (should use .getEditorOption() instead) - targetBlank: this.options.targetBlank // deprecated (should use .getEditorOption() instead) - }; + function initExtensions() { - return new MediumEditor.extensions.paste( - Util.extend({}, options, defaultsBC) - ); - } + this.extensions = []; - function initCommands() { - var buttons = this.options.buttons, - extensions = this.options.extensions, - ext, - name; - this.commands = []; - - buttons.forEach(function (buttonName) { - if (extensions[buttonName]) { - ext = initExtension(extensions[buttonName], buttonName, this); - this.commands.push(ext); - } else if (buttonName === 'anchor') { - ext = initExtension(initAnchorForm.call(this, this.options.anchor), 'anchor', this); - this.commands.push(ext); - } else if (buttonName === 'fontsize') { - ext = initExtension(new MediumEditor.extensions.fontSize(), buttonName, this); - this.commands.push(ext); - } else if (ButtonsData.hasOwnProperty(buttonName)) { - ext = initExtension(new MediumEditor.extensions.button(ButtonsData[buttonName]), buttonName, this); - this.commands.push(ext); + // Passed in extensions + Object.keys(this.options.extensions).forEach(function (name) { + // Always save the toolbar extension for last + if (name !== 'toolbar' && this.options.extensions[name]) { + this.extensions.push(initExtension(this.options.extensions[name], name, this)); } }, this); - for (name in extensions) { - if (extensions.hasOwnProperty(name) && buttons.indexOf(name) === -1) { - ext = initExtension(extensions[name], name, this); - this.commands.push(ext); + // Built-in extensions + var builtIns = { + paste: true, + anchorPreview: isAnchorPreviewEnabled.call(this), + autoLink: isAutoLinkEnabled.call(this), + imageDragging: isImageDraggingEnabled.call(this), + keyboardCommands: isKeyboardCommandsEnabled.call(this), + placeholder: isPlaceholderEnabled.call(this) + }; + Object.keys(builtIns).forEach(function (name) { + if (builtIns[name]) { + this.addBuiltInExtension(name); } - } - - // Only add default paste extension if it wasn't overriden - if (!this.options.extensions['paste']) { - this.commands.push(initExtension(initPasteHandler.call(this, this.options.paste), 'paste', this)); - } - - // Add AnchorPreview as extension if needed - if (shouldAddDefaultAnchorPreview.call(this)) { - this.commands.push(initExtension(initAnchorPreview.call(this, this.options.anchorPreview), 'anchor-preview', this)); - } - - if (shouldAddDefaultAutoLink.call(this)) { - this.commands.push(initExtension(new MediumEditor.extensions.autoLink(), 'auto-link', this)); - } + }, this); - if (shouldAddDefaultImageDragging.call(this)) { - this.commands.push(initExtension(new MediumEditor.extensions.imageDragging(), 'image-dragging', this)); + // Users can pass in a custom toolbar extension + // so check for that first and if it's not present + // just create the default toolbar + var toolbarExtension = this.options.extensions['toolbar']; + if (!toolbarExtension && isToolbarEnabled.call(this)) { + toolbarExtension = new MediumEditor.extensions.toolbar(this.options.toolbar); } - if (shouldAddDefaultPlaceholder.call(this)) { - var placeholderOpts = (typeof this.options.placeholder === 'string') ? {} : this.options.placeholder; - this.commands.push(initExtension(initPlaceholder.call(this, placeholderOpts), 'placeholder', this)); + // If the toolbar is not disabled, so we actually have an extension + // initialize it and add it to the extensions array + if (toolbarExtension) { + this.extensions.push(initExtension(toolbarExtension, 'toolbar', this)); } } function mergeOptions(defaults, options) { var deprecatedProperties = [ - ['forcePlainText', 'paste.forcePlainText'], - ['cleanPastedHTML', 'paste.cleanPastedHTML'], - ['anchorInputPlaceholder', 'anchor.placeholderText'], - ['checkLinkFormat', 'anchor.linkValidation'], - ['anchorButton', 'anchor.customClassOption'], - ['anchorButtonClass', 'anchor.customClassOption'], - ['anchorTarget', 'anchor.targetCheckbox'], - ['anchorInputCheckboxLabel', 'anchor.targetCheckboxText'], - ['anchorPreviewHideDelay', 'anchorPreview.hideDelay'], - ['disableAnchorPreview', 'anchorPreview: false'], - ['disablePlaceholders', 'placeholder: false'], - ['onShowToolbar', 'showToolbar custom event'], - ['onHideToolbar', 'hideToolbar custom event'] + // ['forcePlainText', 'paste.forcePlainText'], ]; // warn about using deprecated properties if (options) { deprecatedProperties.forEach(function (pair) { if (options.hasOwnProperty(pair[0]) && options[pair[0]] !== undefined) { - Util.deprecated(pair[0], pair[1], 'v5.0.0'); + Util.deprecated(pair[0], pair[1], 'v6.0.0'); } }); - - if (options.hasOwnProperty('placeholder') && typeof options.placeholder === 'string') { - Util.deprecated('placeholder', 'placeholder.text', 'v5.0.0'); - } } return Util.defaults({}, options, defaults); @@ -5943,16 +5177,6 @@ function MediumEditor(elements, options) { return this.options.ownerDocument.execCommand(action, false, null); } - // deprecate - MediumEditor.statics = { - ButtonsData: ButtonsData, - DefaultButton: DefaultButton, - AnchorExtension: AnchorExtension, - FontSizeExtension: FontSizeExtension, - Toolbar: Toolbar, - AnchorPreview: AnchorPreviewDeprecated - }; - MediumEditor.Extension = Extension; MediumEditor.extensions = extensionDefaults; @@ -5964,8 +5188,6 @@ function MediumEditor(elements, options) { // NOT DOCUMENTED - exposed for backwards compatability init: function (elements, options) { - var uniqueId = 1; - this.options = mergeOptions.call(this, this.defaults, options); this.origElements = elements; @@ -5973,12 +5195,6 @@ function MediumEditor(elements, options) { this.options.elementsContainer = this.options.ownerDocument.body; } - while (this.options.elementsContainer.querySelector('#medium-editor-toolbar-' + uniqueId)) { - uniqueId = uniqueId + 1; - } - - this.id = uniqueId; - return this.setup(); }, @@ -5988,17 +5204,19 @@ function MediumEditor(elements, options) { } createElementsArray.call(this, this.origElements); + if (this.elements.length === 0) { return; } - this.events = new Events(this); this.isActive = true; + addToEditors.call(this, this.options.contentWindow); + + this.events = new Events(this); // Call initialization helpers initElements.call(this); - initCommands.call(this); - initToolbar.call(this); + initExtensions.call(this); attachHandlers.call(this); }, @@ -6009,20 +5227,12 @@ function MediumEditor(elements, options) { this.isActive = false; - this.commands.forEach(function (extension) { + this.extensions.forEach(function (extension) { if (typeof extension.destroy === 'function') { extension.destroy(); - } else if (typeof extension.deactivate === 'function') { - Util.warn('Extension .deactivate() function has been deprecated. Use .destroy() instead. This will be removed in version 5.0.0'); - extension.deactivate(); } }, this); - if (this.toolbar !== undefined) { - this.toolbar.destroy(); - delete this.toolbar; - } - this.elements.forEach(function (element) { // Reset elements content, fix for issue where after editor destroyed the red underlines on spelling errors are left if (this.options.spellcheck) { @@ -6031,7 +5241,7 @@ function MediumEditor(elements, options) { element.removeAttribute('contentEditable'); element.removeAttribute('spellcheck'); - element.removeAttribute('data-medium-element'); + element.removeAttribute('data-medium-editor-element'); // Remove any elements created for textareas if (element.hasAttribute('medium-editor-textarea-id')) { @@ -6048,6 +5258,7 @@ function MediumEditor(elements, options) { this.elements = []; this.events.destroy(); + removeFromEditors.call(this, this.options.contentWindow); }, on: function (target, event, listener, useCapture) { @@ -6066,11 +5277,6 @@ function MediumEditor(elements, options) { this.events.detachCustomEvent(event, listener); }, - createEvent: function () { - Util.warn('.createEvent() has been deprecated and is no longer needed. ' + - 'You can attach and trigger custom events without calling this method. This will be removed in v5.0.0'); - }, - trigger: function (name, data, editable) { this.events.triggerCustomEvent(name, data, editable); }, @@ -6099,8 +5305,8 @@ function MediumEditor(elements, options) { getExtensionByName: function (name) { var extension; - if (this.commands && this.commands.length) { - this.commands.some(function (ext) { + if (this.extensions && this.extensions.length) { + this.extensions.some(function (ext) { if (ext.name === name) { extension = ext; return true; @@ -6112,31 +5318,53 @@ function MediumEditor(elements, options) { }, /** - * NOT DOCUMENTED - exposed for backwards compatability - * Helper function to call a method with a number of parameters on all registered extensions. - * The function assures that the function exists before calling. - * - * @param {string} funcName name of the function to call - * @param [args] arguments passed into funcName + * NOT DOCUMENTED - exposed as a helper for other extensions to use */ - callExtensions: function (funcName) { - if (arguments.length < 1) { - return; + addBuiltInExtension: function (name) { + var extension = this.getExtensionByName(name); + if (extension) { + return extension; } - var args = Array.prototype.slice.call(arguments, 1), - ext, - name; - - for (name in this.options.extensions) { - if (this.options.extensions.hasOwnProperty(name)) { - ext = this.options.extensions[name]; - if (ext[funcName] !== undefined) { - ext[funcName].apply(ext, args); + switch (name) { + case 'anchor': + extension = new MediumEditor.extensions.anchor(this.options.anchor); + break; + case 'anchorPreview': + extension = new MediumEditor.extensions.anchorPreview(this.options.anchorPreview); + break; + case 'autoLink': + extension = new MediumEditor.extensions.autoLink(); + break; + case 'fontsize': + extension = new MediumEditor.extensions.fontSize(); + break; + case 'imageDragging': + extension = new MediumEditor.extensions.imageDragging(); + break; + case 'keyboardCommands': + extension = new MediumEditor.extensions.keyboardCommands(this.options.keyboardCommands); + break; + case 'paste': + extension = new MediumEditor.extensions.paste(this.options.paste); + break; + case 'placeholder': + extension = new MediumEditor.extensions.placeholder(this.options.placeholder); + break; + default: + // All of the built-in buttons for MediumEditor are extensions + // so check to see if the extension we're creating is a built-in button + if (MediumEditor.extensions.button.isBuiltInButton(name)) { + extension = new MediumEditor.extensions.button(name); } - } + break; } - return this; + + if (extension) { + this.extensions.push(initExtension(extension, name, this)); + } + + return extension; }, stopSelectionUpdates: function () { @@ -6149,8 +5377,9 @@ function MediumEditor(elements, options) { // NOT DOCUMENTED - exposed as extension helper and for backwards compatability checkSelection: function () { - if (this.toolbar) { - this.toolbar.checkState(); + var toolbar = this.getExtensionByName('toolbar'); + if (toolbar) { + toolbar.checkState(); } return this; }, @@ -6215,21 +5444,6 @@ function MediumEditor(elements, options) { return Selection.getSelectedParentElement(range); }, - // NOT DOCUMENTED - exposed as extension helper - hideToolbarDefaultActions: function () { - if (this.toolbar) { - this.toolbar.hideToolbarDefaultActions(); - } - return this; - }, - - // NOT DOCUMENTED - exposed as extension helper and for backwards compatability - setToolbarPosition: function () { - if (this.toolbar) { - this.toolbar.setToolbarPosition(); - } - }, - selectAllContents: function () { var currNode = Selection.getSelectionElement(this.options.contentWindow); @@ -6414,16 +5628,6 @@ function MediumEditor(elements, options) { } }, - // alias for setup - keeping for backwards compatability - activate: function () { - Util.deprecatedMethod.call(this, 'activate', 'setup', arguments, 'v5.0.0'); - }, - - // alias for destroy - keeping for backwards compatability - deactivate: function () { - Util.deprecatedMethod.call(this, 'deactivate', 'destroy', arguments, 'v5.0.0'); - }, - cleanPaste: function (text) { this.getExtensionByName('paste').cleanPaste(text); }, @@ -6434,19 +5638,25 @@ function MediumEditor(elements, options) { }; }()); -MediumEditor.version = (function (major, minor, revision) { +MediumEditor.parseVersionString = function (release) { + var split = release.split('-'), + version = split[0].split('.'), + preRelease = (split.length > 1) ? split[1] : ''; return { - major: parseInt(major, 10), - minor: parseInt(minor, 10), - revision: parseInt(revision, 10), + major: parseInt(version[0], 10), + minor: parseInt(version[1], 10), + revision: parseInt(version[2], 10), + preRelease: preRelease, toString: function () { - return [major, minor, revision].join('.'); + return [[version[0], version[1], version[2]].join('.'), preRelease].join('-'); } }; -}).apply(this, ({ +}; + +MediumEditor.version = MediumEditor.parseVersionString.call(this, ({ // grunt-bump looks for this: - 'version': '4.12.0' -}).version.split('.')); + 'version': '5.0.0-alpha.0' +}).version); return MediumEditor; }())); diff --git a/dist/js/medium-editor.min.js b/dist/js/medium-editor.min.js index 2c6f55bb7..caeddf867 100644 --- a/dist/js/medium-editor.min.js +++ b/dist/js/medium-editor.min.js @@ -1,5 +1,3 @@ -"classList"in document.createElement("_")||!function(a){"use strict";if("Element"in a){var b="classList",c="prototype",d=a.Element[c],e=Object,f=String[c].trim||function(){return this.replace(/^\s+|\s+$/g,"")},g=Array[c].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1},h=function(a,b){this.name=a,this.code=DOMException[a],this.message=b},i=function(a,b){if(""===b)throw new h("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(b))throw new h("INVALID_CHARACTER_ERR","String contains an invalid character");return g.call(a,b)},j=function(a){for(var b=f.call(a.getAttribute("class")||""),c=b?b.split(/\s+/):[],d=0,e=c.length;e>d;d++)this.push(c[d]);this._updateClassName=function(){a.setAttribute("class",this.toString())}},k=j[c]=[],l=function(){return new j(this)};if(h[c]=Error[c],k.item=function(a){return this[a]||null},k.contains=function(a){return a+="",-1!==i(this,a)},k.add=function(){var a,b=arguments,c=0,d=b.length,e=!1;do a=b[c]+"",-1===i(this,a)&&(this.push(a),e=!0);while(++ci;i++)e+=String.fromCharCode(f[i]);c.push(e)}else if("Blob"===b(a)||"File"===b(a)){if(!g)throw new h("NOT_READABLE_ERR");var k=new g;c.push(k.readAsBinaryString(a))}else a instanceof d?"base64"===a.encoding&&p?c.push(p(a.data)):"URI"===a.encoding?c.push(decodeURIComponent(a.data)):"raw"===a.encoding&&c.push(a.data):("string"!=typeof a&&(a+=""),c.push(unescape(encodeURIComponent(a))))},e.getBlob=function(a){return arguments.length||(a=null),new d(this.data.join(""),a,"raw")},e.toString=function(){return"[object BlobBuilder]"},f.slice=function(a,b,c){var e=arguments.length;return 3>e&&(c=null),new d(this.data.slice(a,e>1?b:this.data.length),c,this.encoding)},f.toString=function(){return"[object Blob]"},f.close=function(){this.size=0,delete this.data},c}(a);a.Blob=function(a,b){var d=b?b.type||"":"",e=new c;if(a)for(var f=0,g=a.length;g>f;f++)e.append(Uint8Array&&a[f]instanceof Uint8Array?a[f].buffer:a[f]);var h=e.getBlob(d);return!h.slice&&h.webkitSlice&&(h.slice=h.webkitSlice),h};var d=Object.getPrototypeOf||function(a){return a.__proto__};a.Blob.prototype=d(new a.Blob)}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content||this),function(a,b){"use strict";"object"==typeof module?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):a.MediumEditor=b}(this,function(){"use strict";function a(a,b){return this.init(a,b)}var b;!function(a){function c(b,c,d){d||(d=a);try{for(var e=0;e=0,keyCode:{BACKSPACE:8,TAB:9,ENTER:13,ESCAPE:27,SPACE:32,DELETE:46},isMetaCtrlKey:function(a){return this.isMac&&a.metaKey||!this.isMac&&a.ctrlKey?!0:!1},isKey:function(a,b){var c=a.which;return null===c&&(c=null!==a.charCode?a.charCode:a.keyCode),!1===Array.isArray(b)?c===b:-1===b.indexOf(c)?!1:!0},parentElements:["p","h1","h2","h3","h4","h5","h6","blockquote","pre"],extend:function(){var a=[!0].concat(Array.prototype.slice.call(arguments));return d.apply(this,a)},defaults:function(){var a=[!1].concat(Array.prototype.slice.call(arguments));return d.apply(this,a)},derives:function(a,b){function c(){}var e=b.prototype;return c.prototype=a.prototype,b.prototype=new c,b.prototype.constructor=a,b.prototype=d(!1,b.prototype,e),b},findAdjacentTextNodeWithContent:function(a,b,c){var d,e=!1,f=c.createNodeIterator(a,NodeFilter.SHOW_TEXT,null,!1);for(d=f.nextNode();d;){if(d===b)e=!0;else if(e&&3===d.nodeType&&d.nodeValue&&d.nodeValue.trim().length>0)break;d=f.nextNode()}return d},isDescendant:function(a,b,c){if(!a||!b)return!1;if(c&&a===b)return!0;for(var d=b.parentNode;null!==d;){if(d===a)return!0;d=d.parentNode}return!1},isElement:function(a){return!(!a||1!==a.nodeType)},now:Date.now,throttle:function(a,b){var c,d,e,f=50,g=null,h=0,i=function(){h=Date.now(),g=null,e=a.apply(c,d),g||(c=d=null)};return b||0===b||(b=f),function(){var f=Date.now(),j=b-(f-h);return c=this,d=arguments,0>=j||j>b?(g&&(clearTimeout(g),g=null),h=f,e=a.apply(c,d),g||(c=d=null)):g||(g=setTimeout(i,j)),e}},traverseUp:function(a,b){if(!a)return!1;do{if(1===a.nodeType){if(b(a))return a;if(a.getAttribute("data-medium-element"))return!1}a=a.parentNode}while(a);return!1},htmlEntities:function(a){return String(a).replace(/&/g,"&").replace(//g,">").replace(/"/g,""")},insertHTMLCommand:function(a,b){var c,d,e,f,g,h,i;if(a.queryCommandSupported("insertHTML"))try{return a.execCommand("insertHTML",!1,b)}catch(j){}if(c=a.defaultView.getSelection(),c.getRangeAt&&c.rangeCount){if(d=c.getRangeAt(0),i=d.commonAncestorContainer,3===i.nodeType&&i.nodeValue===d.toString()||3!==i.nodeType&&i.innerHTML===d.toString()){for(;i.parentNode&&1===i.parentNode.childNodes.length&&!i.parentNode.getAttribute("data-medium-element");)i=i.parentNode;d.selectNode(i)}for(d.deleteContents(),e=a.createElement("div"),e.innerHTML=b,f=a.createDocumentFragment();e.firstChild;)g=e.firstChild,h=f.appendChild(g);d.insertNode(f),h&&(d=d.cloneRange(),d.setStartAfter(h),d.collapse(!0),c.removeAllRanges(),c.addRange(d))}},getSelectionRange:function(a){return this.deprecated("Util.getSelectionRange","Selection.getSelectionRange","v5.0.0"),f.getSelectionRange(a)},getSelectionStart:function(a){return this.deprecated("Util.getSelectionStart","Selection.getSelectionStart","v5.0.0"),f.getSelectionStart(a)},getSelectionData:function(a){return this.deprecated("Util.getSelectionData","Selection.getSelectionData","v5.0.0"),f.getSelectionData(a)},execFormatBlock:function(a,b){var c=f.getSelectionData(f.getSelectionStart(a));if("blockquote"===b&&c.el&&"blockquote"===c.el.parentNode.tagName.toLowerCase())return a.execCommand("outdent",!1,null);if(c.tagName===b&&(b="p"),this.isIE){if("blockquote"===b)return a.execCommand("indent",!1,b);b="<"+b+">"}return a.execCommand("formatBlock",!1,b)},setTargetBlank:function(a,b){var c,d=b||!1;if("a"===a.tagName.toLowerCase())a.target="_blank";else for(a=a.getElementsByTagName("a"),c=0;cd?(e=e.parentNode,c-=1):(f=f.parentNode,d-=1);for(;e!==f;)e=e.parentNode,f=f.parentNode;return e},ensureUrlHasProtocol:function(a){return-1===a.indexOf("://")?"http://"+a:a},warn:function(){void 0!==a.console&&"function"==typeof a.console.warn&&a.console.warn.apply(console,arguments)},deprecated:function(a,c,d){var e=a+" is deprecated, please use "+c+" instead.";d&&(e+=" Will be removed in "+d),b.warn(e)},deprecatedMethod:function(a,c,d,e){b.deprecated(a,c,e),"function"==typeof this[c]&&this[c].apply(this,d)},cleanupAttrs:function(a,b){b.forEach(function(b){a.removeAttribute(b)})},cleanupTags:function(a,b){b.forEach(function(b){a.tagName.toLowerCase()===b&&a.parentNode.removeChild(a)},this)},getClosestTag:function(a,b){return this.traverseUp(a,function(a){return a.tagName.toLowerCase()===b.toLowerCase()})},unwrap:function(a,b){for(var c=b.createDocumentFragment(),d=Array.prototype.slice.call(a.childNodes),e=0;eB",contentFA:'',key:"b"},italic:{name:"italic",action:"italic",aria:"italic",tagNames:["i","em"],style:{prop:"font-style",value:"italic"},useQueryState:!0,contentDefault:"I",contentFA:'',key:"i"},underline:{name:"underline",action:"underline",aria:"underline",tagNames:["u"],style:{prop:"text-decoration",value:"underline"},useQueryState:!0,contentDefault:"U",contentFA:'',key:"u"},strikethrough:{name:"strikethrough",action:"strikethrough",aria:"strike through",tagNames:["strike"],style:{prop:"text-decoration",value:"line-through"},useQueryState:!0,contentDefault:"A",contentFA:''},superscript:{name:"superscript",action:"superscript",aria:"superscript",tagNames:["sup"],contentDefault:"x1",contentFA:''},subscript:{name:"subscript",action:"subscript",aria:"subscript",tagNames:["sub"],contentDefault:"x1",contentFA:''},image:{name:"image",action:"image",aria:"image",tagNames:["img"],contentDefault:"image",contentFA:''},quote:{name:"quote",action:"append-blockquote",aria:"blockquote",tagNames:["blockquote"],contentDefault:"",contentFA:''},orderedlist:{name:"orderedlist",action:"insertorderedlist",aria:"ordered list",tagNames:["ol"],useQueryState:!0,contentDefault:"1.",contentFA:''},unorderedlist:{name:"unorderedlist",action:"insertunorderedlist",aria:"unordered list",tagNames:["ul"],useQueryState:!0,contentDefault:"",contentFA:''},pre:{name:"pre",action:"append-pre",aria:"preformatted text",tagNames:["pre"],contentDefault:"0101",contentFA:''},indent:{name:"indent",action:"indent",aria:"indent",tagNames:[],contentDefault:"",contentFA:''},outdent:{name:"outdent",action:"outdent",aria:"outdent",tagNames:[],contentDefault:"",contentFA:''},justifyCenter:{name:"justifyCenter",action:"justifyCenter",aria:"center justify",tagNames:[],style:{prop:"text-align",value:"center"},contentDefault:"C",contentFA:''},justifyFull:{name:"justifyFull",action:"justifyFull",aria:"full justify",tagNames:[],style:{prop:"text-align",value:"justify"},contentDefault:"J",contentFA:''},justifyLeft:{name:"justifyLeft",action:"justifyLeft",aria:"left justify",tagNames:[],style:{prop:"text-align",value:"left"},contentDefault:"L",contentFA:''},justifyRight:{name:"justifyRight",action:"justifyRight",aria:"right justify",tagNames:[],style:{prop:"text-align",value:"right"},contentDefault:"R",contentFA:''},header1:{name:"header1",action:function(a){return"append-"+a.firstHeader},aria:function(a){return a.firstHeader},tagNames:function(a){return[a.firstHeader]},contentDefault:"H1"},header2:{name:"header2",action:function(a){return"append-"+a.secondHeader},aria:function(a){return a.secondHeader},tagNames:function(a){return[a.secondHeader]},contentDefault:"H2"},removeFormat:{name:"removeFormat",aria:"remove formatting",action:"removeFormat",contentDefault:"X",contentFA:''}}}();var d;!function(){d={allowMultiParagraphSelection:!0,buttons:["bold","italic","underline","anchor","header1","header2","quote"],buttonLabels:!1,delay:0,diffLeft:0,diffTop:-10,disableReturn:!1,disableDoubleReturn:!1,disableToolbar:!1,disableEditing:!1,autoLink:!1,toolbarAlign:"center",elementsContainer:!1,imageDragging:!0,standardizeSelectionStart:!1,contentWindow:window,ownerDocument:document,firstHeader:"h3",secondHeader:"h4",targetBlank:!1,extensions:{},activeButtonClass:"medium-editor-button-active",firstButtonClass:"medium-editor-button-first",lastButtonClass:"medium-editor-button-last",spellcheck:!0}}();var e;!function(){e=function(a){b.extend(this,a)},e.extend=function(a){var c,d=this;c=a&&a.hasOwnProperty("constructor")?a.constructor:function(){return d.apply(this,arguments)},b.extend(c,d);var e=function(){this.constructor=c};return e.prototype=d.prototype,c.prototype=new e,a&&b.extend(c.prototype,a),c},e.prototype={init:function(){},base:void 0,name:void 0,checkState:void 0,destroy:void 0,queryCommandState:void 0,isActive:void 0,isAlreadyApplied:void 0,setActive:void 0,setInactive:void 0,window:void 0,document:void 0,getEditorElements:function(){return this.base.elements},getEditorId:function(){return this.base.id},getEditorOption:function(a){return this.base.options[a]}},["execAction","on","off","subscribe"].forEach(function(a){e.prototype[a]=function(){return this.base[a].apply(this.base,arguments)}})}();var f;!function(){f={findMatchingSelectionParent:function(a,c){var d,e,f=c.getSelection();return 0===f.rangeCount?!1:(d=f.getRangeAt(0),e=d.commonAncestorContainer,b.traverseUp(e,a))},getSelectionElement:function(a){return this.findMatchingSelectionParent(function(a){return a.getAttribute("data-medium-element")},a)},importSelectionMoveCursorPastAnchor:function(a,c){var d=function(a){return"a"===a.nodeName.toLowerCase()};if(a.start===a.end&&3===c.startContainer.nodeType&&c.startOffset===c.startContainer.nodeValue.length&&b.traverseUp(c.startContainer,d)){for(var e=c.startContainer,f=c.startContainer.parentNode;null!==f&&"a"!==f.nodeName.toLowerCase();)f.childNodes[f.childNodes.length-1]!==e?f=null:(e=f,f=f.parentNode);if(null!==f&&"a"===f.nodeName.toLowerCase()){for(var g=null,h=0;null===g&&ha;a+=1)c.appendChild(e.getRangeAt(a).cloneContents());d=c.innerHTML}return d},getCaretOffsets:function(a,b){var c,d;return b||(b=window.getSelection().getRangeAt(0)),c=b.cloneRange(),d=b.cloneRange(),c.selectNodeContents(a),c.setEnd(b.endContainer,b.endOffset),d.selectNodeContents(a),d.setStart(b.endContainer,b.endOffset),{left:c.toString().length,right:d.toString().length}},rangeSelectsSingleNode:function(a){var b=a.startContainer;return b===a.endContainer&&b.hasChildNodes()&&a.endOffset===a.startOffset+1},getSelectedParentElement:function(a){return a?this.rangeSelectsSingleNode(a)&&3!==a.startContainer.childNodes[a.startOffset].nodeType?a.startContainer.childNodes[a.startOffset]:3===a.startContainer.nodeType?a.startContainer.parentNode:a.startContainer:null},getSelectedElements:function(a){var b,c,d,e=a.getSelection();if(!e.rangeCount||e.isCollapsed||!e.getRangeAt(0).commonAncestorContainer)return[];if(b=e.getRangeAt(0),3===b.commonAncestorContainer.nodeType){for(c=[],d=b.commonAncestorContainer;d.parentNode&&1===d.parentNode.childNodes.length;)c.push(d.parentNode),d=d.parentNode;return c}return[].filter.call(b.commonAncestorContainer.getElementsByTagName("*"),function(a){return"function"==typeof e.containsNode?e.containsNode(a,!0):!0})},selectNode:function(a,b){var c=b.createRange(),d=b.getSelection();c.selectNodeContents(a),d.removeAllRanges(),d.addRange(c)},moveCursor:function(a,b,c){var d,e,f=c||0;d=a.createRange(),e=a.getSelection(),d.setStart(b,f),d.collapse(!0),e.removeAllRanges(),e.addRange(d)},getSelectionRange:function(a){var b=a.getSelection();return 0===b.rangeCount||!0===b.isCollapsed?null:b.getRangeAt(0)},getSelectionStart:function(a){var b=a.getSelection().anchorNode,c=b&&3===b.nodeType?b.parentNode:b;return c},getSelectionData:function(a){var c;for(a&&a.tagName&&(c=a.tagName.toLowerCase());a&&-1===b.parentElements.indexOf(c);)a=a.parentNode,a&&a.tagName&&(c=a.tagName.toLowerCase());return{el:a,tagName:c}}}}();var g;!function(){g=function(a){this.base=a,this.options=this.base.options,this.events=[],this.customEvents={},this.listeners={}},g.prototype={InputEventOnContenteditableSupported:!b.isIE,attachDOMEvent:function(a,b,c,d){a.addEventListener(b,c,d),this.events.push([a,b,c,d])},detachDOMEvent:function(a,b,c,d){var e,f=this.indexOfListener(a,b,c,d);-1!==f&&(e=this.events.splice(f,1)[0],e[0].removeEventListener(e[1],e[2],e[3]))},indexOfListener:function(a,b,c,d){var e,f,g;for(e=0,f=this.events.length;f>e;e+=1)if(g=this.events[e],g[0]===a&&g[1]===b&&g[2]===c&&g[3]===d)return e;return-1},detachAllDOMEvents:function(){for(var a=this.events.pop();a;)a[0].removeEventListener(a[1],a[2],a[3]),a=this.events.pop()},attachCustomEvent:function(a,b){this.setupListener(a),this.customEvents[a]||(this.customEvents[a]=[]),this.customEvents[a].push(b)},detachCustomEvent:function(a,b){var c=this.indexOfCustomListener(a,b);-1!==c&&this.customEvents[a].splice(c,1)},indexOfCustomListener:function(a,b){return this.customEvents[a]&&this.customEvents[a].length?this.customEvents[a].indexOf(b):-1},detachAllCustomEvents:function(){this.customEvents={}},triggerCustomEvent:function(a,b,c){this.customEvents[a]&&this.customEvents[a].forEach(function(a){a(b,c)})},destroy:function(){this.detachAllDOMEvents(),this.detachAllCustomEvents(),this.detachExecCommand()},attachToExecCommand:function(){this.execCommandListener||(this.execCommandListener=function(a){this.handleDocumentExecCommand(a)}.bind(this),this.wrapExecCommand(),this.options.ownerDocument.execCommand.listeners.push(this.execCommandListener))},detachExecCommand:function(){var a=this.options.ownerDocument;if(this.execCommandListener&&a.execCommand.listeners){var b=a.execCommand.listeners.indexOf(this.execCommandListener);-1!==b&&a.execCommand.listeners.splice(b,1),a.execCommand.listeners.length||this.unwrapExecCommand()}},wrapExecCommand:function(){var a=this.options.ownerDocument;if(!a.execCommand.listeners){var b=function(b,c,d){var e=a.execCommand.orig.apply(this,arguments);if(!a.execCommand.listeners)return e;var f=Array.prototype.slice.call(arguments);return a.execCommand.listeners.forEach(function(a){a({command:b,value:d,args:f,result:e})}),e};b.orig=a.execCommand,b.listeners=[],a.execCommand=b}},unwrapExecCommand:function(){var a=this.options.ownerDocument;a.execCommand.orig&&(a.execCommand=a.execCommand.orig)},setupListener:function(a){if(!this.listeners[a]){switch(a){case"externalInteraction":this.attachDOMEvent(this.options.ownerDocument.body,"mousedown",this.handleBodyMousedown.bind(this),!0),this.attachDOMEvent(this.options.ownerDocument.body,"click",this.handleBodyClick.bind(this),!0),this.attachDOMEvent(this.options.ownerDocument.body,"focus",this.handleBodyFocus.bind(this),!0);break;case"blur":this.setupListener("externalInteraction");break;case"focus":this.setupListener("externalInteraction");break;case"editableInput":this.contentCache=[],this.base.elements.forEach(function(a){this.contentCache[a.getAttribute("medium-editor-index")]=a.innerHTML,this.InputEventOnContenteditableSupported&&this.attachDOMEvent(a,"input",this.handleInput.bind(this))}.bind(this)),this.InputEventOnContenteditableSupported||(this.setupListener("editableKeypress"),this.keypressUpdateInput=!0,this.attachDOMEvent(document,"selectionchange",this.handleDocumentSelectionChange.bind(this)),this.attachToExecCommand());break;case"editableClick":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"click",this.handleClick.bind(this))}.bind(this));break;case"editableBlur":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"blur",this.handleBlur.bind(this))}.bind(this));break;case"editableKeypress":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"keypress",this.handleKeypress.bind(this))}.bind(this));break;case"editableKeyup":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"keyup",this.handleKeyup.bind(this))}.bind(this));break;case"editableKeydown":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"keydown",this.handleKeydown.bind(this))}.bind(this));break;case"editableKeydownEnter":this.setupListener("editableKeydown");break;case"editableKeydownTab":this.setupListener("editableKeydown");break;case"editableKeydownDelete":this.setupListener("editableKeydown");break;case"editableMouseover":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"mouseover",this.handleMouseover.bind(this))},this);break;case"editableDrag":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"dragover",this.handleDragging.bind(this)),this.attachDOMEvent(a,"dragleave",this.handleDragging.bind(this))},this);break;case"editableDrop":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"drop",this.handleDrop.bind(this))},this);break;case"editablePaste":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"paste",this.handlePaste.bind(this))},this)}this.listeners[a]=!0}},focusElement:function(a){a.focus(),this.updateFocus(a,{target:a,type:"focus"})},updateFocus:function(a,c){var d,e=this.base.toolbar?this.base.toolbar.getToolbarElement():null,f=this.base.getExtensionByName("anchor-preview"),g=f&&f.getPreviewElement?f.getPreviewElement():null,h=this.base.getFocusedElement();h&&"click"===c.type&&this.lastMousedownTarget&&(b.isDescendant(h,this.lastMousedownTarget,!0)||b.isDescendant(e,this.lastMousedownTarget,!0)||b.isDescendant(g,this.lastMousedownTarget,!0))&&(d=h),d||this.base.elements.some(function(c){return!d&&b.isDescendant(c,a,!0)&&(d=c),!!d},this);var i=!b.isDescendant(h,a,!0)&&!b.isDescendant(e,a,!0)&&!b.isDescendant(g,a,!0);d!==h&&(h&&i&&(h.removeAttribute("data-medium-focused"),this.triggerCustomEvent("blur",c,h)),d&&(d.setAttribute("data-medium-focused",!0),this.triggerCustomEvent("focus",c,d))),i&&this.triggerCustomEvent("externalInteraction",c)},updateInput:function(a,b){var c=a.getAttribute("medium-editor-index");a.innerHTML!==this.contentCache[c]&&this.triggerCustomEvent("editableInput",b,a),this.contentCache[c]=a.innerHTML},handleDocumentSelectionChange:function(a){if(a.currentTarget&&a.currentTarget.activeElement){var c,d=a.currentTarget.activeElement;this.base.elements.some(function(a){return b.isDescendant(a,d,!0)?(c=a,!0):!1},this),c&&this.updateInput(c,{target:d,currentTarget:c})}},handleDocumentExecCommand:function(){var a=this.base.getFocusedElement();a&&this.updateInput(a,{target:a,currentTarget:a})},handleBodyClick:function(a){this.updateFocus(a.target,a)},handleBodyFocus:function(a){this.updateFocus(a.target,a)},handleBodyMousedown:function(a){this.lastMousedownTarget=a.target},handleInput:function(a){this.updateInput(a.currentTarget,a)},handleClick:function(a){this.triggerCustomEvent("editableClick",a,a.currentTarget)},handleBlur:function(a){this.triggerCustomEvent("editableBlur",a,a.currentTarget)},handleKeypress:function(a){if(this.triggerCustomEvent("editableKeypress",a,a.currentTarget),this.keypressUpdateInput){var b={target:a.target,currentTarget:a.currentTarget};setTimeout(function(){this.updateInput(b.currentTarget,b)}.bind(this),0)}},handleKeyup:function(a){this.triggerCustomEvent("editableKeyup",a,a.currentTarget)},handleMouseover:function(a){this.triggerCustomEvent("editableMouseover",a,a.currentTarget)},handleDragging:function(a){this.triggerCustomEvent("editableDrag",a,a.currentTarget)},handleDrop:function(a){this.triggerCustomEvent("editableDrop",a,a.currentTarget)},handlePaste:function(a){this.triggerCustomEvent("editablePaste",a,a.currentTarget)},handleKeydown:function(a){return this.triggerCustomEvent("editableKeydown",a,a.currentTarget),b.isKey(a,b.keyCode.ENTER)?this.triggerCustomEvent("editableKeydownEnter",a,a.currentTarget):b.isKey(a,b.keyCode.TAB)?this.triggerCustomEvent("editableKeydownTab",a,a.currentTarget):b.isKey(a,[b.keyCode.DELETE,b.keyCode.BACKSPACE])?this.triggerCustomEvent("editableKeydownDelete",a,a.currentTarget):void 0}}}();var h;!function(){h=function(a,c){b.deprecated("MediumEditor.statics.DefaultButton","MediumEditor.extensions.button","v5.0.0"),this.options=a,this.name=a.name,this.init(c)},h.prototype={init:function(a){this.base=a,this.button=this.createButton(),this.base.on(this.button,"click",this.handleClick.bind(this)),this.options.key&&this.base.subscribe("editableKeydown",this.handleKeydown.bind(this))},getButton:function(){return this.button},getAction:function(){return"function"==typeof this.options.action?this.options.action(this.base.options):this.options.action},getAria:function(){return"function"==typeof this.options.aria?this.options.aria(this.base.options):this.options.aria},getTagNames:function(){return"function"==typeof this.options.tagNames?this.options.tagNames(this.base.options):this.options.tagNames},createButton:function(){var a=this.base.options.ownerDocument.createElement("button"),b=this.options.contentDefault,c=this.getAria();return a.classList.add("medium-editor-action"),a.classList.add("medium-editor-action-"+this.name),a.setAttribute("data-action",this.getAction()),c&&(a.setAttribute("title",c),a.setAttribute("aria-label",c)),this.base.options.buttonLabels&&("fontawesome"===this.base.options.buttonLabels&&this.options.contentFA?b=this.options.contentFA:"object"==typeof this.base.options.buttonLabels&&this.base.options.buttonLabels[this.name]&&(b=this.base.options.buttonLabels[this.options.name])),a.innerHTML=b,a},handleKeydown:function(a){var c,d=String.fromCharCode(a.which||a.keyCode).toLowerCase();this.options.key===d&&b.isMetaCtrlKey(a)&&(a.preventDefault(),a.stopPropagation(),c=this.getAction(),c&&this.base.execAction(c))},handleClick:function(a){a.preventDefault(),a.stopPropagation();var b=this.getAction();b&&this.base.execAction(b)},isActive:function(){return this.button.classList.contains(this.base.options.activeButtonClass)},setInactive:function(){this.button.classList.remove(this.base.options.activeButtonClass),delete this.knownState},setActive:function(){this.button.classList.add(this.base.options.activeButtonClass),delete this.knownState},queryCommandState:function(){var a=null;return this.options.useQueryState&&(a=this.base.queryCommandState(this.getAction())),a},isAlreadyApplied:function(a){var b,c,d=!1,e=this.getTagNames();return this.knownState===!1||this.knownState===!0?this.knownState:(e&&e.length>0&&a.tagName&&(d=-1!==e.indexOf(a.tagName.toLowerCase())),!d&&this.options.style&&(b=this.options.style.value.split("|"),c=this.base.options.contentWindow.getComputedStyle(a,null).getPropertyValue(this.options.style.prop),b.forEach(function(a){this.knownState||(d=-1!==c.indexOf(a),(d||"text-decoration"!==this.options.style.prop)&&(this.knownState=d))},this)),d)}}}();var i;!function(){function a(){b.deprecated("MediumEditor.statics.AnchorExtension","MediumEditor.extensions.anchor","v5.0.0"),this.parent=!0,this.options={name:"anchor",action:"createLink",aria:"link",tagNames:["a"],contentDefault:"#",contentFA:'',key:"k"},this.name="anchor",this.hasForm=!0}a.prototype={formSaveLabel:"✓",formCloseLabel:"×",handleClick:function(a){a.preventDefault(),a.stopPropagation();var b=f.getSelectedParentElement(f.getSelectionRange(this.base.options.ownerDocument));return b.tagName&&"a"===b.tagName.toLowerCase()?this.base.execAction("unlink"):(this.isDisplayed()||this.showForm(),!1)},handleKeydown:function(a){var c=String.fromCharCode(a.which||a.keyCode).toLowerCase(); - -this.options.key===c&&b.isMetaCtrlKey(a)&&(a.preventDefault(),a.stopPropagation(),this.handleClick(a))},getForm:function(){return this.form||(this.form=this.createForm()),this.form},getTemplate:function(){var a=[''];return a.push('',"fontawesome"===this.base.options.buttonLabels?'':this.formSaveLabel,""),a.push('',"fontawesome"===this.base.options.buttonLabels?'':this.formCloseLabel,""),this.base.options.anchorTarget&&a.push('',""),this.base.options.anchorButton&&a.push('',""),a.join("")},isDisplayed:function(){return"block"===this.getForm().style.display},hideForm:function(){this.getForm().style.display="none",this.getInput().value=""},showForm:function(a){var b=this.getInput();this.base.saveSelection(),this.base.hideToolbarDefaultActions(),this.getForm().style.display="block",this.base.setToolbarPosition(),b.value=a||"",b.focus()},deactivate:function(){return this.form?(this.form.parentNode&&this.form.parentNode.removeChild(this.form),void delete this.form):!1},getFormOpts:function(){var a=this.getForm().querySelector(".medium-editor-toolbar-anchor-target"),b=this.getForm().querySelector(".medium-editor-toolbar-anchor-button"),c={url:this.getInput().value};return this.base.options.checkLinkFormat&&(c.url=this.checkLinkFormat(c.url)),a&&a.checked?c.target="_blank":c.target="_self",b&&b.checked&&(c.buttonClass=this.base.options.anchorButtonClass),c},doFormSave:function(){var a=this.getFormOpts();this.completeFormSave(a)},completeFormSave:function(a){this.base.restoreSelection(),this.base.createLink(a),this.base.checkSelection()},checkLinkFormat:function(a){var b=/^(https?|ftps?|rtmpt?):\/\/|mailto:/;return(b.test(a)?"":"http://")+a},doFormCancel:function(){this.base.restoreSelection(),this.base.checkSelection()},attachFormEvents:function(a){var b=a.querySelector(".medium-editor-toolbar-close"),c=a.querySelector(".medium-editor-toolbar-save"),d=a.querySelector(".medium-editor-toolbar-input");this.base.on(a,"click",this.handleFormClick.bind(this)),this.base.on(d,"keyup",this.handleTextboxKeyup.bind(this)),this.base.on(b,"click",this.handleCloseClick.bind(this)),this.base.on(c,"click",this.handleSaveClick.bind(this),!0)},createForm:function(){var a=this.base.options.ownerDocument,b=a.createElement("div");return b.className="medium-editor-toolbar-form",b.id="medium-editor-toolbar-form-anchor-"+this.base.id,b.innerHTML=this.getTemplate(),this.attachFormEvents(b),b},getInput:function(){return this.getForm().querySelector("input.medium-editor-toolbar-input")},handleTextboxKeyup:function(a){return a.keyCode===b.keyCode.ENTER?(a.preventDefault(),void this.doFormSave()):void(a.keyCode===b.keyCode.ESCAPE&&(a.preventDefault(),this.doFormCancel()))},handleFormClick:function(a){a.stopPropagation()},handleSaveClick:function(a){a.preventDefault(),this.doFormSave()},handleCloseClick:function(a){a.preventDefault(),this.doFormCancel()}},i=b.derives(h,a)}();var j;!function(){j=function(){b.deprecated("MediumEditor.statics.AnchorPreview","MediumEditor.extensions.anchorPreview","v5.0.0"),this.parent=!0,this.name="anchor-preview"},j.prototype={previewValueSelector:"a",init:function(){this.anchorPreview=this.createPreview(),this.base.options.elementsContainer.appendChild(this.anchorPreview),this.attachToEditables()},getPreviewElement:function(){return this.anchorPreview},createPreview:function(){var a=this.base.options.ownerDocument.createElement("div");return a.id="medium-editor-anchor-preview-"+this.base.id,a.className="medium-editor-anchor-preview",a.innerHTML=this.getTemplate(),this.base.on(a,"click",this.handleClick.bind(this)),a},getTemplate:function(){return'

'},deactivate:function(){this.anchorPreview&&(this.anchorPreview.parentNode&&this.anchorPreview.parentNode.removeChild(this.anchorPreview),delete this.anchorPreview)},hidePreview:function(){this.anchorPreview.classList.remove("medium-editor-anchor-preview-active"),this.activeAnchor=null},showPreview:function(a){return this.anchorPreview.classList.contains("medium-editor-anchor-preview-active")||a.getAttribute("data-disable-preview")?!0:(this.previewValueSelector&&(this.anchorPreview.querySelector(this.previewValueSelector).textContent=a.attributes.href.value,this.anchorPreview.querySelector(this.previewValueSelector).href=a.attributes.href.value),this.anchorPreview.classList.add("medium-toolbar-arrow-over"),this.anchorPreview.classList.remove("medium-toolbar-arrow-under"),this.anchorPreview.classList.contains("medium-editor-anchor-preview-active")||this.anchorPreview.classList.add("medium-editor-anchor-preview-active"),this.activeAnchor=a,this.positionPreview(),this.attachPreviewHandlers(),this)},positionPreview:function(){var a,b,c=this.anchorPreview.offsetHeight,d=this.activeAnchor.getBoundingClientRect(),e=(d.left+d.right)/2;a=this.anchorPreview.offsetWidth/2,b=this.base.options.diffLeft-a,this.anchorPreview.style.top=Math.round(c+d.bottom-this.base.options.diffTop+this.base.options.contentWindow.pageYOffset-this.anchorPreview.offsetHeight)+"px",a>e?this.anchorPreview.style.left=b+a+"px":this.base.options.contentWindow.innerWidth-ethis.base.options.anchorPreviewHideDelay&&this.detachPreviewHandlers()},detachPreviewHandlers:function(){clearInterval(this.intervalTimer),this.instanceHandlePreviewMouseover&&(this.base.off(this.anchorPreview,"mouseover",this.instanceHandlePreviewMouseover),this.base.off(this.anchorPreview,"mouseout",this.instanceHandlePreviewMouseout),this.activeAnchor&&(this.base.off(this.activeAnchor,"mouseover",this.instanceHandlePreviewMouseover),this.base.off(this.activeAnchor,"mouseout",this.instanceHandlePreviewMouseout))),this.hidePreview(),this.hovering=this.instanceHandlePreviewMouseover=this.instanceHandlePreviewMouseout=null},attachPreviewHandlers:function(){this.lastOver=(new Date).getTime(),this.hovering=!0,this.instanceHandlePreviewMouseover=this.handlePreviewMouseover.bind(this),this.instanceHandlePreviewMouseout=this.handlePreviewMouseout.bind(this),this.intervalTimer=setInterval(this.updatePreview.bind(this),200),this.base.on(this.anchorPreview,"mouseover",this.instanceHandlePreviewMouseover),this.base.on(this.anchorPreview,"mouseout",this.instanceHandlePreviewMouseout),this.base.on(this.activeAnchor,"mouseover",this.instanceHandlePreviewMouseover),this.base.on(this.activeAnchor,"mouseout",this.instanceHandlePreviewMouseout)}}}();var k;!function(){function a(){b.deprecated("MediumEditor.statics.FontSizeExtension","MediumEditor.extensions.fontSize","v5.0.0"),this.parent=!0,this.options={name:"fontsize",action:"fontSize",aria:"increase/decrease font size",contentDefault:"±",contentFA:''},this.name="fontsize",this.hasForm=!0}a.prototype={handleClick:function(a){if(a.preventDefault(),a.stopPropagation(),!this.isDisplayed()){var b=this.base.options.ownerDocument.queryCommandValue("fontSize")+"";this.showForm(b)}return!1},getForm:function(){return this.form||(this.form=this.createForm()),this.form},isDisplayed:function(){return"block"===this.getForm().style.display},hideForm:function(){this.getForm().style.display="none",this.getInput().value=""},showForm:function(a){var b=this.getInput();this.base.saveSelection(),this.base.hideToolbarDefaultActions(),this.getForm().style.display="block",this.base.setToolbarPosition(),b.value=a||"",b.focus()},deactivate:function(){return this.form?(this.form.parentNode&&this.form.parentNode.removeChild(this.form),void delete this.form):!1},doFormSave:function(){this.base.restoreSelection(),this.base.checkSelection()},doFormCancel:function(){this.base.restoreSelection(),this.clearFontSize(),this.base.checkSelection()},createForm:function(){var a=this.base.options.ownerDocument,b=a.createElement("div"),c=a.createElement("input"),d=a.createElement("a"),e=a.createElement("a");return b.className="medium-editor-toolbar-form",b.id="medium-editor-toolbar-form-fontsize-"+this.base.id,this.base.on(b,"click",this.handleFormClick.bind(this)),c.setAttribute("type","range"),c.setAttribute("min","1"),c.setAttribute("max","7"),c.className="medium-editor-toolbar-input",b.appendChild(c),this.base.on(c,"change",this.handleSliderChange.bind(this)),e.setAttribute("href","#"),e.className="medium-editor-toobar-save",e.innerHTML="fontawesome"===this.base.options.buttonLabels?'':"✓",b.appendChild(e),this.base.on(e,"click",this.handleSaveClick.bind(this),!0),d.setAttribute("href","#"),d.className="medium-editor-toobar-close",d.innerHTML="fontawesome"===this.base.options.buttonLabels?'':"×",b.appendChild(d),this.base.on(d,"click",this.handleCloseClick.bind(this)),b},getInput:function(){return this.getForm().querySelector("input.medium-editor-toolbar-input")},clearFontSize:function(){f.getSelectedElements(this.base.options.ownerDocument).forEach(function(a){"FONT"===a.tagName&&a.hasAttribute("size")&&a.removeAttribute("size")})},handleSliderChange:function(){var a=this.getInput().value;"4"===a?this.clearFontSize():this.base.execAction("fontSize",{size:a})},handleFormClick:function(a){a.stopPropagation()},handleSaveClick:function(a){a.preventDefault(),this.doFormSave()},handleCloseClick:function(a){a.preventDefault(),this.doFormCancel()}},k=b.derives(h,a)}();var l;!function(){l=e.extend({init:function(){this.button=this.createButton(),this.on(this.button,"click",this.handleClick.bind(this)),this.key&&this.subscribe("editableKeydown",this.handleKeydown.bind(this))},getButton:function(){return this.button},getAction:function(){return"function"==typeof this.action?this.action(this.base.options):this.action},getAria:function(){return"function"==typeof this.aria?this.aria(this.base.options):this.aria},getTagNames:function(){return"function"==typeof this.tagNames?this.tagNames(this.base.options):this.tagNames},createButton:function(){var a=this.document.createElement("button"),b=this.contentDefault,c=this.getAria(),d=this.getEditorOption("buttonLabels");return a.classList.add("medium-editor-action"),a.classList.add("medium-editor-action-"+this.name),a.setAttribute("data-action",this.getAction()),c&&(a.setAttribute("title",c),a.setAttribute("aria-label",c)),d&&("fontawesome"===d&&this.contentFA?b=this.contentFA:"object"==typeof d&&d[this.name]&&(b=d[this.name])),a.innerHTML=b,a},handleKeydown:function(a){var c;b.isKey(a,this.key.charCodeAt(0))&&b.isMetaCtrlKey(a)&&!a.shiftKey&&(a.preventDefault(),a.stopPropagation(),c=this.getAction(),c&&this.execAction(c))},handleClick:function(a){a.preventDefault(),a.stopPropagation();var b=this.getAction();b&&this.execAction(b)},isActive:function(){return this.button.classList.contains(this.getEditorOption("activeButtonClass"))},setInactive:function(){this.button.classList.remove(this.getEditorOption("activeButtonClass")),delete this.knownState},setActive:function(){this.button.classList.add(this.getEditorOption("activeButtonClass")),delete this.knownState},queryCommandState:function(){var a=null;return this.useQueryState&&(a=this.base.queryCommandState(this.getAction())),a},isAlreadyApplied:function(a){var b,c,d=!1,e=this.getTagNames();return this.knownState===!1||this.knownState===!0?this.knownState:(e&&e.length>0&&a.tagName&&(d=-1!==e.indexOf(a.tagName.toLowerCase())),!d&&this.style&&(b=this.style.value.split("|"),c=this.window.getComputedStyle(a,null).getPropertyValue(this.style.prop),b.forEach(function(a){this.knownState||(d=-1!==c.indexOf(a),(d||"text-decoration"!==this.style.prop)&&(this.knownState=d))},this)),d)}})}();var m;!function(){var a=function(){};m=l.extend({formSaveLabel:"✓",formCloseLabel:"×",hasForm:!0,getForm:a,isDisplayed:a,hideForm:a})}();var n;!function(){n=m.extend({customClassOption:null,customClassOptionText:"Button",linkValidation:!1,placeholderText:"Paste or type a link",targetCheckbox:!1,targetCheckboxText:"Open in new window",name:"anchor",action:"createLink",aria:"link",tagNames:["a"],contentDefault:"#",contentFA:'',key:"k",handleClick:function(a){a.preventDefault(),a.stopPropagation();var b=f.getSelectedParentElement(f.getSelectionRange(this.document));return b.tagName&&"a"===b.tagName.toLowerCase()?this.execAction("unlink"):(this.isDisplayed()||this.showForm(),!1)},handleKeydown:function(a){b.isKey(a,this.key.charCodeAt(0))&&b.isMetaCtrlKey(a)&&this.handleClick(a)},getForm:function(){return this.form||(this.form=this.createForm()),this.form},getTemplate:function(){var a=[''];return a.push('',"fontawesome"===this.getEditorOption("buttonLabels")?'':this.formSaveLabel,""),a.push('',"fontawesome"===this.getEditorOption("buttonLabels")?'':this.formCloseLabel,""),this.targetCheckbox&&a.push('',""),this.customClassOption&&a.push('',""),a.join("")},isDisplayed:function(){return"block"===this.getForm().style.display},hideForm:function(){this.getForm().style.display="none",this.getInput().value=""},showForm:function(a){var b=this.getInput();this.base.saveSelection(),this.base.hideToolbarDefaultActions(),this.getForm().style.display="block",this.base.setToolbarPosition(),b.value=a||"",b.focus()},destroy:function(){return this.form?(this.form.parentNode&&this.form.parentNode.removeChild(this.form),void delete this.form):!1},deactivate:function(){b.deprecatedMethod.call(this,"deactivate","destroy",arguments,"v5.0.0")},getFormOpts:function(){var a=this.getForm().querySelector(".medium-editor-toolbar-anchor-target"),b=this.getForm().querySelector(".medium-editor-toolbar-anchor-button"),c={url:this.getInput().value};return this.linkValidation&&(c.url=this.checkLinkFormat(c.url)),c.target="_self",a&&a.checked&&(c.target="_blank"),b&&b.checked&&(c.buttonClass=this.customClassOption),c},doFormSave:function(){var a=this.getFormOpts();this.completeFormSave(a)},completeFormSave:function(a){this.base.restoreSelection(),this.execAction(this.action,a),this.base.checkSelection()},checkLinkFormat:function(a){var b=/^(https?|ftps?|rtmpt?):\/\/|mailto:/;return(b.test(a)?"":"http://")+a},doFormCancel:function(){this.base.restoreSelection(),this.base.checkSelection()},attachFormEvents:function(a){var b=a.querySelector(".medium-editor-toolbar-close"),c=a.querySelector(".medium-editor-toolbar-save"),d=a.querySelector(".medium-editor-toolbar-input");this.on(a,"click",this.handleFormClick.bind(this)),this.on(d,"keyup",this.handleTextboxKeyup.bind(this)),this.on(b,"click",this.handleCloseClick.bind(this)),this.on(c,"click",this.handleSaveClick.bind(this),!0)},createForm:function(){var a=this.document,b=a.createElement("div");return b.className="medium-editor-toolbar-form",b.id="medium-editor-toolbar-form-anchor-"+this.getEditorId(),b.innerHTML=this.getTemplate(),this.attachFormEvents(b),b},getInput:function(){return this.getForm().querySelector("input.medium-editor-toolbar-input")},handleTextboxKeyup:function(a){return a.keyCode===b.keyCode.ENTER?(a.preventDefault(),void this.doFormSave()):void(a.keyCode===b.keyCode.ESCAPE&&(a.preventDefault(),this.doFormCancel()))},handleFormClick:function(a){a.stopPropagation()},handleSaveClick:function(a){a.preventDefault(),this.doFormSave()},handleCloseClick:function(a){a.preventDefault(),this.doFormCancel()}})}();var o;!function(){o=e.extend({name:"anchor-preview",hideDelay:500,previewValueSelector:"a",diffLeft:0,diffTop:-10,elementsContainer:!1,init:function(){this.anchorPreview=this.createPreview(),this.elementsContainer||(this.elementsContainer=this.document.body),this.elementsContainer.appendChild(this.anchorPreview),this.attachToEditables()},getPreviewElement:function(){return this.anchorPreview},createPreview:function(){var a=this.document.createElement("div");return a.id="medium-editor-anchor-preview-"+this.getEditorId(),a.className="medium-editor-anchor-preview",a.innerHTML=this.getTemplate(),this.on(a,"click",this.handleClick.bind(this)),a},getTemplate:function(){return'
'},destroy:function(){this.anchorPreview&&(this.anchorPreview.parentNode&&this.anchorPreview.parentNode.removeChild(this.anchorPreview),delete this.anchorPreview)},deactivate:function(){b.deprecatedMethod.call(this,"deactivate","destroy",arguments,"v5.0.0")},hidePreview:function(){this.anchorPreview.classList.remove("medium-editor-anchor-preview-active"),this.activeAnchor=null},showPreview:function(a){return this.anchorPreview.classList.contains("medium-editor-anchor-preview-active")||a.getAttribute("data-disable-preview")?!0:(this.previewValueSelector&&(this.anchorPreview.querySelector(this.previewValueSelector).textContent=a.attributes.href.value,this.anchorPreview.querySelector(this.previewValueSelector).href=a.attributes.href.value),this.anchorPreview.classList.add("medium-toolbar-arrow-over"),this.anchorPreview.classList.remove("medium-toolbar-arrow-under"),this.anchorPreview.classList.contains("medium-editor-anchor-preview-active")||this.anchorPreview.classList.add("medium-editor-anchor-preview-active"),this.activeAnchor=a,this.positionPreview(),this.attachPreviewHandlers(),this)},positionPreview:function(){var a,b,c=this.anchorPreview.offsetHeight,d=this.activeAnchor.getBoundingClientRect(),e=(d.left+d.right)/2;a=this.anchorPreview.offsetWidth/2,b=this.diffLeft-a,this.anchorPreview.style.top=Math.round(c+d.bottom-this.diffTop+this.window.pageYOffset-this.anchorPreview.offsetHeight)+"px",a>e?this.anchorPreview.style.left=b+a+"px":this.window.innerWidth-ethis.hideDelay&&this.detachPreviewHandlers()},detachPreviewHandlers:function(){clearInterval(this.intervalTimer),this.instanceHandlePreviewMouseover&&(this.off(this.anchorPreview,"mouseover",this.instanceHandlePreviewMouseover),this.off(this.anchorPreview,"mouseout",this.instanceHandlePreviewMouseout),this.activeAnchor&&(this.off(this.activeAnchor,"mouseover",this.instanceHandlePreviewMouseover),this.off(this.activeAnchor,"mouseout",this.instanceHandlePreviewMouseout))),this.hidePreview(),this.hovering=this.instanceHandlePreviewMouseover=this.instanceHandlePreviewMouseout=null},attachPreviewHandlers:function(){this.lastOver=(new Date).getTime(),this.hovering=!0,this.instanceHandlePreviewMouseover=this.handlePreviewMouseover.bind(this),this.instanceHandlePreviewMouseout=this.handlePreviewMouseout.bind(this),this.intervalTimer=setInterval(this.updatePreview.bind(this),200),this.on(this.anchorPreview,"mouseover",this.instanceHandlePreviewMouseover),this.on(this.anchorPreview,"mouseout",this.instanceHandlePreviewMouseout),this.on(this.activeAnchor,"mouseover",this.instanceHandlePreviewMouseover),this.on(this.activeAnchor,"mouseout",this.instanceHandlePreviewMouseout)}})}();var p,q,r;q="com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw",r="(((?:(https?://|ftps?://|nntp://)|www\\d{0,3}[.]|[a-z0-9.\\-]+[.]("+q+")\\/)\\S+(?:[^\\s`!\\[\\]{};:'\".,?«»“”‘’])))|(([a-z0-9\\-]+\\.)?[a-z0-9\\-]+\\.("+q+"))",function(){function a(a){return!b.getClosestTag(a,"a")}var c=new RegExp("^("+q+")$","i");p=e.extend({init:function(){this.disableEventHandling=!1,this.subscribe("editableKeypress",this.onKeypress.bind(this)),this.subscribe("editableBlur",this.onBlur.bind(this)),this.document.execCommand("AutoUrlDetect",!1,!1)},destroy:function(){this.document.queryCommandSupported("AutoUrlDetect")&&this.document.execCommand("AutoUrlDetect",!1,!0)},onBlur:function(a,b){this.performLinking(b)},onKeypress:function(a){this.disableEventHandling||b.isKey(a,[b.keyCode.SPACE,b.keyCode.ENTER])&&(clearTimeout(this.performLinkingTimeout),this.performLinkingTimeout=setTimeout(function(){try{var b=this.base.exportSelection();this.performLinking(a.target)&&this.base.importSelection(b,!0)}catch(c){window.console&&window.console.error("Failed to perform linking",c),this.disableEventHandling=!0}}.bind(this),0))},performLinking:function(a){var b=a.querySelectorAll("p"),c=!1;0===b.length&&(b=[a]);for(var d=0;d=c&&d!==e&&0!==f&&(b||a).splitText(f)},removeObsoleteAutoLinkSpans:function(c){for(var d=c.querySelectorAll('span[data-auto-link="true"]'),e=!1,f=0;f0;)d[f].parentNode.insertBefore(d[f].firstChild,d[f]);d[f].parentNode.removeChild(d[f])}}return e},performLinkingWithinElement:function(a){for(var b=this.findLinkableText(a),c=!1,d=0;db.end+1)throw new Error("PerformLinking overshot the target!");f&&d.push(h||g),e+=g.nodeValue.length,null!==h&&(e+=h.nodeValue.length,c.nextNode()),h=null}return d},createLink:function(a,c){for(var d=!1,e=0;e'),c.onload=function(){var a=this.document.getElementById(d);a&&(a.removeAttribute("id"),a.removeAttribute("class"),a.src=c.result)}.bind(this)}}.bind(this))),a.target.classList.remove(d)}})}();var t;!function(){t=m.extend({name:"fontsize",action:"fontSize",aria:"increase/decrease font size",contentDefault:"±",contentFA:'',handleClick:function(a){if(a.preventDefault(),a.stopPropagation(),!this.isDisplayed()){var b=this.document.queryCommandValue("fontSize")+"";this.showForm(b)}return!1},getForm:function(){return this.form||(this.form=this.createForm()),this.form},isDisplayed:function(){return"block"===this.getForm().style.display},hideForm:function(){this.getForm().style.display="none",this.getInput().value=""},showForm:function(a){var b=this.getInput();this.base.saveSelection(),this.base.hideToolbarDefaultActions(),this.getForm().style.display="block",this.base.setToolbarPosition(),b.value=a||"",b.focus()},destroy:function(){return this.form?(this.form.parentNode&&this.form.parentNode.removeChild(this.form),void delete this.form):!1},deactivate:function(){b.deprecatedMethod.call(this,"deactivate","destroy",arguments,"v5.0.0")},doFormSave:function(){this.base.restoreSelection(),this.base.checkSelection()},doFormCancel:function(){this.base.restoreSelection(),this.clearFontSize(),this.base.checkSelection()},createForm:function(){var a=this.document,b=a.createElement("div"),c=a.createElement("input"),d=a.createElement("a"),e=a.createElement("a");return b.className="medium-editor-toolbar-form",b.id="medium-editor-toolbar-form-fontsize-"+this.getEditorId(),this.on(b,"click",this.handleFormClick.bind(this)),c.setAttribute("type","range"),c.setAttribute("min","1"),c.setAttribute("max","7"),c.className="medium-editor-toolbar-input",b.appendChild(c),this.on(c,"change",this.handleSliderChange.bind(this)),e.setAttribute("href","#"),e.className="medium-editor-toobar-save",e.innerHTML="fontawesome"===this.getEditorOption("buttonLabels")?'':"✓",b.appendChild(e),this.on(e,"click",this.handleSaveClick.bind(this),!0),d.setAttribute("href","#"),d.className="medium-editor-toobar-close",d.innerHTML="fontawesome"===this.getEditorOption("buttonLabels")?'':"×",b.appendChild(d),this.on(d,"click",this.handleCloseClick.bind(this)),b},getInput:function(){return this.getForm().querySelector("input.medium-editor-toolbar-input")},clearFontSize:function(){f.getSelectedElements(this.document).forEach(function(a){"FONT"===a.tagName&&a.hasAttribute("size")&&a.removeAttribute("size")})},handleSliderChange:function(){var a=this.getInput().value;"4"===a?this.clearFontSize():this.execAction("fontSize",{size:a})},handleFormClick:function(a){a.stopPropagation()},handleSaveClick:function(a){a.preventDefault(),this.doFormSave()},handleCloseClick:function(a){a.preventDefault(),this.doFormCancel()}})}();var u;!function(){function a(){return[[new RegExp(/<[^>]*docs-internal-guid[^>]*>/gi),""],[new RegExp(/<\/b>(]*>)?$/gi),""],[new RegExp(/\s+<\/span>/g)," "],[new RegExp(/
/g),"
"],[new RegExp(/]*(font-style:italic;font-weight:bold|font-weight:bold;font-style:italic)[^>]*>/gi),''],[new RegExp(/]*font-style:italic[^>]*>/gi),''],[new RegExp(/]*font-weight:bold[^>]*>/gi),''],[new RegExp(/<(\/?)(i|b|a)>/gi),"<$1$2>"],[new RegExp(/<a(?:(?!href).)+href=(?:"|”|“|"|“|”)(((?!"|”|“|"|“|”).)*)(?:"|”|“|"|“|”)(?:(?!>).)*>/gi),''],[new RegExp(/<\/p>\n+/gi),"

"],[new RegExp(/\n+

/gi),""]]}u=e.extend({forcePlainText:!0,cleanPastedHTML:!1,cleanReplacements:[],cleanAttrs:["class","style","dir"],cleanTags:["meta"],targetBlank:!1,disableReturn:!1,init:function(){(this.forcePlainText||this.cleanPastedHTML)&&this.subscribe("editablePaste",this.handlePaste.bind(this)); - -},handlePaste:function(a,c){var d,e,f,g,h="",i="text/html",j="text/plain";if(this.window.clipboardData&&void 0===a.clipboardData&&(a.clipboardData=this.window.clipboardData,i="Text",j="Text"),a.clipboardData&&a.clipboardData.getData&&!a.defaultPrevented){if(a.preventDefault(),f=a.clipboardData.getData(i),g=a.clipboardData.getData(j),this.cleanPastedHTML&&f)return this.cleanPaste(f);if(this.disableReturn||c.getAttribute("data-disable-return"))h=b.htmlEntities(g);else if(d=g.split(/[\r\n]+/g),d.length>1)for(e=0;e"+b.htmlEntities(d[e])+"

");else h=b.htmlEntities(d[0]);b.insertHTMLCommand(this.document,h)}},cleanPaste:function(b){var c,d,e,g=f.getSelectionElement(this.window),h=/
"),this.pasteHTML("

"+d.join("

")+"

");try{this.document.execCommand("insertText",!1,"\n")}catch(j){}for(d=g.querySelectorAll("a,p,div,br"),c=0;c"+d.innerHTML+"":e.innerHTML=d.innerHTML,d.parentNode.replaceChild(e,d);for(f=a.querySelectorAll("span"),c=0;c0&&(d[0].classList.add(this.options.firstButtonClass),d[d.length-1].classList.add(this.options.lastButtonClass)),f},destroy:function(){this.toolbar&&(this.toolbar.parentNode&&this.toolbar.parentNode.removeChild(this.toolbar),delete this.toolbar)},deactivate:function(){b.deprecatedMethod.call(this,"deactivate","destroy",arguments,"v5.0.0")},getToolbarElement:function(){return this.toolbar||(this.toolbar=this.createToolbar()),this.toolbar},getToolbarActionsElement:function(){return this.getToolbarElement().querySelector(".medium-editor-toolbar-actions")},initThrottledMethods:function(){this.throttledPositionToolbar=b.throttle(function(){this.base.isActive&&this.positionToolbarIfShown()}.bind(this))},attachEventHandlers:function(){this.base.subscribe("blur",this.handleBlur.bind(this)),this.base.subscribe("focus",this.handleFocus.bind(this)),this.base.subscribe("editableClick",this.handleEditableClick.bind(this)),this.base.subscribe("editableKeyup",this.handleEditableKeyup.bind(this)),this.base.on(this.options.ownerDocument.documentElement,"mouseup",this.handleDocumentMouseup.bind(this)),this.options.staticToolbar&&this.options.stickyToolbar&&this.base.on(this.options.contentWindow,"scroll",this.handleWindowScroll.bind(this),!0),this.base.on(this.options.contentWindow,"resize",this.handleWindowResize.bind(this))},handleWindowScroll:function(){this.positionToolbarIfShown()},handleWindowResize:function(){this.throttledPositionToolbar()},handleDocumentMouseup:function(a){return a&&a.target&&b.isDescendant(this.getToolbarElement(),a.target)?!1:void this.checkState()},handleEditableClick:function(){setTimeout(function(){this.checkState()}.bind(this),0)},handleEditableKeyup:function(){this.checkState()},handleBlur:function(){clearTimeout(this.hideTimeout),clearTimeout(this.delayShowTimeout),this.hideTimeout=setTimeout(function(){this.hideToolbar()}.bind(this),1)},handleFocus:function(){this.checkState()},isDisplayed:function(){return this.getToolbarElement().classList.contains("medium-editor-toolbar-active")},showToolbar:function(){clearTimeout(this.hideTimeout),this.isDisplayed()||(this.getToolbarElement().classList.add("medium-editor-toolbar-active"),this.base.trigger("showToolbar",{},this.base.getFocusedElement()),"function"==typeof this.options.onShowToolbar&&(b.deprecated("onShowToolbar","the showToolbar custom event","v5.0.0"),this.options.onShowToolbar()))},hideToolbar:function(){this.isDisplayed()&&(this.getToolbarElement().classList.remove("medium-editor-toolbar-active"),this.base.trigger("hideToolbar",{},this.base.getFocusedElement()),this.base.commands.forEach(function(a){"function"==typeof a.onHide&&(b.deprecated("onHide","the hideToolbar custom event","v5.0.0"),a.onHide())}),"function"==typeof this.options.onHideToolbar&&(b.deprecated("onHideToolbar","the hideToolbar custom event","v5.0.0"),this.options.onHideToolbar()))},isToolbarDefaultActionsDisplayed:function(){return"block"===this.getToolbarActionsElement().style.display},hideToolbarDefaultActions:function(){this.isToolbarDefaultActionsDisplayed()&&(this.getToolbarActionsElement().style.display="none")},showToolbarDefaultActions:function(){this.hideExtensionForms(),this.isToolbarDefaultActionsDisplayed()||(this.getToolbarActionsElement().style.display="block"),this.delayShowTimeout=this.base.delay(function(){this.showToolbar()}.bind(this))},hideExtensionForms:function(){this.base.commands.forEach(function(a){a.hasForm&&a.isDisplayed()&&a.hideForm()})},multipleBlockElementsSelected:function(){var a=f.getSelectionHtml.call(this).replace(/<[\S]+><\/[\S]+>/gim,""),b=a.match(/<(p|h[1-6]|blockquote)[^>]*>/g);return!!b&&b.length>1},modifySelection:function(){var a=this.options.contentWindow.getSelection(),c=a.getRangeAt(0);if(this.options.standardizeSelectionStart&&c.startContainer.nodeValue&&c.startOffset===c.startContainer.nodeValue.length){var d=b.findAdjacentTextNodeWithContent(f.getSelectionElement(this.options.contentWindow),c.startContainer,this.options.ownerDocument);if(d){for(var e=0;0===d.nodeValue.substr(e,1).trim().length;)e+=1;var g=this.options.ownerDocument.createRange();g.setStart(d,e),g.setEnd(c.endContainer,c.endOffset),a.removeAllRanges(),a.addRange(g),c=g}}},checkState:function(){if(!this.base.preventSelectionUpdates){if(!this.base.getFocusedElement()||f.selectionInContentEditableFalse(this.options.contentWindow))return this.hideToolbar();var a=f.getSelectionElement(this.options.contentWindow);return!a||-1===this.base.elements.indexOf(a)||a.getAttribute("data-disable-toolbar")?this.hideToolbar():this.options.updateOnEmptySelection&&this.options.staticToolbar?this.showAndUpdateToolbar():""===this.options.contentWindow.getSelection().toString().trim()||this.options.allowMultiParagraphSelection===!1&&this.multipleBlockElementsSelected()?this.hideToolbar():void this.showAndUpdateToolbar()}},getFocusedElement:function(){return this.base.getFocusedElement()},showAndUpdateToolbar:function(){this.modifySelection(),this.setToolbarButtonStates(),this.base.trigger("positionToolbar",{},this.base.getFocusedElement()),this.showToolbarDefaultActions(),this.setToolbarPosition()},setToolbarButtonStates:function(){this.base.commands.forEach(function(a){"function"==typeof a.isActive&&"function"==typeof a.setInactive&&a.setInactive()}.bind(this)),this.checkActiveButtons()},checkActiveButtons:function(){var a,c=[],d=null,e=f.getSelectionRange(this.options.ownerDocument),g=function(b){"function"==typeof b.checkState?b.checkState(a):"function"==typeof b.isActive&&"function"==typeof b.isAlreadyApplied&&"function"==typeof b.setActive&&!b.isActive()&&b.isAlreadyApplied(a)&&b.setActive()};if(e)for(a=f.getSelectedParentElement(e),this.base.commands.forEach(function(a){return"function"==typeof a.queryCommandState&&(d=a.queryCommandState(),null!==d)?void(d&&"function"==typeof a.setActive&&a.setActive()):void c.push(a)});void 0!==a.tagName&&-1===b.parentElements.indexOf(a.tagName.toLowerCase)&&(c.forEach(g),-1===this.base.elements.indexOf(a));)a=a.parentNode},positionToolbarIfShown:function(){this.isDisplayed()&&this.setToolbarPosition()},setToolbarPosition:function(){var a,b=this.base.getFocusedElement(),c=this.options.contentWindow.getSelection();return b?(this.options.staticToolbar?(this.showToolbar(),this.positionStaticToolbar(b)):c.isCollapsed||(this.showToolbar(),this.positionToolbar(c)),a=this.base.getExtensionByName("anchor-preview"),void(a&&"function"==typeof a.hidePreview&&a.hidePreview())):this},positionStaticToolbar:function(a){this.getToolbarElement().style.left="0";var b,c=this.options.ownerDocument.documentElement&&this.options.ownerDocument.documentElement.scrollTop||this.options.ownerDocument.body.scrollTop,d=this.options.contentWindow.innerWidth,e=this.getToolbarElement(),f=a.getBoundingClientRect(),g=f.top+c,h=f.left+f.width/2,i=e.offsetHeight,j=e.offsetWidth,k=j/2;switch(this.options.stickyToolbar?c>g+a.offsetHeight-i?(e.style.top=g+a.offsetHeight-i+"px",e.classList.remove("sticky-toolbar")):c>g-i?(e.classList.add("sticky-toolbar"),e.style.top="0px"):(e.classList.remove("sticky-toolbar"),e.style.top=g-i+"px"):e.style.top=g-i+"px",this.options.toolbarAlign){case"left":b=f.left;break;case"right":b=f.right-j;break;case"center":b=h-k}0>b?b=0:b+j>d&&(b=d-Math.ceil(j)-1),e.style.left=b+"px"},positionToolbar:function(a){this.getToolbarElement().style.left="0";var b=this.options.contentWindow.innerWidth,c=a.getRangeAt(0),d=c.getBoundingClientRect(),e=(d.left+d.right)/2,f=this.getToolbarElement(),g=f.offsetHeight,h=f.offsetWidth,i=h/2,j=50,k=this.options.diffLeft-i;d.tope?f.style.left=k+i+"px":i>b-e?f.style.left=b+k-i+"px":f.style.left=k+e+"px"}}}();var x;return function(){x={button:l,form:m,anchor:n,anchorPreview:o,autoLink:p,fontSize:t,imageDragging:s,paste:u,placeholder:v}}(),function(){function l(a,b){if(this.options.disableReturn||b.getAttribute("data-disable-return"))a.preventDefault();else if(this.options.disableDoubleReturn||b.getAttribute("data-disable-double-return")){var c=f.getSelectionStart(this.options.ownerDocument);(c&&""===c.textContent.trim()||c.previousElementSibling&&""===c.previousElementSibling.textContent.trim())&&a.preventDefault()}}function m(a){var c=f.getSelectionStart(this.options.ownerDocument),d=c&&c.tagName.toLowerCase();"pre"===d&&(a.preventDefault(),b.insertHTMLCommand(this.options.ownerDocument," ")),b.isListItem(c)&&(a.preventDefault(),a.shiftKey?this.options.ownerDocument.execCommand("outdent",!1,null):this.options.ownerDocument.execCommand("indent",!1,null))}function n(a){var c,d=f.getSelectionStart(this.options.ownerDocument),e=d.tagName.toLowerCase(),g=/^(\s+|)?$/i,h=/h\d/i;b.isKey(a,[b.keyCode.BACKSPACE,b.keyCode.ENTER])&&d.previousElementSibling&&h.test(e)&&0===f.getCaretOffsets(d).left?b.isKey(a,b.keyCode.BACKSPACE)&&g.test(d.previousElementSibling.innerHTML)?(d.previousElementSibling.parentNode.removeChild(d.previousElementSibling),a.preventDefault()):b.isKey(a,b.keyCode.ENTER)&&(c=this.options.ownerDocument.createElement("p"),c.innerHTML="
",d.previousElementSibling.parentNode.insertBefore(c,d),a.preventDefault()):b.isKey(a,b.keyCode.DELETE)&&d.nextElementSibling&&d.previousElementSibling&&!h.test(e)&&g.test(d.innerHTML)&&h.test(d.nextElementSibling.tagName)?(f.moveCursor(this.options.ownerDocument,d.nextElementSibling),d.previousElementSibling.parentNode.removeChild(d),a.preventDefault()):b.isKey(a,b.keyCode.BACKSPACE)&&"li"===e&&g.test(d.innerHTML)&&!d.previousElementSibling&&!d.parentElement.previousElementSibling&&d.nextElementSibling&&"li"===d.nextElementSibling.tagName.toLowerCase()&&(c=this.options.ownerDocument.createElement("p"),c.innerHTML="
",d.parentElement.parentElement.insertBefore(c,d.parentElement),f.moveCursor(this.options.ownerDocument,c),d.parentElement.removeChild(d),a.preventDefault())}function o(a){var c,d=f.getSelectionStart(this.options.ownerDocument);d&&(d.getAttribute("data-medium-element")&&0===d.children.length&&this.options.ownerDocument.execCommand("formatBlock",!1,"p"),b.isKey(a,b.keyCode.ENTER)&&!b.isListItem(d)&&(c=d.tagName.toLowerCase(),"a"===c?this.options.ownerDocument.execCommand("unlink",!1,null):a.shiftKey||a.ctrlKey||/h\d/.test(c)||this.options.ownerDocument.execCommand("formatBlock",!1,"p")))}function p(a){a||(a=[]),"string"==typeof a&&(a=this.options.ownerDocument.querySelectorAll(a)),b.isElement(a)&&(a=[a]);var c=Array.prototype.slice.apply(a);this.elements=[],c.forEach(function(a){this.elements.push("textarea"===a.tagName.toLowerCase()?y.call(this,a):a)},this)}function q(a,b){return Object.keys(b).forEach(function(c){void 0===a[c]&&(a[c]=b[c])}),a}function r(a,c,d){"undefined"!=typeof a.parent&&b.warn("Extension .parent property has been deprecated. The .base property for extensions will always be set to MediumEditor in version 5.0.0");var e={window:d.options.contentWindow,document:d.options.ownerDocument};return a.parent!==!1&&(e.base=d),a=q(a,e),"function"==typeof a.init&&a.init(d),a.name||(a.name=c),a}function s(){var a,b=!1;if(this.options.disableAnchorPreview)return!1;if(this.options.anchorPreview===!1)return!1;if(this.options.extensions["anchor-preview"])return!1;if(this.options.disableToolbar)return!1;for(a=0;a0&&(a=f.getRangeAt(0),c=a.cloneRange(),this.elements.some(function(c,d){return c===a.startContainer||b.isDescendant(c,a.startContainer)?(g=d,!0):!1}),g>-1&&(c.selectNodeContents(this.elements[g]),c.setEnd(a.startContainer,a.startOffset),d=c.toString().length,e={start:d,end:d+a.toString().length,editableElementIndex:g})),null!==e&&0===e.editableElementIndex&&delete e.editableElementIndex,e},saveSelection:function(){this.selectionState=this.exportSelection()},importSelection:function(a,b){if(a){var c,d,e,g,h=void 0===a.editableElementIndex?0:a.editableElementIndex,i={editableElementIndex:h,start:a.start,end:a.end},j=this.elements[i.editableElementIndex],k=0,l=this.options.ownerDocument.createRange(),m=[j],n=!1,o=!1;for(l.setStart(j,0),l.collapse(!0),c=m.pop();!o&&c;){if(3===c.nodeType)g=k+c.length,!n&&i.start>=k&&i.start<=g&&(l.setStart(c,i.start-k),n=!0),n&&i.end>=k&&i.end<=g&&(l.setEnd(c,i.end-k),o=!0),k=g;else for(d=c.childNodes.length-1;d>=0;)m.push(c.childNodes[d]),d-=1;o||(c=m.pop())}b&&(l=f.importSelectionMoveCursorPastAnchor(i,l)),e=this.options.contentWindow.getSelection(),e.removeAllRanges(),e.addRange(l)}},restoreSelection:function(){this.importSelection(this.selectionState)},createLink:function(a){var c,d;if(a.url&&a.url.trim().length>0&&(this.options.ownerDocument.execCommand("createLink",!1,a.url),(this.options.targetBlank||"_blank"===a.target)&&b.setTargetBlank(f.getSelectionStart(this.options.ownerDocument),a.url),a.buttonClass&&b.addClassToAnchors(f.getSelectionStart(this.options.ownerDocument),a.buttonClass)),this.options.targetBlank||"_blank"===a.target||a.buttonClass)for(c=this.options.ownerDocument.createEvent("HTMLEvents"),c.initEvent("input",!0,!0,this.options.contentWindow),d=0;db;b++)if(b in this&&this[b]===a)return b;return-1},h=function(a,b){this.name=a,this.code=DOMException[a],this.message=b},i=function(a,b){if(""===b)throw new h("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(b))throw new h("INVALID_CHARACTER_ERR","String contains an invalid character");return g.call(a,b)},j=function(a){for(var b=f.call(a.getAttribute("class")||""),c=b?b.split(/\s+/):[],d=0,e=c.length;e>d;d++)this.push(c[d]);this._updateClassName=function(){a.setAttribute("class",this.toString())}},k=j[c]=[],l=function(){return new j(this)};if(h[c]=Error[c],k.item=function(a){return this[a]||null},k.contains=function(a){return a+="",-1!==i(this,a)},k.add=function(){var a,b=arguments,c=0,d=b.length,e=!1;do a=b[c]+"",-1===i(this,a)&&(this.push(a),e=!0);while(++ci;i++)e+=String.fromCharCode(f[i]);c.push(e)}else if("Blob"===b(a)||"File"===b(a)){if(!g)throw new h("NOT_READABLE_ERR");var k=new g;c.push(k.readAsBinaryString(a))}else a instanceof d?"base64"===a.encoding&&p?c.push(p(a.data)):"URI"===a.encoding?c.push(decodeURIComponent(a.data)):"raw"===a.encoding&&c.push(a.data):("string"!=typeof a&&(a+=""),c.push(unescape(encodeURIComponent(a))))},e.getBlob=function(a){return arguments.length||(a=null),new d(this.data.join(""),a,"raw")},e.toString=function(){return"[object BlobBuilder]"},f.slice=function(a,b,c){var e=arguments.length;return 3>e&&(c=null),new d(this.data.slice(a,e>1?b:this.data.length),c,this.encoding)},f.toString=function(){return"[object Blob]"},f.close=function(){this.size=0,delete this.data},c}(a);a.Blob=function(a,b){var d=b?b.type||"":"",e=new c;if(a)for(var f=0,g=a.length;g>f;f++)e.append(Uint8Array&&a[f]instanceof Uint8Array?a[f].buffer:a[f]);var h=e.getBlob(d);return!h.slice&&h.webkitSlice&&(h.slice=h.webkitSlice),h};var d=Object.getPrototypeOf||function(a){return a.__proto__};a.Blob.prototype=d(new a.Blob)}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content||this),function(a,b){"use strict";"object"==typeof module?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):a.MediumEditor=b}(this,function(){"use strict";function a(a,b){return this.init(a,b)}var b;!function(a){function c(a,b){var c,d=Array.prototype.slice.call(arguments,2);b=b||{};for(var e=0;e=0,keyCode:{BACKSPACE:8,TAB:9,ENTER:13,ESCAPE:27,SPACE:32,DELETE:46,K:107},isMetaCtrlKey:function(a){return this.isMac&&a.metaKey||!this.isMac&&a.ctrlKey?!0:!1},isKey:function(a,b){var c=this.getKeyCode(a);return!1===Array.isArray(b)?c===b:-1===b.indexOf(c)?!1:!0},getKeyCode:function(a){var b=a.which;return null===b&&(b=null!==a.charCode?a.charCode:a.keyCode),b},parentElements:["p","h1","h2","h3","h4","h5","h6","blockquote","pre"],extend:function(){var a=[!0].concat(Array.prototype.slice.call(arguments));return c.apply(this,a)},defaults:function(){var a=[!1].concat(Array.prototype.slice.call(arguments));return c.apply(this,a)},findAdjacentTextNodeWithContent:function(a,b,c){var d,e=!1,f=c.createNodeIterator(a,NodeFilter.SHOW_TEXT,null,!1);for(d=f.nextNode();d;){if(d===b)e=!0;else if(e&&3===d.nodeType&&d.nodeValue&&d.nodeValue.trim().length>0)break;d=f.nextNode()}return d},isDescendant:function(a,b,c){if(!a||!b)return!1;if(c&&a===b)return!0;for(var d=b.parentNode;null!==d;){if(d===a)return!0;d=d.parentNode}return!1},isElement:function(a){return!(!a||1!==a.nodeType)},now:Date.now,throttle:function(a,b){var c,d,e,f=50,g=null,h=0,i=function(){h=Date.now(),g=null,e=a.apply(c,d),g||(c=d=null)};return b||0===b||(b=f),function(){var f=Date.now(),j=b-(f-h);return c=this,d=arguments,0>=j||j>b?(g&&(clearTimeout(g),g=null),h=f,e=a.apply(c,d),g||(c=d=null)):g||(g=setTimeout(i,j)),e}},traverseUp:function(a,b){if(!a)return!1;do{if(1===a.nodeType){if(b(a))return a;if(a.getAttribute("data-medium-editor-element"))return!1}a=a.parentNode}while(a);return!1},htmlEntities:function(a){return String(a).replace(/&/g,"&").replace(//g,">").replace(/"/g,""")},insertHTMLCommand:function(a,b){var c,d,e,f,g,h,i;if(a.queryCommandSupported("insertHTML"))try{return a.execCommand("insertHTML",!1,b)}catch(j){}if(c=a.defaultView.getSelection(),c.getRangeAt&&c.rangeCount){if(d=c.getRangeAt(0),i=d.commonAncestorContainer,3===i.nodeType&&i.nodeValue===d.toString()||3!==i.nodeType&&i.innerHTML===d.toString()){for(;i.parentNode&&1===i.parentNode.childNodes.length&&!i.parentNode.getAttribute("data-medium-editor-element");)i=i.parentNode;d.selectNode(i)}for(d.deleteContents(),e=a.createElement("div"),e.innerHTML=b,f=a.createDocumentFragment();e.firstChild;)g=e.firstChild,h=f.appendChild(g);d.insertNode(f),h&&(d=d.cloneRange(),d.setStartAfter(h),d.collapse(!0),c.removeAllRanges(),c.addRange(d))}},execFormatBlock:function(a,b){var c=f.getSelectionData(f.getSelectionStart(a));if("blockquote"===b&&c.el&&"blockquote"===c.el.parentNode.tagName.toLowerCase())return a.execCommand("outdent",!1,null);if(c.tagName===b&&(b="p"),this.isIE){if("blockquote"===b)return a.execCommand("indent",!1,b);b="<"+b+">"}return a.execCommand("formatBlock",!1,b)},setTargetBlank:function(a,b){var c,d=b||!1;if("a"===a.tagName.toLowerCase())a.target="_blank";else for(a=a.getElementsByTagName("a"),c=0;cd?(e=e.parentNode,c-=1):(f=f.parentNode,d-=1);for(;e!==f;)e=e.parentNode,f=f.parentNode;return e},ensureUrlHasProtocol:function(a){return-1===a.indexOf("://")?"http://"+a:a},warn:function(){void 0!==a.console&&"function"==typeof a.console.warn&&a.console.warn.apply(console,arguments)},deprecated:function(a,c,d){var e=a+" is deprecated, please use "+c+" instead.";d&&(e+=" Will be removed in "+d),b.warn(e)},deprecatedMethod:function(a,c,d,e){b.deprecated(a,c,e),"function"==typeof this[c]&&this[c].apply(this,d)},cleanupAttrs:function(a,b){b.forEach(function(b){a.removeAttribute(b)})},cleanupTags:function(a,b){b.forEach(function(b){a.tagName.toLowerCase()===b&&a.parentNode.removeChild(a)},this)},getClosestTag:function(a,b){return this.traverseUp(a,function(a){return a.tagName.toLowerCase()===b.toLowerCase()})},unwrap:function(a,b){for(var c=b.createDocumentFragment(),d=Array.prototype.slice.call(a.childNodes),e=0;eB",contentFA:''},italic:{name:"italic",action:"italic",aria:"italic",tagNames:["i","em"],style:{prop:"font-style",value:"italic"},useQueryState:!0,contentDefault:"I",contentFA:''},underline:{name:"underline",action:"underline",aria:"underline",tagNames:["u"],style:{prop:"text-decoration",value:"underline"},useQueryState:!0,contentDefault:"U",contentFA:''},strikethrough:{name:"strikethrough",action:"strikethrough",aria:"strike through",tagNames:["strike"],style:{prop:"text-decoration",value:"line-through"},useQueryState:!0,contentDefault:"A",contentFA:''},superscript:{name:"superscript",action:"superscript",aria:"superscript",tagNames:["sup"],contentDefault:"x1",contentFA:''},subscript:{name:"subscript",action:"subscript",aria:"subscript",tagNames:["sub"],contentDefault:"x1",contentFA:''},image:{name:"image",action:"image",aria:"image",tagNames:["img"],contentDefault:"image",contentFA:''},quote:{name:"quote",action:"append-blockquote",aria:"blockquote",tagNames:["blockquote"],contentDefault:"",contentFA:''},orderedlist:{name:"orderedlist",action:"insertorderedlist",aria:"ordered list",tagNames:["ol"],useQueryState:!0,contentDefault:"1.",contentFA:''},unorderedlist:{name:"unorderedlist",action:"insertunorderedlist",aria:"unordered list",tagNames:["ul"],useQueryState:!0,contentDefault:"",contentFA:''},pre:{name:"pre",action:"append-pre",aria:"preformatted text",tagNames:["pre"],contentDefault:"0101",contentFA:''},indent:{name:"indent",action:"indent",aria:"indent",tagNames:[],contentDefault:"",contentFA:''},outdent:{name:"outdent",action:"outdent",aria:"outdent",tagNames:[],contentDefault:"",contentFA:''},justifyCenter:{name:"justifyCenter",action:"justifyCenter",aria:"center justify",tagNames:[],style:{prop:"text-align",value:"center"},contentDefault:"C",contentFA:''},justifyFull:{name:"justifyFull",action:"justifyFull",aria:"full justify",tagNames:[],style:{prop:"text-align",value:"justify"},contentDefault:"J",contentFA:''},justifyLeft:{name:"justifyLeft",action:"justifyLeft",aria:"left justify",tagNames:[],style:{prop:"text-align",value:"left"},contentDefault:"L",contentFA:''},justifyRight:{name:"justifyRight",action:"justifyRight",aria:"right justify",tagNames:[],style:{prop:"text-align",value:"right"},contentDefault:"R",contentFA:''},header1:{name:"header1",action:function(a){return"append-"+a.firstHeader},aria:function(a){return a.firstHeader},tagNames:function(a){return[a.firstHeader]},contentDefault:"H1"},header2:{name:"header2",action:function(a){return"append-"+a.secondHeader},aria:function(a){return a.secondHeader},tagNames:function(a){return[a.secondHeader]},contentDefault:"H2"},removeFormat:{name:"removeFormat",aria:"remove formatting",action:"removeFormat",contentDefault:"X",contentFA:''}}}();var d;!function(){d={activeButtonClass:"medium-editor-button-active",allowMultiParagraphSelection:!0,buttonLabels:!1,delay:0,disableReturn:!1,disableDoubleReturn:!1,disableEditing:!1,autoLink:!1,elementsContainer:!1,contentWindow:window,ownerDocument:document,firstHeader:"h3",secondHeader:"h4",targetBlank:!1,extensions:{},spellcheck:!0}}();var e;!function(){e=function(a){b.extend(this,a)},e.extend=function(a){var c,d=this;c=a&&a.hasOwnProperty("constructor")?a.constructor:function(){return d.apply(this,arguments)},b.extend(c,d);var e=function(){this.constructor=c};return e.prototype=d.prototype,c.prototype=new e,a&&b.extend(c.prototype,a),c},e.prototype={init:function(){},base:void 0,name:void 0,checkState:void 0,destroy:void 0,queryCommandState:void 0,isActive:void 0,isAlreadyApplied:void 0,setActive:void 0,setInactive:void 0,window:void 0,document:void 0,getEditorElements:function(){return this.base.elements},getEditorId:function(){return this.base.id},getEditorOption:function(a){return this.base.options[a]}},["execAction","on","off","subscribe","trigger"].forEach(function(a){e.prototype[a]=function(){return this.base[a].apply(this.base,arguments)}})}();var f;!function(){f={findMatchingSelectionParent:function(a,c){var d,e,f=c.getSelection();return 0===f.rangeCount?!1:(d=f.getRangeAt(0),e=d.commonAncestorContainer,b.traverseUp(e,a))},getSelectionElement:function(a){return this.findMatchingSelectionParent(function(a){return a.getAttribute("data-medium-editor-element")},a)},importSelectionMoveCursorPastAnchor:function(a,c){var d=function(a){return"a"===a.nodeName.toLowerCase()};if(a.start===a.end&&3===c.startContainer.nodeType&&c.startOffset===c.startContainer.nodeValue.length&&b.traverseUp(c.startContainer,d)){for(var e=c.startContainer,f=c.startContainer.parentNode;null!==f&&"a"!==f.nodeName.toLowerCase();)f.childNodes[f.childNodes.length-1]!==e?f=null:(e=f,f=f.parentNode);if(null!==f&&"a"===f.nodeName.toLowerCase()){for(var g=null,h=0;null===g&&hb;b+=1)d.appendChild(f.getRangeAt(b).cloneContents());e=d.innerHTML}return e},getCaretOffsets:function(a,b){var c,d;return b||(b=window.getSelection().getRangeAt(0)),c=b.cloneRange(),d=b.cloneRange(),c.selectNodeContents(a),c.setEnd(b.endContainer,b.endOffset),d.selectNodeContents(a),d.setStart(b.endContainer,b.endOffset),{left:c.toString().length,right:d.toString().length}},rangeSelectsSingleNode:function(a){var b=a.startContainer;return b===a.endContainer&&b.hasChildNodes()&&a.endOffset===a.startOffset+1},getSelectedParentElement:function(a){return a?this.rangeSelectsSingleNode(a)&&3!==a.startContainer.childNodes[a.startOffset].nodeType?a.startContainer.childNodes[a.startOffset]:3===a.startContainer.nodeType?a.startContainer.parentNode:a.startContainer:null},getSelectedElements:function(a){var b,c,d,e=a.getSelection();if(!e.rangeCount||e.isCollapsed||!e.getRangeAt(0).commonAncestorContainer)return[];if(b=e.getRangeAt(0),3===b.commonAncestorContainer.nodeType){for(c=[],d=b.commonAncestorContainer;d.parentNode&&1===d.parentNode.childNodes.length;)c.push(d.parentNode),d=d.parentNode;return c}return[].filter.call(b.commonAncestorContainer.getElementsByTagName("*"),function(a){return"function"==typeof e.containsNode?e.containsNode(a,!0):!0})},selectNode:function(a,b){var c=b.createRange(),d=b.getSelection();c.selectNodeContents(a),d.removeAllRanges(),d.addRange(c)},moveCursor:function(a,b,c){var d,e,f=c||0;d=a.createRange(),e=a.getSelection(),d.setStart(b,f),d.collapse(!0),e.removeAllRanges(),e.addRange(d)},getSelectionRange:function(a){var b=a.getSelection();return 0===b.rangeCount?null:b.getRangeAt(0)},getSelectionStart:function(a){var b=a.getSelection().anchorNode,c=b&&3===b.nodeType?b.parentNode:b;return c},getSelectionData:function(a){var c;for(a&&a.tagName&&(c=a.tagName.toLowerCase());a&&-1===b.parentElements.indexOf(c);)a=a.parentNode,a&&a.tagName&&(c=a.tagName.toLowerCase());return{el:a,tagName:c}}}}();var g;!function(){g=function(a){this.base=a,this.options=this.base.options,this.events=[],this.customEvents={},this.listeners={}},g.prototype={InputEventOnContenteditableSupported:!b.isIE,attachDOMEvent:function(a,b,c,d){a.addEventListener(b,c,d),this.events.push([a,b,c,d])},detachDOMEvent:function(a,b,c,d){var e,f=this.indexOfListener(a,b,c,d);-1!==f&&(e=this.events.splice(f,1)[0],e[0].removeEventListener(e[1],e[2],e[3]))},indexOfListener:function(a,b,c,d){var e,f,g;for(e=0,f=this.events.length;f>e;e+=1)if(g=this.events[e],g[0]===a&&g[1]===b&&g[2]===c&&g[3]===d)return e;return-1},detachAllDOMEvents:function(){for(var a=this.events.pop();a;)a[0].removeEventListener(a[1],a[2],a[3]),a=this.events.pop()},attachCustomEvent:function(a,b){this.setupListener(a),this.customEvents[a]||(this.customEvents[a]=[]),this.customEvents[a].push(b)},detachCustomEvent:function(a,b){var c=this.indexOfCustomListener(a,b);-1!==c&&this.customEvents[a].splice(c,1)},indexOfCustomListener:function(a,b){return this.customEvents[a]&&this.customEvents[a].length?this.customEvents[a].indexOf(b):-1},detachAllCustomEvents:function(){this.customEvents={}},triggerCustomEvent:function(a,b,c){this.customEvents[a]&&this.customEvents[a].forEach(function(a){a(b,c)})},destroy:function(){this.detachAllDOMEvents(),this.detachAllCustomEvents(),this.detachExecCommand()},attachToExecCommand:function(){this.execCommandListener||(this.execCommandListener=function(a){this.handleDocumentExecCommand(a)}.bind(this),this.wrapExecCommand(),this.options.ownerDocument.execCommand.listeners.push(this.execCommandListener))},detachExecCommand:function(){var a=this.options.ownerDocument;if(this.execCommandListener&&a.execCommand.listeners){var b=a.execCommand.listeners.indexOf(this.execCommandListener);-1!==b&&a.execCommand.listeners.splice(b,1),a.execCommand.listeners.length||this.unwrapExecCommand()}},wrapExecCommand:function(){var a=this.options.ownerDocument;if(!a.execCommand.listeners){var b=function(b,c,d){var e=a.execCommand.orig.apply(this,arguments);if(!a.execCommand.listeners)return e;var f=Array.prototype.slice.call(arguments);return a.execCommand.listeners.forEach(function(a){a({command:b,value:d,args:f,result:e})}),e};b.orig=a.execCommand,b.listeners=[],a.execCommand=b}},unwrapExecCommand:function(){var a=this.options.ownerDocument;a.execCommand.orig&&(a.execCommand=a.execCommand.orig)},setupListener:function(a){if(!this.listeners[a]){switch(a){case"externalInteraction":this.attachDOMEvent(this.options.ownerDocument.body,"mousedown",this.handleBodyMousedown.bind(this),!0),this.attachDOMEvent(this.options.ownerDocument.body,"click",this.handleBodyClick.bind(this),!0),this.attachDOMEvent(this.options.ownerDocument.body,"focus",this.handleBodyFocus.bind(this),!0);break;case"blur":this.setupListener("externalInteraction");break;case"focus":this.setupListener("externalInteraction");break;case"editableInput":this.contentCache=[],this.base.elements.forEach(function(a){this.contentCache[a.getAttribute("medium-editor-index")]=a.innerHTML,this.InputEventOnContenteditableSupported&&this.attachDOMEvent(a,"input",this.handleInput.bind(this))}.bind(this)),this.InputEventOnContenteditableSupported||(this.setupListener("editableKeypress"),this.keypressUpdateInput=!0,this.attachDOMEvent(document,"selectionchange",this.handleDocumentSelectionChange.bind(this)),this.attachToExecCommand());break;case"editableClick":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"click",this.handleClick.bind(this))}.bind(this));break;case"editableBlur":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"blur",this.handleBlur.bind(this))}.bind(this));break;case"editableKeypress":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"keypress",this.handleKeypress.bind(this))}.bind(this));break;case"editableKeyup":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"keyup",this.handleKeyup.bind(this))}.bind(this));break;case"editableKeydown":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"keydown",this.handleKeydown.bind(this))}.bind(this));break;case"editableKeydownEnter":this.setupListener("editableKeydown");break;case"editableKeydownTab":this.setupListener("editableKeydown");break;case"editableKeydownDelete":this.setupListener("editableKeydown");break;case"editableMouseover":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"mouseover",this.handleMouseover.bind(this))},this);break;case"editableDrag":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"dragover",this.handleDragging.bind(this)),this.attachDOMEvent(a,"dragleave",this.handleDragging.bind(this))},this);break;case"editableDrop":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"drop",this.handleDrop.bind(this))},this);break;case"editablePaste":this.base.elements.forEach(function(a){this.attachDOMEvent(a,"paste",this.handlePaste.bind(this))},this)}this.listeners[a]=!0}},focusElement:function(a){a.focus(),this.updateFocus(a,{target:a,type:"focus"})},updateFocus:function(a,c){var d,e=this.base.getExtensionByName("toolbar"),f=e?e.getToolbarElement():null,g=this.base.getExtensionByName("anchor-preview"),h=g&&g.getPreviewElement?g.getPreviewElement():null,i=this.base.getFocusedElement();i&&"click"===c.type&&this.lastMousedownTarget&&(b.isDescendant(i,this.lastMousedownTarget,!0)||b.isDescendant(f,this.lastMousedownTarget,!0)||b.isDescendant(h,this.lastMousedownTarget,!0))&&(d=i),d||this.base.elements.some(function(c){return!d&&b.isDescendant(c,a,!0)&&(d=c),!!d},this);var j=!b.isDescendant(i,a,!0)&&!b.isDescendant(f,a,!0)&&!b.isDescendant(h,a,!0);d!==i&&(i&&j&&(i.removeAttribute("data-medium-focused"),this.triggerCustomEvent("blur",c,i)),d&&(d.setAttribute("data-medium-focused",!0),this.triggerCustomEvent("focus",c,d))),j&&this.triggerCustomEvent("externalInteraction",c)},updateInput:function(a,b){var c=a.getAttribute("medium-editor-index");a.innerHTML!==this.contentCache[c]&&this.triggerCustomEvent("editableInput",b,a),this.contentCache[c]=a.innerHTML},handleDocumentSelectionChange:function(a){if(a.currentTarget&&a.currentTarget.activeElement){var c,d=a.currentTarget.activeElement;this.base.elements.some(function(a){return b.isDescendant(a,d,!0)?(c=a,!0):!1},this),c&&this.updateInput(c,{target:d,currentTarget:c})}},handleDocumentExecCommand:function(){var a=this.base.getFocusedElement();a&&this.updateInput(a,{target:a,currentTarget:a})},handleBodyClick:function(a){this.updateFocus(a.target,a)},handleBodyFocus:function(a){this.updateFocus(a.target,a)},handleBodyMousedown:function(a){this.lastMousedownTarget=a.target},handleInput:function(a){this.updateInput(a.currentTarget,a)},handleClick:function(a){this.triggerCustomEvent("editableClick",a,a.currentTarget)},handleBlur:function(a){this.triggerCustomEvent("editableBlur",a,a.currentTarget)},handleKeypress:function(a){if(this.triggerCustomEvent("editableKeypress",a,a.currentTarget),this.keypressUpdateInput){var b={target:a.target,currentTarget:a.currentTarget};setTimeout(function(){this.updateInput(b.currentTarget,b)}.bind(this),0)}},handleKeyup:function(a){this.triggerCustomEvent("editableKeyup",a,a.currentTarget)},handleMouseover:function(a){this.triggerCustomEvent("editableMouseover",a,a.currentTarget)},handleDragging:function(a){this.triggerCustomEvent("editableDrag",a,a.currentTarget)},handleDrop:function(a){this.triggerCustomEvent("editableDrop",a,a.currentTarget)},handlePaste:function(a){this.triggerCustomEvent("editablePaste",a,a.currentTarget)},handleKeydown:function(a){return this.triggerCustomEvent("editableKeydown",a,a.currentTarget),b.isKey(a,b.keyCode.ENTER)?this.triggerCustomEvent("editableKeydownEnter",a,a.currentTarget):b.isKey(a,b.keyCode.TAB)?this.triggerCustomEvent("editableKeydownTab",a,a.currentTarget):b.isKey(a,[b.keyCode.DELETE,b.keyCode.BACKSPACE])?this.triggerCustomEvent("editableKeydownDelete",a,a.currentTarget):void 0}}}();var h;!function(){h=e.extend({action:void 0,aria:void 0,tagNames:void 0,style:void 0,useQueryState:void 0,contentDefault:void 0,contentFA:void 0,defaults:c,constructor:function(a){h.isBuiltInButton(a)?e.call(this,this.defaults[a]):e.call(this,a)},init:function(){e.prototype.init.apply(this,arguments),this.button=this.createButton(),this.on(this.button,"click",this.handleClick.bind(this))},getButton:function(){return this.button},getAction:function(){return"function"==typeof this.action?this.action(this.base.options):this.action},getAria:function(){return"function"==typeof this.aria?this.aria(this.base.options):this.aria},getTagNames:function(){return"function"==typeof this.tagNames?this.tagNames(this.base.options):this.tagNames},createButton:function(){var a=this.document.createElement("button"),b=this.contentDefault,c=this.getAria(),d=this.getEditorOption("buttonLabels");return a.classList.add("medium-editor-action"),a.classList.add("medium-editor-action-"+this.name),a.setAttribute("data-action",this.getAction()),c&&(a.setAttribute("title",c),a.setAttribute("aria-label",c)),d&&("fontawesome"===d&&this.contentFA?b=this.contentFA:"object"==typeof d&&d[this.name]&&(b=d[this.name])),a.innerHTML=b,a},handleClick:function(a){a.preventDefault(),a.stopPropagation();var b=this.getAction();b&&this.execAction(b)},isActive:function(){return this.button.classList.contains(this.getEditorOption("activeButtonClass"))},setInactive:function(){this.button.classList.remove(this.getEditorOption("activeButtonClass")),delete this.knownState},setActive:function(){this.button.classList.add(this.getEditorOption("activeButtonClass")),delete this.knownState},queryCommandState:function(){var a=null;return this.useQueryState&&(a=this.base.queryCommandState(this.getAction())),a},isAlreadyApplied:function(a){var b,c,d=!1,e=this.getTagNames();return this.knownState===!1||this.knownState===!0?this.knownState:(e&&e.length>0&&a.tagName&&(d=-1!==e.indexOf(a.tagName.toLowerCase())),!d&&this.style&&(b=this.style.value.split("|"),c=this.window.getComputedStyle(a,null).getPropertyValue(this.style.prop),b.forEach(function(a){this.knownState||(d=-1!==c.indexOf(a),(d||"text-decoration"!==this.style.prop)&&(this.knownState=d))},this)),d)}}),h.isBuiltInButton=function(a){return"string"==typeof a&&h.prototype.defaults.hasOwnProperty(a)}}();var i;!function(){var a=function(){};i=h.extend({init:function(){h.prototype.init.apply(this,arguments)},formSaveLabel:"✓",formCloseLabel:"×",hasForm:!0,getForm:a,isDisplayed:a,hideForm:a,hideToolbarDefaultActions:function(){var a=this.base.getExtensionByName("toolbar");a&&a.hideToolbarDefaultActions()},setToolbarPosition:function(){var a=this.base.getExtensionByName("toolbar");a&&a.setToolbarPosition()}})}();var j;!function(){j=i.extend({customClassOption:null,customClassOptionText:"Button",linkValidation:!1,placeholderText:"Paste or type a link",targetCheckbox:!1,targetCheckboxText:"Open in new window",name:"anchor",action:"createLink",aria:"link",tagNames:["a"],contentDefault:"#",contentFA:'',init:function(){i.prototype.init.apply(this,arguments),this.subscribe("editableKeydown",this.handleKeydown.bind(this))},handleClick:function(a){a.preventDefault(),a.stopPropagation();var b=f.getSelectedParentElement(f.getSelectionRange(this.document));return b.tagName&&"a"===b.tagName.toLowerCase()?this.execAction("unlink"):(this.isDisplayed()||this.showForm(),!1)},handleKeydown:function(a){b.isKey(a,b.keyCode.K)&&b.isMetaCtrlKey(a)&&!a.shiftKey&&this.handleClick(a)},getForm:function(){return this.form||(this.form=this.createForm()),this.form},getTemplate:function(){var a=[''];return a.push('
',"fontawesome"===this.getEditorOption("buttonLabels")?'':this.formSaveLabel,""),a.push('',"fontawesome"===this.getEditorOption("buttonLabels")?'':this.formCloseLabel,""),this.targetCheckbox&&a.push('',""),this.customClassOption&&a.push('',""),a.join("")},isDisplayed:function(){return"block"===this.getForm().style.display},hideForm:function(){this.getForm().style.display="none",this.getInput().value=""},showForm:function(a){var b=this.getInput();this.base.saveSelection(),this.hideToolbarDefaultActions(),this.getForm().style.display="block", +this.setToolbarPosition(),b.value=a||"",b.focus()},destroy:function(){return this.form?(this.form.parentNode&&this.form.parentNode.removeChild(this.form),void delete this.form):!1},getFormOpts:function(){var a=this.getForm().querySelector(".medium-editor-toolbar-anchor-target"),b=this.getForm().querySelector(".medium-editor-toolbar-anchor-button"),c={url:this.getInput().value};return this.linkValidation&&(c.url=this.checkLinkFormat(c.url)),c.target="_self",a&&a.checked&&(c.target="_blank"),b&&b.checked&&(c.buttonClass=this.customClassOption),c},doFormSave:function(){var a=this.getFormOpts();this.completeFormSave(a)},completeFormSave:function(a){this.base.restoreSelection(),this.execAction(this.action,a),this.base.checkSelection()},checkLinkFormat:function(a){var b=/^(https?|ftps?|rtmpt?):\/\/|mailto:/;return(b.test(a)?"":"http://")+a},doFormCancel:function(){this.base.restoreSelection(),this.base.checkSelection()},attachFormEvents:function(a){var b=a.querySelector(".medium-editor-toolbar-close"),c=a.querySelector(".medium-editor-toolbar-save"),d=a.querySelector(".medium-editor-toolbar-input");this.on(a,"click",this.handleFormClick.bind(this)),this.on(d,"keyup",this.handleTextboxKeyup.bind(this)),this.on(b,"click",this.handleCloseClick.bind(this)),this.on(c,"click",this.handleSaveClick.bind(this),!0)},createForm:function(){var a=this.document,b=a.createElement("div");return b.className="medium-editor-toolbar-form",b.id="medium-editor-toolbar-form-anchor-"+this.getEditorId(),b.innerHTML=this.getTemplate(),this.attachFormEvents(b),b},getInput:function(){return this.getForm().querySelector("input.medium-editor-toolbar-input")},handleTextboxKeyup:function(a){return a.keyCode===b.keyCode.ENTER?(a.preventDefault(),void this.doFormSave()):void(a.keyCode===b.keyCode.ESCAPE&&(a.preventDefault(),this.doFormCancel()))},handleFormClick:function(a){a.stopPropagation()},handleSaveClick:function(a){a.preventDefault(),this.doFormSave()},handleCloseClick:function(a){a.preventDefault(),this.doFormCancel()}})}();var k;!function(){k=e.extend({name:"anchor-preview",hideDelay:500,previewValueSelector:"a",init:function(){this.anchorPreview=this.createPreview(),this.getEditorOption("elementsContainer").appendChild(this.anchorPreview),this.attachToEditables()},getPreviewElement:function(){return this.anchorPreview},createPreview:function(){var a=this.document.createElement("div");return a.id="medium-editor-anchor-preview-"+this.getEditorId(),a.className="medium-editor-anchor-preview",a.innerHTML=this.getTemplate(),this.on(a,"click",this.handleClick.bind(this)),a},getTemplate:function(){return'
'},destroy:function(){this.anchorPreview&&(this.anchorPreview.parentNode&&this.anchorPreview.parentNode.removeChild(this.anchorPreview),delete this.anchorPreview)},hidePreview:function(){this.anchorPreview.classList.remove("medium-editor-anchor-preview-active"),this.activeAnchor=null},showPreview:function(a){return this.anchorPreview.classList.contains("medium-editor-anchor-preview-active")||a.getAttribute("data-disable-preview")?!0:(this.previewValueSelector&&(this.anchorPreview.querySelector(this.previewValueSelector).textContent=a.attributes.href.value,this.anchorPreview.querySelector(this.previewValueSelector).href=a.attributes.href.value),this.anchorPreview.classList.add("medium-toolbar-arrow-over"),this.anchorPreview.classList.remove("medium-toolbar-arrow-under"),this.anchorPreview.classList.contains("medium-editor-anchor-preview-active")||this.anchorPreview.classList.add("medium-editor-anchor-preview-active"),this.activeAnchor=a,this.positionPreview(),this.attachPreviewHandlers(),this)},positionPreview:function(){var a,b,c=this.anchorPreview.offsetHeight,d=this.activeAnchor.getBoundingClientRect(),e=(d.left+d.right)/2,f=this.diffLeft,g=this.diffTop;a=this.anchorPreview.offsetWidth/2;var h=this.base.getExtensionByName("toolbar");h&&(f=h.diffLeft,g=h.diffTop),b=f-a,this.anchorPreview.style.top=Math.round(c+d.bottom-g+this.window.pageYOffset-this.anchorPreview.offsetHeight)+"px",a>e?this.anchorPreview.style.left=b+a+"px":this.window.innerWidth-ethis.hideDelay&&this.detachPreviewHandlers()},detachPreviewHandlers:function(){clearInterval(this.intervalTimer),this.instanceHandlePreviewMouseover&&(this.off(this.anchorPreview,"mouseover",this.instanceHandlePreviewMouseover),this.off(this.anchorPreview,"mouseout",this.instanceHandlePreviewMouseout),this.activeAnchor&&(this.off(this.activeAnchor,"mouseover",this.instanceHandlePreviewMouseover),this.off(this.activeAnchor,"mouseout",this.instanceHandlePreviewMouseout))),this.hidePreview(),this.hovering=this.instanceHandlePreviewMouseover=this.instanceHandlePreviewMouseout=null},attachPreviewHandlers:function(){this.lastOver=(new Date).getTime(),this.hovering=!0,this.instanceHandlePreviewMouseover=this.handlePreviewMouseover.bind(this),this.instanceHandlePreviewMouseout=this.handlePreviewMouseout.bind(this),this.intervalTimer=setInterval(this.updatePreview.bind(this),200),this.on(this.anchorPreview,"mouseover",this.instanceHandlePreviewMouseover),this.on(this.anchorPreview,"mouseout",this.instanceHandlePreviewMouseout),this.on(this.activeAnchor,"mouseover",this.instanceHandlePreviewMouseover),this.on(this.activeAnchor,"mouseout",this.instanceHandlePreviewMouseout)}})}();var l,m,n;m="com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw",n="(((?:(https?://|ftps?://|nntp://)|www\\d{0,3}[.]|[a-z0-9.\\-]+[.]("+m+")\\/)\\S+(?:[^\\s`!\\[\\]{};:'\".,?«»“”‘’])))|(([a-z0-9\\-]+\\.)?[a-z0-9\\-]+\\.("+m+"))",function(){function a(a){return!b.getClosestTag(a,"a")}var c=new RegExp("^("+m+")$","i");l=e.extend({init:function(){e.prototype.init.apply(this,arguments),this.disableEventHandling=!1,this.subscribe("editableKeypress",this.onKeypress.bind(this)),this.subscribe("editableBlur",this.onBlur.bind(this)),this.document.execCommand("AutoUrlDetect",!1,!1)},destroy:function(){this.document.queryCommandSupported("AutoUrlDetect")&&this.document.execCommand("AutoUrlDetect",!1,!0)},onBlur:function(a,b){this.performLinking(b)},onKeypress:function(a){this.disableEventHandling||b.isKey(a,[b.keyCode.SPACE,b.keyCode.ENTER])&&(clearTimeout(this.performLinkingTimeout),this.performLinkingTimeout=setTimeout(function(){try{var b=this.base.exportSelection();this.performLinking(a.target)&&this.base.importSelection(b,!0)}catch(c){window.console&&window.console.error("Failed to perform linking",c),this.disableEventHandling=!0}}.bind(this),0))},performLinking:function(a){var b=a.querySelectorAll("p"),c=!1;0===b.length&&(b=[a]);for(var d=0;d=c&&d!==e&&0!==f&&(b||a).splitText(f)},removeObsoleteAutoLinkSpans:function(c){for(var d=c.querySelectorAll('span[data-auto-link="true"]'),e=!1,f=0;f0;)d[f].parentNode.insertBefore(d[f].firstChild,d[f]);d[f].parentNode.removeChild(d[f])}}return e},performLinkingWithinElement:function(a){for(var b=this.findLinkableText(a),c=!1,d=0;db.end+1)throw new Error("PerformLinking overshot the target!");f&&d.push(h||g),e+=g.nodeValue.length,null!==h&&(e+=h.nodeValue.length,c.nextNode()),h=null}return d},createLink:function(a,c){for(var d=!1,e=0;e'),c.onload=function(){var a=this.document.getElementById(d);a&&(a.removeAttribute("id"),a.removeAttribute("class"),a.src=c.result)}.bind(this)}}.bind(this))),a.target.classList.remove(d)}})}();var p;!function(){p=e.extend({name:"keyboard-commands",commands:[{command:"bold",key:"b",meta:!0,shift:!1},{command:"italic",key:"i",meta:!0,shift:!1},{command:"underline",key:"u",meta:!0,shift:!1}],init:function(){e.prototype.init.apply(this,arguments),this.subscribe("editableKeydown",this.handleKeydown.bind(this)),this.keys={},this.commands.forEach(function(a){var b=a.key.charCodeAt(0);this.keys[b]||(this.keys[b]=[]),this.keys[b].push(a)},this)},handleKeydown:function(a){var c=b.getKeyCode(a);if(this.keys[c]){var d=b.isMetaCtrlKey(a),e=!!a.shiftKey;this.keys[c].forEach(function(b){b.meta===d&&b.shift===e&&(a.preventDefault(),a.stopPropagation(),this.execAction(b.command))},this)}}})}();var q;!function(){q=i.extend({name:"fontsize",action:"fontSize",aria:"increase/decrease font size",contentDefault:"±",contentFA:'',init:function(){i.prototype.init.apply(this,arguments)},handleClick:function(a){if(a.preventDefault(),a.stopPropagation(),!this.isDisplayed()){var b=this.document.queryCommandValue("fontSize")+"";this.showForm(b)}return!1},getForm:function(){return this.form||(this.form=this.createForm()),this.form},isDisplayed:function(){return"block"===this.getForm().style.display},hideForm:function(){this.getForm().style.display="none",this.getInput().value=""},showForm:function(a){var b=this.getInput();this.base.saveSelection(),this.hideToolbarDefaultActions(),this.getForm().style.display="block",this.setToolbarPosition(),b.value=a||"",b.focus()},destroy:function(){return this.form?(this.form.parentNode&&this.form.parentNode.removeChild(this.form),void delete this.form):!1},doFormSave:function(){this.base.restoreSelection(),this.base.checkSelection()},doFormCancel:function(){this.base.restoreSelection(),this.clearFontSize(),this.base.checkSelection()},createForm:function(){var a=this.document,b=a.createElement("div"),c=a.createElement("input"),d=a.createElement("a"),e=a.createElement("a");return b.className="medium-editor-toolbar-form",b.id="medium-editor-toolbar-form-fontsize-"+this.getEditorId(),this.on(b,"click",this.handleFormClick.bind(this)),c.setAttribute("type","range"),c.setAttribute("min","1"),c.setAttribute("max","7"),c.className="medium-editor-toolbar-input",b.appendChild(c),this.on(c,"change",this.handleSliderChange.bind(this)),e.setAttribute("href","#"),e.className="medium-editor-toobar-save",e.innerHTML="fontawesome"===this.getEditorOption("buttonLabels")?'':"✓",b.appendChild(e),this.on(e,"click",this.handleSaveClick.bind(this),!0),d.setAttribute("href","#"),d.className="medium-editor-toobar-close",d.innerHTML="fontawesome"===this.getEditorOption("buttonLabels")?'':"×",b.appendChild(d),this.on(d,"click",this.handleCloseClick.bind(this)),b},getInput:function(){return this.getForm().querySelector("input.medium-editor-toolbar-input")},clearFontSize:function(){f.getSelectedElements(this.document).forEach(function(a){"FONT"===a.tagName&&a.hasAttribute("size")&&a.removeAttribute("size")})},handleSliderChange:function(){var a=this.getInput().value;"4"===a?this.clearFontSize():this.execAction("fontSize",{size:a})},handleFormClick:function(a){a.stopPropagation()},handleSaveClick:function(a){a.preventDefault(),this.doFormSave()},handleCloseClick:function(a){a.preventDefault(),this.doFormCancel()}})}();var r;!function(){function a(){return[[new RegExp(/<[^>]*docs-internal-guid[^>]*>/gi),""],[new RegExp(/<\/b>(]*>)?$/gi),""],[new RegExp(/\s+<\/span>/g)," "],[new RegExp(/
/g),"
"],[new RegExp(/]*(font-style:italic;font-weight:bold|font-weight:bold;font-style:italic)[^>]*>/gi),''],[new RegExp(/]*font-style:italic[^>]*>/gi),''],[new RegExp(/]*font-weight:bold[^>]*>/gi),''],[new RegExp(/<(\/?)(i|b|a)>/gi),"<$1$2>"],[new RegExp(/<a(?:(?!href).)+href=(?:"|”|“|"|“|”)(((?!"|”|“|"|“|”).)*)(?:"|”|“|"|“|”)(?:(?!>).)*>/gi),''],[new RegExp(/<\/p>\n+/gi),"

"],[new RegExp(/\n+

/gi),""]]}r=e.extend({forcePlainText:!0,cleanPastedHTML:!1,cleanReplacements:[],cleanAttrs:["class","style","dir"],cleanTags:["meta"],init:function(){e.prototype.init.apply(this,arguments),(this.forcePlainText||this.cleanPastedHTML)&&this.subscribe("editablePaste",this.handlePaste.bind(this))},handlePaste:function(a,c){var d,e,f,g,h="",i="text/html",j="text/plain";if(this.window.clipboardData&&void 0===a.clipboardData&&(a.clipboardData=this.window.clipboardData,i="Text",j="Text"),a.clipboardData&&a.clipboardData.getData&&!a.defaultPrevented){if(a.preventDefault(),f=a.clipboardData.getData(i),g=a.clipboardData.getData(j),this.cleanPastedHTML&&f)return this.cleanPaste(f);if(this.getEditorOption("disableReturn")||c.getAttribute("data-disable-return"))h=b.htmlEntities(g);else if(d=g.split(/[\r\n]+/g),d.length>1)for(e=0;e"+b.htmlEntities(d[e])+"

");else h=b.htmlEntities(d[0]);b.insertHTMLCommand(this.document,h)}},cleanPaste:function(b){var c,d,e,g=f.getSelectionElement(this.window),h=/
"),this.pasteHTML("

"+d.join("

")+"

");try{this.document.execCommand("insertText",!1,"\n")}catch(j){}for(d=g.querySelectorAll("a,p,div,br"),c=0;c"+d.innerHTML+"":e.innerHTML=d.innerHTML,d.parentNode.replaceChild(e,d);for(f=a.querySelectorAll("span"),c=0;c0&&(d[0].classList.add(this.firstButtonClass),d[d.length-1].classList.add(this.lastButtonClass)),f},destroy:function(){this.toolbar&&(this.toolbar.parentNode&&this.toolbar.parentNode.removeChild(this.toolbar),delete this.toolbar)},getToolbarElement:function(){return this.toolbar||(this.toolbar=this.createToolbar()),this.toolbar},getToolbarActionsElement:function(){return this.getToolbarElement().querySelector(".medium-editor-toolbar-actions")},initThrottledMethods:function(){this.throttledPositionToolbar=b.throttle(function(){this.base.isActive&&this.positionToolbarIfShown()}.bind(this))},attachEventHandlers:function(){this.subscribe("blur",this.handleBlur.bind(this)),this.subscribe("focus",this.handleFocus.bind(this)),this.subscribe("editableClick",this.handleEditableClick.bind(this)),this.subscribe("editableKeyup",this.handleEditableKeyup.bind(this)),this.on(this.document.documentElement,"mouseup",this.handleDocumentMouseup.bind(this)),this["static"]&&this.sticky&&this.on(this.window,"scroll",this.handleWindowScroll.bind(this),!0),this.on(this.window,"resize",this.handleWindowResize.bind(this))},handleWindowScroll:function(){this.positionToolbarIfShown()},handleWindowResize:function(){this.throttledPositionToolbar()},handleDocumentMouseup:function(a){return a&&a.target&&b.isDescendant(this.getToolbarElement(),a.target)?!1:void this.checkState()},handleEditableClick:function(){setTimeout(function(){this.checkState()}.bind(this),0)},handleEditableKeyup:function(){this.checkState()},handleBlur:function(){clearTimeout(this.hideTimeout),clearTimeout(this.delayShowTimeout),this.hideTimeout=setTimeout(function(){this.hideToolbar()}.bind(this),1)},handleFocus:function(){this.checkState()},isDisplayed:function(){return this.getToolbarElement().classList.contains("medium-editor-toolbar-active")},showToolbar:function(){clearTimeout(this.hideTimeout),this.isDisplayed()||(this.getToolbarElement().classList.add("medium-editor-toolbar-active"),this.trigger("showToolbar",{},this.base.getFocusedElement()))},hideToolbar:function(){this.isDisplayed()&&(this.getToolbarElement().classList.remove("medium-editor-toolbar-active"),this.trigger("hideToolbar",{},this.base.getFocusedElement()))},isToolbarDefaultActionsDisplayed:function(){return"block"===this.getToolbarActionsElement().style.display},hideToolbarDefaultActions:function(){this.isToolbarDefaultActionsDisplayed()&&(this.getToolbarActionsElement().style.display="none")},showToolbarDefaultActions:function(){this.hideExtensionForms(),this.isToolbarDefaultActionsDisplayed()||(this.getToolbarActionsElement().style.display="block"),this.delayShowTimeout=this.base.delay(function(){this.showToolbar()}.bind(this))},hideExtensionForms:function(){this.forEachExtension(function(a){a.hasForm&&a.isDisplayed()&&a.hideForm()})},multipleBlockElementsSelected:function(){var a=f.getSelectionHtml(this.document).replace(/<[\S]+><\/[\S]+>/gim,""),b=a.match(/<(p|h[1-6]|blockquote)[^>]*>/g);return!!b&&b.length>1},modifySelection:function(){var a=this.window.getSelection(),c=a.getRangeAt(0);if(this.standardizeSelectionStart&&c.startContainer.nodeValue&&c.startOffset===c.startContainer.nodeValue.length){var d=b.findAdjacentTextNodeWithContent(f.getSelectionElement(this.window),c.startContainer,this.document);if(d){for(var e=0;0===d.nodeValue.substr(e,1).trim().length;)e+=1;var g=this.document.createRange();g.setStart(d,e),g.setEnd(c.endContainer,c.endOffset),a.removeAllRanges(),a.addRange(g),c=g}}},checkState:function(){if(!this.base.preventSelectionUpdates){if(!this.base.getFocusedElement()||f.selectionInContentEditableFalse(this.window))return this.hideToolbar();var a=f.getSelectionElement(this.window);return!a||-1===this.getEditorElements().indexOf(a)||a.getAttribute("data-disable-toolbar")?this.hideToolbar():this.updateOnEmptySelection&&this["static"]?this.showAndUpdateToolbar():""===this.window.getSelection().toString().trim()||this.getEditorOption("allowMultiParagraphSelection")===!1&&this.multipleBlockElementsSelected()?this.hideToolbar():void this.showAndUpdateToolbar()}},showAndUpdateToolbar:function(){this.modifySelection(),this.setToolbarButtonStates(),this.trigger("positionToolbar",{},this.base.getFocusedElement()),this.showToolbarDefaultActions(),this.setToolbarPosition()},setToolbarButtonStates:function(){this.forEachExtension(function(a){"function"==typeof a.isActive&&"function"==typeof a.setInactive&&a.setInactive()}),this.checkActiveButtons()},checkActiveButtons:function(){var a,c=[],d=null,e=f.getSelectionRange(this.document),g=function(b){"function"==typeof b.checkState?b.checkState(a):"function"==typeof b.isActive&&"function"==typeof b.isAlreadyApplied&&"function"==typeof b.setActive&&!b.isActive()&&b.isAlreadyApplied(a)&&b.setActive()};if(e)for(a=f.getSelectedParentElement(e),this.forEachExtension(function(a){return"function"==typeof a.queryCommandState&&(d=a.queryCommandState(),null!==d)?void(d&&"function"==typeof a.setActive&&a.setActive()):void c.push(a)});void 0!==a.tagName&&-1===b.parentElements.indexOf(a.tagName.toLowerCase)&&(c.forEach(g),-1===this.getEditorElements().indexOf(a));)a=a.parentNode},positionToolbarIfShown:function(){this.isDisplayed()&&this.setToolbarPosition()},setToolbarPosition:function(){var a,b=this.base.getFocusedElement(),c=this.window.getSelection();return b?(this["static"]?(this.showToolbar(),this.positionStaticToolbar(b)):c.isCollapsed||(this.showToolbar(),this.positionToolbar(c)),a=this.base.getExtensionByName("anchor-preview"),void(a&&"function"==typeof a.hidePreview&&a.hidePreview())):this},positionStaticToolbar:function(a){this.getToolbarElement().style.left="0";var b,c=this.document.documentElement&&this.document.documentElement.scrollTop||this.document.body.scrollTop,d=this.window.innerWidth,e=this.getToolbarElement(),f=a.getBoundingClientRect(),g=f.top+c,h=f.left+f.width/2,i=e.offsetHeight,j=e.offsetWidth,k=j/2;switch(this.sticky?c>g+a.offsetHeight-i?(e.style.top=g+a.offsetHeight-i+"px",e.classList.remove("medium-editor-sticky-toolbar")):c>g-i?(e.classList.add("medium-editor-sticky-toolbar"),e.style.top="0px"):(e.classList.remove("medium-editor-sticky-toolbar"),e.style.top=g-i+"px"):e.style.top=g-i+"px",this.align){case"left":b=f.left;break;case"right":b=f.right-j;break;case"center":b=h-k}0>b?b=0:b+j>d&&(b=d-Math.ceil(j)-1),e.style.left=b+"px"},positionToolbar:function(a){this.getToolbarElement().style.left="0";var b=this.window.innerWidth,c=a.getRangeAt(0),d=c.getBoundingClientRect(),e=(d.left+d.right)/2,f=this.getToolbarElement(),g=f.offsetHeight,h=f.offsetWidth,i=h/2,j=50,k=this.diffLeft-i;d.tope?f.style.left=k+i+"px":i>b-e?f.style.left=b+k-i+"px":f.style.left=k+e+"px"}})}();var u;return function(){u={button:h,form:i,anchor:j,anchorPreview:k,autoLink:l,fontSize:q,imageDragging:o,keyboardCommands:p,paste:r,placeholder:s,toolbar:t}}(),function(){function c(a,b){if(this.options.disableReturn||b.getAttribute("data-disable-return"))a.preventDefault();else if(this.options.disableDoubleReturn||b.getAttribute("data-disable-double-return")){var c=f.getSelectionStart(this.options.ownerDocument);(c&&""===c.textContent.trim()||c.previousElementSibling&&""===c.previousElementSibling.textContent.trim())&&a.preventDefault()}}function h(a){var c=f.getSelectionStart(this.options.ownerDocument),d=c&&c.tagName.toLowerCase();"pre"===d&&(a.preventDefault(),b.insertHTMLCommand(this.options.ownerDocument," ")),b.isListItem(c)&&(a.preventDefault(),a.shiftKey?this.options.ownerDocument.execCommand("outdent",!1,null):this.options.ownerDocument.execCommand("indent",!1,null))}function i(a){var c,d=f.getSelectionStart(this.options.ownerDocument),e=d.tagName.toLowerCase(),g=/^(\s+|)?$/i,h=/h\d/i;b.isKey(a,[b.keyCode.BACKSPACE,b.keyCode.ENTER])&&d.previousElementSibling&&h.test(e)&&0===f.getCaretOffsets(d).left?b.isKey(a,b.keyCode.BACKSPACE)&&g.test(d.previousElementSibling.innerHTML)?(d.previousElementSibling.parentNode.removeChild(d.previousElementSibling),a.preventDefault()):b.isKey(a,b.keyCode.ENTER)&&(c=this.options.ownerDocument.createElement("p"),c.innerHTML="
",d.previousElementSibling.parentNode.insertBefore(c,d),a.preventDefault()):b.isKey(a,b.keyCode.DELETE)&&d.nextElementSibling&&d.previousElementSibling&&!h.test(e)&&g.test(d.innerHTML)&&h.test(d.nextElementSibling.tagName)?(f.moveCursor(this.options.ownerDocument,d.nextElementSibling),d.previousElementSibling.parentNode.removeChild(d),a.preventDefault()):b.isKey(a,b.keyCode.BACKSPACE)&&"li"===e&&g.test(d.innerHTML)&&!d.previousElementSibling&&!d.parentElement.previousElementSibling&&d.nextElementSibling&&"li"===d.nextElementSibling.tagName.toLowerCase()&&(c=this.options.ownerDocument.createElement("p"), +c.innerHTML="
",d.parentElement.parentElement.insertBefore(c,d.parentElement),f.moveCursor(this.options.ownerDocument,c),d.parentElement.removeChild(d),a.preventDefault())}function j(a){var c,d=f.getSelectionStart(this.options.ownerDocument);d&&(d.getAttribute("data-medium-editor-element")&&0===d.children.length&&this.options.ownerDocument.execCommand("formatBlock",!1,"p"),b.isKey(a,b.keyCode.ENTER)&&!b.isListItem(d)&&(c=d.tagName.toLowerCase(),"a"===c?this.options.ownerDocument.execCommand("unlink",!1,null):a.shiftKey||a.ctrlKey||/h\d/.test(c)||this.options.ownerDocument.execCommand("formatBlock",!1,"p")))}function k(a){a._mediumEditors||(a._mediumEditors=[null]),this.id||(this.id=a._mediumEditors.length),a._mediumEditors[this.id]=this}function l(a){a._mediumEditors&&a._mediumEditors[this.id]&&(a._mediumEditors[this.id]=null)}function m(a){a||(a=[]),"string"==typeof a&&(a=this.options.ownerDocument.querySelectorAll(a)),b.isElement(a)&&(a=[a]);var c=Array.prototype.slice.apply(a);this.elements=[],c.forEach(function(a){this.elements.push("textarea"===a.tagName.toLowerCase()?w.call(this,a):a)},this)}function n(a,b){return Object.keys(b).forEach(function(c){void 0===a[c]&&(a[c]=b[c])}),a}function o(a,b,c){var d={window:c.options.contentWindow,document:c.options.ownerDocument,base:c};return a=n(a,d),"function"==typeof a.init&&a.init(),a.name||(a.name=b),a}function p(){return this.elements.every(function(a){return!!a.getAttribute("data-disable-toolbar")})?!1:this.options.toolbar!==!1}function q(){return p.call(this)?this.options.anchorPreview!==!1:!1}function r(){return this.options.placeholder!==!1}function s(){return this.options.autoLink!==!1}function t(){return this.options.imageDragging!==!1}function v(){return this.options.keyboardCommands!==!1}function w(a){var b=this.options.ownerDocument.createElement("div"),c=+new Date,d=["data-disable-editing","data-disable-toolbar","data-placeholder","data-disable-return","data-disable-double-return","data-disable-preview","spellcheck"];return b.className=a.className,b.id=c,b.innerHTML=a.value,b.setAttribute("medium-editor-textarea-id",c),d.forEach(function(c){a.hasAttribute(c)&&b.setAttribute(c,a.getAttribute(c))}),a.classList.add("medium-editor-hidden"),a.setAttribute("medium-editor-textarea-id",c),a.parentNode.insertBefore(b,a),b}function x(){this.elements.forEach(function(a,b){this.options.disableEditing||a.getAttribute("data-disable-editing")||(a.setAttribute("contentEditable",!0),a.setAttribute("spellcheck",this.options.spellcheck)),a.setAttribute("data-medium-editor-element",!0),a.setAttribute("role","textbox"),a.setAttribute("aria-multiline",!0),a.setAttribute("medium-editor-index",b),a.hasAttribute("medium-editor-textarea-id")&&this.on(a,"input",function(a){var b=a.target,c=b.parentNode.querySelector('textarea[medium-editor-textarea-id="'+b.getAttribute("medium-editor-textarea-id")+'"]');c&&(c.value=this.serialize()[b.id].value)}.bind(this))},this)}function y(){var a;if(this.subscribe("editableKeydownTab",h.bind(this)),this.subscribe("editableKeydownDelete",i.bind(this)),this.subscribe("editableKeydownEnter",i.bind(this)),this.options.disableReturn||this.options.disableDoubleReturn)this.subscribe("editableKeydownEnter",c.bind(this));else for(a=0;a0&&(a=f.getRangeAt(0),c=a.cloneRange(),this.elements.some(function(c,d){return c===a.startContainer||b.isDescendant(c,a.startContainer)?(g=d,!0):!1}),g>-1&&(c.selectNodeContents(this.elements[g]),c.setEnd(a.startContainer,a.startOffset),d=c.toString().length,e={start:d,end:d+a.toString().length,editableElementIndex:g})),null!==e&&0===e.editableElementIndex&&delete e.editableElementIndex,e},saveSelection:function(){this.selectionState=this.exportSelection()},importSelection:function(a,b){if(a){var c,d,e,g,h=void 0===a.editableElementIndex?0:a.editableElementIndex,i={editableElementIndex:h,start:a.start,end:a.end},j=this.elements[i.editableElementIndex],k=0,l=this.options.ownerDocument.createRange(),m=[j],n=!1,o=!1;for(l.setStart(j,0),l.collapse(!0),c=m.pop();!o&&c;){if(3===c.nodeType)g=k+c.length,!n&&i.start>=k&&i.start<=g&&(l.setStart(c,i.start-k),n=!0),n&&i.end>=k&&i.end<=g&&(l.setEnd(c,i.end-k),o=!0),k=g;else for(d=c.childNodes.length-1;d>=0;)m.push(c.childNodes[d]),d-=1;o||(c=m.pop())}b&&(l=f.importSelectionMoveCursorPastAnchor(i,l)),e=this.options.contentWindow.getSelection(),e.removeAllRanges(),e.addRange(l)}},restoreSelection:function(){this.importSelection(this.selectionState)},createLink:function(a){var c,d;if(a.url&&a.url.trim().length>0&&(this.options.ownerDocument.execCommand("createLink",!1,a.url),(this.options.targetBlank||"_blank"===a.target)&&b.setTargetBlank(f.getSelectionStart(this.options.ownerDocument),a.url),a.buttonClass&&b.addClassToAnchors(f.getSelectionStart(this.options.ownerDocument),a.buttonClass)),this.options.targetBlank||"_blank"===a.target||a.buttonClass)for(c=this.options.ownerDocument.createEvent("HTMLEvents"),c.initEvent("input",!0,!0,this.options.contentWindow),d=0;d1?b[1]:"";return{major:parseInt(c[0],10),minor:parseInt(c[1],10),revision:parseInt(c[2],10),preRelease:d,toString:function(){return[[c[0],c[1],c[2]].join("."),d].join("-")}}},a.version=a.parseVersionString.call(this,{version:"5.0.0-alpha.0"}.version),a}()); \ No newline at end of file diff --git a/package.json b/package.json index 6a3007b76..3c899eed0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "medium-editor", - "version": "4.12.0", + "version": "5.0.0-alpha.0", "author": "Davi Ferreira ", "contributors": [ { diff --git a/src/js/version.js b/src/js/version.js index e1137b141..b3c6db8d0 100644 --- a/src/js/version.js +++ b/src/js/version.js @@ -17,5 +17,5 @@ MediumEditor.parseVersionString = function (release) { MediumEditor.version = MediumEditor.parseVersionString.call(this, ({ // grunt-bump looks for this: - 'version': '4.12.0' + 'version': '5.0.0-alpha.0' }).version);