Вход Регистрация
Файл: library/wysihtml5/src/toolbar/toolbar.js
Строк: 416
<?php
/**
 * Toolbar
 *
 * @param {Object} parent Reference to instance of Editor instance
 * @param {Element} container Reference to the toolbar container element
 *
 * @example
 *    <div id="toolbar">
 *      <a data-wysihtml5-command="createLink">insert link</a>
 *      <a data-wysihtml5-command="formatBlock" data-wysihtml5-command-value="h1">insert h1</a>
 *    </div>
 *
 *    <script>
 *      var toolbar = new wysihtml5.toolbar.Toolbar(editor, document.getElementById("toolbar"));
 *    </script>
 */
(function(wysihtml5) {
  var 
CLASS_NAME_COMMAND_DISABLED   "wysihtml5-command-disabled",
      
CLASS_NAME_COMMANDS_DISABLED  "wysihtml5-commands-disabled",
      
CLASS_NAME_COMMAND_ACTIVE     "wysihtml5-command-active",
      
CLASS_NAME_ACTION_ACTIVE      "wysihtml5-action-active",
      
dom                           wysihtml5.dom;
  
  
wysihtml5.toolbar.Toolbar Base.extend(
    
/** @scope wysihtml5.toolbar.Toolbar.prototype */ {
    
constructor: function(editorcontainer) {
      
this.editor     editor;
      
this.container  typeof(container) === "string" document.getElementById(container) : container;
      
this.composer   editor.composer;

      
this._getLinks("command");
      
this._getLinks("action");

      
this._observe();
      
this.show();
      
      var 
speechInputLinks  this.container.querySelectorAll("[data-wysihtml5-command=insertSpeech]"),
          
length            speechInputLinks.length,
          
i                 0;
      for (; 
i<lengthi++) {
        new 
wysihtml5.toolbar.Speech(thisspeechInputLinks[i]);
      }
    },

    
_getLinks: function(type) {
      var 
links   this[type "Links"] = wysihtml5.lang.array(this.container.querySelectorAll("[data-wysihtml5-" type "]")).get(),
          
length  links.length,
          
i       0,
          
mapping this[type "Mapping"] = {},
          
link,
          
group,
          
name,
          
value,
          
dialog;
      for (; 
i<lengthi++) {
        
link    links[i];
        
name    link.getAttribute("data-wysihtml5-" type);
        
value   link.getAttribute("data-wysihtml5-" type "-value");
        
group   this.container.querySelector("[data-wysihtml5-" type "-group='" name "']");
        
dialog  this._getDialog(linkname);
        
        
mapping[name ":" value] = {
          
link:   link,
          
group:  group,
          
name:   name,
          
value:  value,
          
dialogdialog,
          
state:  false
        
};
      }
    },

    
_getDialog: function(linkcommand) {
      var 
that          this,
          
dialogElement this.container.querySelector("[data-wysihtml5-dialog='" command "']"),
          
dialog,
          
caretBookmark;
      
      if (
dialogElement) {
        
dialog = new wysihtml5.toolbar.Dialog(linkdialogElement);

        
dialog.on("show", function() {
          
caretBookmark that.composer.selection.getBookmark();

          
that.editor.fire("show:dialog", { commandcommanddialogContainerdialogElementcommandLinklink });
        });

        
dialog.on("save", function(attributes) {
          if (
caretBookmark) {
            
that.composer.selection.setBookmark(caretBookmark);
          }
          
that._execCommand(commandattributes);
          
          
that.editor.fire("save:dialog", { commandcommanddialogContainerdialogElementcommandLinklink });
        });

        
dialog.on("cancel", function() {
          
that.editor.focus(false);
          
that.editor.fire("cancel:dialog", { commandcommanddialogContainerdialogElementcommandLinklink });
        });
      }
      return 
dialog;
    },

    
/**
     * @example
     *    var toolbar = new wysihtml5.Toolbar();
     *    // Insert a <blockquote> element or wrap current selection in <blockquote>
     *    toolbar.execCommand("formatBlock", "blockquote");
     */
    
execCommand: function(commandcommandValue) {
      if (
this.commandsDisabled) {
        return;
      }

      var 
commandObj this.commandMapping[command ":" commandValue];

      
// Show dialog when available
      
if (commandObj && commandObj.dialog && !commandObj.state) {
        
commandObj.dialog.show();
      } else {
        
this._execCommand(commandcommandValue);
      }
    },

    
_execCommand: function(commandcommandValue) {
      
// Make sure that composer is focussed (false => don't move caret to the end)
      
this.editor.focus(false);

      
this.composer.commands.exec(commandcommandValue);
      
this._updateLinkStates();
    },

    
execAction: function(action) {
      var 
editor this.editor;
      if (
action === "change_view") {
        if (
editor.currentView === editor.textarea) {
          
editor.fire("change_view""composer");
        } else {
          
editor.fire("change_view""textarea");
        }
      }
    },

    
_observe: function() {
      var 
that      this,
          
editor    this.editor,
          
container this.container,
          
links     this.commandLinks.concat(this.actionLinks),
          
length    links.length,
          
i         0;
      
      for (; 
i<lengthi++) {
        
// 'javascript:;' and unselectable=on Needed for IE, but done in all browsers to make sure that all get the same css applied
        // (you know, a:link { ... } doesn't match anchors with missing href attribute)
        
if (links[i].nodeName === "A") {
          
dom.setAttributes({
            
href:         "javascript:;",
            
unselectable"on"
          
}).on(links[i]);
        } else {
          
dom.setAttributes({ unselectable"on" }).on(links[i]);
        }
      }

      
// Needed for opera and chrome
      
dom.delegate(container"[data-wysihtml5-command], [data-wysihtml5-action]""mousedown", function(event) { event.preventDefault(); });
      
      
dom.delegate(container"[data-wysihtml5-command]""click", function(event) {
        var 
link          this,
            
command       link.getAttribute("data-wysihtml5-command"),
            
commandValue  link.getAttribute("data-wysihtml5-command-value");
        
that.execCommand(commandcommandValue);
        
event.preventDefault();
      });

      
dom.delegate(container"[data-wysihtml5-action]""click", function(event) {
        var 
action this.getAttribute("data-wysihtml5-action");
        
that.execAction(action);
        
event.preventDefault();
      });

      
editor.on("focus:composer", function() {
        
that.bookmark null;
        
clearInterval(that.interval);
        
that.interval setInterval(function() { that._updateLinkStates(); }, 500);
      });

      
editor.on("blur:composer", function() {
        
clearInterval(that.interval);
      });

      
editor.on("destroy:composer", function() {
        
clearInterval(that.interval);
      });

      
editor.on("change_view", function(currentView) {
        
// Set timeout needed in order to let the blur event fire first
        
setTimeout(function() {
          
that.commandsDisabled = (currentView !== "composer");
          
that._updateLinkStates();
          if (
that.commandsDisabled) {
            
dom.addClass(containerCLASS_NAME_COMMANDS_DISABLED);
          } else {
            
dom.removeClass(containerCLASS_NAME_COMMANDS_DISABLED);
          }
        }, 
0);
      });
    },

    
_updateLinkStates: function() {
      var 
commandMapping    this.commandMapping,
          
actionMapping     this.actionMapping,
          
i,
          
state,
          
action,
          
command;
      
// every millisecond counts... this is executed quite often
      
for (i in commandMapping) {
        
command commandMapping[i];
        if (
this.commandsDisabled) {
          
state false;
          
dom.removeClass(command.linkCLASS_NAME_COMMAND_ACTIVE);
          if (
command.group) {
            
dom.removeClass(command.groupCLASS_NAME_COMMAND_ACTIVE);
          }
          if (
command.dialog) {
            
command.dialog.hide();
          }
        } else {
          
state this.composer.commands.state(command.namecommand.value);
          if (
wysihtml5.lang.object(state).isArray()) {
            
// Grab first and only object/element in state array, otherwise convert state into boolean
            // to avoid showing a dialog for multiple selected elements which may have different attributes
            // eg. when two links with different href are selected, the state will be an array consisting of both link elements
            // but the dialog interface can only update one
            
state state.length === state[0] : true;
          }
          
dom.removeClass(command.linkCLASS_NAME_COMMAND_DISABLED);
          if (
command.group) {
            
dom.removeClass(command.groupCLASS_NAME_COMMAND_DISABLED);
          }
        }

        if (
command.state === state) {
          continue;
        }

        
command.state state;
        if (
state) {
          
dom.addClass(command.linkCLASS_NAME_COMMAND_ACTIVE);
          if (
command.group) {
            
dom.addClass(command.groupCLASS_NAME_COMMAND_ACTIVE);
          }
          if (
command.dialog) {
            if (
typeof(state) === "object") {
              
command.dialog.show(state);
            } else {
              
command.dialog.hide();
            }
          }
        } else {
          
dom.removeClass(command.linkCLASS_NAME_COMMAND_ACTIVE);
          if (
command.group) {
            
dom.removeClass(command.groupCLASS_NAME_COMMAND_ACTIVE);
          }
          if (
command.dialog) {
            
command.dialog.hide();
          }
        }
      }
      
      for (
i in actionMapping) {
        
action actionMapping[i];
        
        if (
action.name === "change_view") {
          
action.state this.editor.currentView === this.editor.textarea;
          if (
action.state) {
            
dom.addClass(action.linkCLASS_NAME_ACTION_ACTIVE);
          } else {
            
dom.removeClass(action.linkCLASS_NAME_ACTION_ACTIVE);
          }
        }
      }
    },

    
show: function() {
      
this.container.style.display "";
    },

    
hide: function() {
      
this.container.style.display "none";
    }
  });
  
})(
wysihtml5);
?>
Онлайн: 1
Реклама