Browse Source

add link formatting

Jason Chen 12 years ago
parent
commit
c24c6f31f5
4 changed files with 140 additions and 84 deletions
  1. 1 0
      .gitignore
  2. 12 75
      demo/pretty.haml
  3. 94 9
      demo/scripts/pretty.coffee
  4. 33 0
      lib/toggler.coffee

+ 1 - 0
.gitignore

@@ -4,3 +4,4 @@ build/
 lib/jetsync.js
 node_modules/
 lib/tandem.js
+lib/toggler.js

+ 12 - 75
demo/pretty.haml

@@ -32,86 +32,23 @@
               .format.underline
             .format-button<>
               .format.strike.last
+          .format-group
+            .format-button<>
+              .format.link.last
 
         #editor-container.editor-container
-          %div<>
-            %span<> Welcome to Stypi
-          %div<>
-            %b<> Bold
-            %span<> &nbsp;
-            %i<> Italic
-            %span<> &nbsp;
-            %s<> Strike
-            %span<> &nbsp;
-            %u<> Underline
-            %span<> &nbsp;
-            %a{:href => 'http://www.google.com'}<> Link
-          %div<>
-            %u<> Zero
-            %i<> One
-            %u<> Two
-            %i<>
-              %b<> Three
-              %s<> Four
-              %i<> Five
-          %div<>
-            %i<>
-              %b<> Hey
-              %u<> Now
-            %s<> What
-          %div<>
-            %b<> a
-            %i<> b
-            %b<> c
-            %i<> d
-            %b<> e
-            %i<> f
-            %b<> g
-          %div<>
-            %span.tab<> &#09;
-            %span<> I look like an indent but actually I'm not cuz I'm a tab.
-          %div<>
-            %span.size-huge<> Huge
-            %span.size-large<> Large
-            %span.size-small<> Small
-          %div<>
-            %span.size-huge<> Huge
-          %div<>
-            %span.size-large<> Large
-          %div<>
-            %span.size-small<> Small
-          %div<>
-            %span.family-serif<> Serif
-            %span.family-monospace<> Monospace
-          %div<>
-            %span.color-white<>
-              %span.background-black<> white
-            %span.color-red<> red
-            %span.color-orange<> orange
-            %span.color-yellow<> yellow
-            %span.color-green<> green
-            %span.color-blue<> blue
-            %span.color-purple<> purple
-          %div<>
-            %span.background-black<>
-              %span.color-white<> black
-            %span.background-red<> red
-            %span.background-orange<> orange
-            %span.background-yellow<> yellow
-            %span.background-green<> green
-            %span.background-blue<> blue
-            %span.background-purple<> purple
-          %div<>
-            %br<>
-          %div<>
-            %br<>
-          %div<>
-            %span<> Goodbye
-          %div<>
-            %br<>
+
+        .link-tooltip
+          %span.title Visit URL:
+          %span.input-container
+            %a.url{:target => '_blank'}
+            %input.url-editor{:type => 'text'}
+            %span - 
+            %a.change Change
 
     %script{:type => 'text/javascript', :src => '../lib/jquery.js'}
     %script{:type => 'text/javascript', :src => '../lib/dropkick/dropkick.js'}
+    %script{:type => 'text/javascript', :src => '../lib/toggler.js'}
     %script{:type => 'text/javascript', :src => '../lib/underscore.js'}
     %script{:type => 'text/javascript', :src => '../lib/eventemitter2.js'}
     %script{:type => 'text/javascript', :src => '../lib/rangy/rangy-core.js'}

+ 94 - 9
demo/scripts/pretty.coffee

@@ -1,11 +1,79 @@
-$(document).ready( ->
-  editor = new Scribe.Editor("editor-container", {
-    styles: {
-      'a': { 'color': '#06c' }
-      '.editor': { 'min-height': '95%' }
-    }
+curLink = linkTooltip = null
+
+showLinkEditor = (editor, link, change = false) ->
+  curLink = link
+  url = $(link).attr('href')
+  $('.url', linkTooltip).text(url).attr('href', url)
+  $('.url-editor', linkTooltip).val(url)
+  linkTooltip.show()
+  offset = $(link).offset()
+  left = offset.left + $(link).width() / 2 - linkTooltip.width() / 2
+  left = Math.min(Math.max(10, left), $(editor.doc.root).width() - linkTooltip.width())
+  top = offset.top + $(link).height() + 5
+  if top > $('#editor-container').height() - linkTooltip.height()
+    top = offset.top - linkTooltip.height() - $(link).height() - 5
+  linkTooltip.css({ left: left, top: top })
+  $('.change', linkTooltip).click()
+
+initLinkEditor = (editor) ->
+  editor.renderer.addStyles(
+    '.link-tooltip':
+      'background-color': '#fff'
+      'border': '1px solid #ccc'
+      'box-shadow': '0px 0px 5px #ddd'
+      'color': '#222'
+      'display': 'none'
+      'font-family': 'Helvetica, Arial, san-serif'
+      'font-size': '13px'
+      'padding': '5px 10px'
+      'position': 'absolute'
+      'white-space': 'nowrap'
+    '.link-tooltip a':
+      'color': '#06c'
+      'cursor': 'pointer'
+    '.link-tooltip .title':
+      'margin-right': '5px'
+    '.link-tooltip .url-editor':
+      'display': 'none'
+    '.link-tooltip.editing .url':
+      'display': 'none'
+    '.link-tooltip.editing .url-editor':
+      'display': 'inline'
+  )
+  linkTooltip = $('.link-tooltip').appendTo(editor.doc.root.parentNode)
+  $('a', editor.doc.root).live('click', (event) ->
+    showLinkEditor(editor, this)
+  )
+  $('.url-editor', linkTooltip).keyup((event) ->
+    $('.change', linkTooltip).trigger('click') if event.which == 13
+  )
+  $('.change', linkTooltip).toggler({
+    target: linkTooltip
+    toggleClass: 'editing'
+    before: (event, hasClass) ->
+      if hasClass
+        $('.url-editor', linkTooltip).width($('.url', linkTooltip).width() + 10)
+    after: (event, hasClass) ->
+      if hasClass
+        $('.url-editor', linkTooltip).focus()
+        $('.change', linkTooltip).text('Done')
+      else
+        url = $('.url-editor', linkTooltip).val()
+        url = 'https://' + url unless url.match(/http[s]{0,1}:\/\//)
+        if curLink?
+          $(curLink).attr('href', url)
+          protocol = $(curLink).get(0).protocol
+          $(curLink).attr('about:blank') if $(curLink).get(0).protocol
+        $('.url', linkTooltip).text(url).attr('href', url)
+        $('.change', linkTooltip).text('Change')
+        editor.update()
   })
+  editor.on(Scribe.Editor.events.SELECTION_CHANGE, (selection) ->
+    formats = selection.getFormats()
+    linkTooltip.hide() unless formats['link']?
+  )
 
+initToolbar = (editor) ->
   _.each(['family', 'size'], (format) ->
     $(".formatting-container .#{format}").dropkick({
       change: (value) ->
@@ -29,14 +97,19 @@ $(document).ready( ->
     link = if $(this).parent().hasClass('active') then false else selection.getText()
     editor.selection.format('link', link)
     selection = editor.getSelection()
-    $link = $('a', selection.start.leafNode).first() or $('a', selection.end.leafNode).first()
-    unless _.any([selection.start.leafNode, selection.end.leafNode], (node) ->
+    boundries = [selection.start.leafNode, selection.end.leafNode]
+    _.each(boundries, (node, index) ->
+      while node.parentNode?.childNodes.length == 1
+        boundries[index] = node.parentNode
+        node = node.parentNode
+    )
+    unless _.any(boundries, (node) ->
       if node.tagName == 'A'
         showLinkEditor(editor, node)
         return true
       return false
     )
-      $link = $('a', selection.start.leafNode).first() or $('a', selection.end.leafNode).first()
+      $link = $('a', boundries[0]).first() or $('a', boundries[0]).first()
       showLinkEditor(editor, $link.get(0)) if $link
   )
   editor.on(Scribe.Editor.events.SELECTION_CHANGE, (selection) ->
@@ -55,4 +128,16 @@ $(document).ready( ->
       else
         container.parent().addClass('active')
   )
+
+
+$(document).ready( ->
+  editor = new Scribe.Editor("editor-container", {
+    styles: {
+      'a': { 'color': '#06c' }
+      '.editor': { 'min-height': '95%' }
+    }
+  })
+  
+  initToolbar(editor)
+  initLinkEditor(editor)
 )

+ 33 - 0
lib/toggler.coffee

@@ -0,0 +1,33 @@
+# Purpose: Easy way to bind an element event to the toggling of a class of another element,
+#          for example clicking on something toggles the active class of something else
+#
+# Usage: $("jqueryObj").toggler()
+$.extend($.fn, {
+  toggler: (method, others...) ->
+    if (typeof method == 'object' || !method)
+      methods.init.call(this, method)
+    else
+      $.error('You need to pass in an object or nothing to toggler')
+    return this
+})
+
+
+DEFAULTS = {
+  after: (event, hasClass) ->
+  before: (event, willHaveClass) ->
+  target: $()                      # elements that activate the context menu upon rightclick
+  toggleClass: "active"
+  toggleEvent: "click"
+}
+
+
+methods = {
+  init: (options = {}) ->
+    settings = $.extend({}, DEFAULTS, options)
+    $(this).bind(settings.toggleEvent, (event) =>
+      trigger = settings.before.call(this, event, !settings.target.hasClass(settings.toggleClass))
+      if trigger != false
+        settings.target.toggleClass(settings.toggleClass)
+        settings.after.call(this, event, settings.target.hasClass(settings.toggleClass))
+    )
+}