Преглед изворни кода

Added some more jQuery events

This adds the `select` and `unselect` events so users can still
hook into them from their jQuery plugins.

This also modifies the core `trigger` to fire pre-events that can
be canceled for the `open`, `close`, `select`, and `unselect`
events. Users implementing these events who need to handle cases
where the event has been prevented should check `args.prevented`,
where `args` is the object that was included for arguments when
triggering the internal event.
Kevin Brown пре 10 година
родитељ
комит
28f9cae5d7

+ 1 - 1
dist/js/i18n/de.js

@@ -1 +1 @@
-window.$=window.$||{},function(){$&&$.fn&&$.fn.select2&&$.fn.select2.amd&&(define=$.fn.select2.amd.define,require=$.fn.select2.amd.require),define("select2/i18n/de",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return"Bitte "+t+" Zeichen weniger eingeben"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Bitte "+t+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(){var e="Sie können nur "+args.maximum+" Eintr";return args.maximum===1?e+="ag":e+="äge",e+=" auswählen",e},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"}}}),require("jquery.select2"),$.fn.select2.amd={define:define,require:require}}();
+window.$=window.$||{},function(){$&&$.fn&&$.fn.select2&&$.fn.select2.amd&&(define=$.fn.select2.amd.define,require=$.fn.select2.amd.require),define("select2/i18n/de",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return"Bitte "+t+" Zeichen weniger eingeben"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Bitte "+t+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var t="Sie können nur "+e.maximum+" Eintr";return e.maximum===1?t+="ag":t+="äge",t+=" auswählen",t},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"}}}),require("jquery.select2"),$.fn.select2.amd={define:define,require:require}}();

+ 60 - 6
dist/js/select2.amd.full.js

@@ -1231,18 +1231,39 @@ define('select2/selection/eventRelay',[
 
   EventRelay.prototype.bind = function (decorated, container, $container) {
     var self = this;
-    var relayEvents = ['open', 'close'];
+    var relayEvents = [
+      'open', 'opening',
+      'close', 'closing',
+      'select', 'selecting',
+      'unselect', 'unselecting'
+    ];
+
+    var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
 
     decorated.call(this, container, $container);
 
     container.on('*', function (name, params) {
+      // Ignore events that should not be relayed
       if (relayEvents.indexOf(name) === -1) {
         return;
       }
 
-      var evt = $.Event('select2:' + name, params);
+      // The parameters should always be an object
+      params = params || {};
+
+      // Generate the jQuery event for the Select2 event
+      var evt = $.Event('select2:' + name, {
+        params: params
+      });
 
       self.$element.trigger(evt);
+
+      // Only handle preventable events if it was one
+      if (preventableEvents.indexOf(name) === -1) {
+        return;
+      }
+
+      params.prevented = evt.isDefaultPrevented();
     });
   };
 
@@ -4138,14 +4159,14 @@ define('select2/core',[
 
           evt.preventDefault();
         } else if (key === KEYS.ESC || key === KEYS.TAB) {
-          self.close();
+          self.trigger('close');
 
           evt.preventDefault();
         }
       } else {
         if (key === KEYS.ENTER || key === KEYS.SPACE ||
             ((key === KEYS.DOWN || key === KEYS.UP) && evt.altKey)) {
-          self.open();
+          self.trigger('open');
 
           evt.preventDefault();
         }
@@ -4167,15 +4188,48 @@ define('select2/core',[
     }
   };
 
+  /**
+   * Override the trigger method to automatically trigger pre-events when
+   * there are events that can be prevented.
+   */
+  Select2.prototype.trigger = function (name, args) {
+    var actualTrigger = Select2.__super__.trigger;
+    var preTriggerMap = {
+      'open': 'opening',
+      'close': 'closing',
+      'select': 'selecting',
+      'unselect': 'unselecting'
+    };
+
+    if (name in preTriggerMap) {
+      var preTriggerName = preTriggerMap[name];
+      var preTriggerArgs = {
+        prevented: false,
+        name: name,
+        args: args
+      };
+
+      actualTrigger.call(this, preTriggerName, preTriggerArgs);
+
+      if (preTriggerArgs.prevented) {
+        args.prevented = true;
+
+        return;
+      }
+    }
+
+    actualTrigger.call(this, name, args);
+  };
+
   Select2.prototype.toggleDropdown = function () {
     if (this.options.get('disabled')) {
       return;
     }
 
     if (this.isOpen()) {
-      this.close();
+      this.trigger('close');
     } else {
-      this.open();
+      this.trigger('open');
     }
   };
 

+ 60 - 6
dist/js/select2.amd.js

@@ -1231,18 +1231,39 @@ define('select2/selection/eventRelay',[
 
   EventRelay.prototype.bind = function (decorated, container, $container) {
     var self = this;
-    var relayEvents = ['open', 'close'];
+    var relayEvents = [
+      'open', 'opening',
+      'close', 'closing',
+      'select', 'selecting',
+      'unselect', 'unselecting'
+    ];
+
+    var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
 
     decorated.call(this, container, $container);
 
     container.on('*', function (name, params) {
+      // Ignore events that should not be relayed
       if (relayEvents.indexOf(name) === -1) {
         return;
       }
 
-      var evt = $.Event('select2:' + name, params);
+      // The parameters should always be an object
+      params = params || {};
+
+      // Generate the jQuery event for the Select2 event
+      var evt = $.Event('select2:' + name, {
+        params: params
+      });
 
       self.$element.trigger(evt);
+
+      // Only handle preventable events if it was one
+      if (preventableEvents.indexOf(name) === -1) {
+        return;
+      }
+
+      params.prevented = evt.isDefaultPrevented();
     });
   };
 
@@ -4138,14 +4159,14 @@ define('select2/core',[
 
           evt.preventDefault();
         } else if (key === KEYS.ESC || key === KEYS.TAB) {
-          self.close();
+          self.trigger('close');
 
           evt.preventDefault();
         }
       } else {
         if (key === KEYS.ENTER || key === KEYS.SPACE ||
             ((key === KEYS.DOWN || key === KEYS.UP) && evt.altKey)) {
-          self.open();
+          self.trigger('open');
 
           evt.preventDefault();
         }
@@ -4167,15 +4188,48 @@ define('select2/core',[
     }
   };
 
+  /**
+   * Override the trigger method to automatically trigger pre-events when
+   * there are events that can be prevented.
+   */
+  Select2.prototype.trigger = function (name, args) {
+    var actualTrigger = Select2.__super__.trigger;
+    var preTriggerMap = {
+      'open': 'opening',
+      'close': 'closing',
+      'select': 'selecting',
+      'unselect': 'unselecting'
+    };
+
+    if (name in preTriggerMap) {
+      var preTriggerName = preTriggerMap[name];
+      var preTriggerArgs = {
+        prevented: false,
+        name: name,
+        args: args
+      };
+
+      actualTrigger.call(this, preTriggerName, preTriggerArgs);
+
+      if (preTriggerArgs.prevented) {
+        args.prevented = true;
+
+        return;
+      }
+    }
+
+    actualTrigger.call(this, name, args);
+  };
+
   Select2.prototype.toggleDropdown = function () {
     if (this.options.get('disabled')) {
       return;
     }
 
     if (this.isOpen()) {
-      this.close();
+      this.trigger('close');
     } else {
-      this.open();
+      this.trigger('open');
     }
   };
 

+ 60 - 6
dist/js/select2.full.js

@@ -10766,18 +10766,39 @@ define('select2/selection/eventRelay',[
 
   EventRelay.prototype.bind = function (decorated, container, $container) {
     var self = this;
-    var relayEvents = ['open', 'close'];
+    var relayEvents = [
+      'open', 'opening',
+      'close', 'closing',
+      'select', 'selecting',
+      'unselect', 'unselecting'
+    ];
+
+    var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
 
     decorated.call(this, container, $container);
 
     container.on('*', function (name, params) {
+      // Ignore events that should not be relayed
       if (relayEvents.indexOf(name) === -1) {
         return;
       }
 
-      var evt = $.Event('select2:' + name, params);
+      // The parameters should always be an object
+      params = params || {};
+
+      // Generate the jQuery event for the Select2 event
+      var evt = $.Event('select2:' + name, {
+        params: params
+      });
 
       self.$element.trigger(evt);
+
+      // Only handle preventable events if it was one
+      if (preventableEvents.indexOf(name) === -1) {
+        return;
+      }
+
+      params.prevented = evt.isDefaultPrevented();
     });
   };
 
@@ -13673,14 +13694,14 @@ define('select2/core',[
 
           evt.preventDefault();
         } else if (key === KEYS.ESC || key === KEYS.TAB) {
-          self.close();
+          self.trigger('close');
 
           evt.preventDefault();
         }
       } else {
         if (key === KEYS.ENTER || key === KEYS.SPACE ||
             ((key === KEYS.DOWN || key === KEYS.UP) && evt.altKey)) {
-          self.open();
+          self.trigger('open');
 
           evt.preventDefault();
         }
@@ -13702,15 +13723,48 @@ define('select2/core',[
     }
   };
 
+  /**
+   * Override the trigger method to automatically trigger pre-events when
+   * there are events that can be prevented.
+   */
+  Select2.prototype.trigger = function (name, args) {
+    var actualTrigger = Select2.__super__.trigger;
+    var preTriggerMap = {
+      'open': 'opening',
+      'close': 'closing',
+      'select': 'selecting',
+      'unselect': 'unselecting'
+    };
+
+    if (name in preTriggerMap) {
+      var preTriggerName = preTriggerMap[name];
+      var preTriggerArgs = {
+        prevented: false,
+        name: name,
+        args: args
+      };
+
+      actualTrigger.call(this, preTriggerName, preTriggerArgs);
+
+      if (preTriggerArgs.prevented) {
+        args.prevented = true;
+
+        return;
+      }
+    }
+
+    actualTrigger.call(this, name, args);
+  };
+
   Select2.prototype.toggleDropdown = function () {
     if (this.options.get('disabled')) {
       return;
     }
 
     if (this.isOpen()) {
-      this.close();
+      this.trigger('close');
     } else {
-      this.open();
+      this.trigger('open');
     }
   };
 

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
dist/js/select2.full.min.js


+ 60 - 6
dist/js/select2.js

@@ -1659,18 +1659,39 @@ define('select2/selection/eventRelay',[
 
   EventRelay.prototype.bind = function (decorated, container, $container) {
     var self = this;
-    var relayEvents = ['open', 'close'];
+    var relayEvents = [
+      'open', 'opening',
+      'close', 'closing',
+      'select', 'selecting',
+      'unselect', 'unselecting'
+    ];
+
+    var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
 
     decorated.call(this, container, $container);
 
     container.on('*', function (name, params) {
+      // Ignore events that should not be relayed
       if (relayEvents.indexOf(name) === -1) {
         return;
       }
 
-      var evt = $.Event('select2:' + name, params);
+      // The parameters should always be an object
+      params = params || {};
+
+      // Generate the jQuery event for the Select2 event
+      var evt = $.Event('select2:' + name, {
+        params: params
+      });
 
       self.$element.trigger(evt);
+
+      // Only handle preventable events if it was one
+      if (preventableEvents.indexOf(name) === -1) {
+        return;
+      }
+
+      params.prevented = evt.isDefaultPrevented();
     });
   };
 
@@ -4566,14 +4587,14 @@ define('select2/core',[
 
           evt.preventDefault();
         } else if (key === KEYS.ESC || key === KEYS.TAB) {
-          self.close();
+          self.trigger('close');
 
           evt.preventDefault();
         }
       } else {
         if (key === KEYS.ENTER || key === KEYS.SPACE ||
             ((key === KEYS.DOWN || key === KEYS.UP) && evt.altKey)) {
-          self.open();
+          self.trigger('open');
 
           evt.preventDefault();
         }
@@ -4595,15 +4616,48 @@ define('select2/core',[
     }
   };
 
+  /**
+   * Override the trigger method to automatically trigger pre-events when
+   * there are events that can be prevented.
+   */
+  Select2.prototype.trigger = function (name, args) {
+    var actualTrigger = Select2.__super__.trigger;
+    var preTriggerMap = {
+      'open': 'opening',
+      'close': 'closing',
+      'select': 'selecting',
+      'unselect': 'unselecting'
+    };
+
+    if (name in preTriggerMap) {
+      var preTriggerName = preTriggerMap[name];
+      var preTriggerArgs = {
+        prevented: false,
+        name: name,
+        args: args
+      };
+
+      actualTrigger.call(this, preTriggerName, preTriggerArgs);
+
+      if (preTriggerArgs.prevented) {
+        args.prevented = true;
+
+        return;
+      }
+    }
+
+    actualTrigger.call(this, name, args);
+  };
+
   Select2.prototype.toggleDropdown = function () {
     if (this.options.get('disabled')) {
       return;
     }
 
     if (this.isOpen()) {
-      this.close();
+      this.trigger('close');
     } else {
-      this.open();
+      this.trigger('open');
     }
   };
 

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
dist/js/select2.min.js


+ 28 - 9
docs/examples.html

@@ -418,8 +418,6 @@ $(".js-example-basic-multiple-limit").select2({
     </div>
   </section>
 
-  <!-- Hidden until 4.0.0-beta.2 is released
-
   <section id="events" class="row">
     <div class="col-md-4">
       <h1>Events</h1>
@@ -445,10 +443,22 @@ $(".js-example-basic-multiple-limit").select2({
 
       <p>
         <code>select2:open</code> is fired whenever the dropdown is opened.
+        <code>select2:opening</code> is fired before this and can be prevented.
       </p>
 
       <p>
         <code>select2:close</code> is fired whenever the dropdown is closed.
+        <code>select2:closing</code> is fired before this and can be prevented.
+      </p>
+
+      <p>
+        <code>select2:select</code> is fired whenever a result is selected.
+        <code>select2:selecting</code> is fired before this and can be prevented.
+      </p>
+
+      <p>
+        <code>select2:unselect</code> is fired whenever a result is unselected.
+        <code>select2:unselecting</code> is fired before this and can be prevented.
       </p>
     </div>
     <div class="col-md-8">
@@ -462,14 +472,24 @@ $(".js-example-basic-multiple-limit").select2({
 var $eventLog = $(".js-event-log");
 var $eventSelect = $(".js-example-events");
 
-$eventSelect.on("select2:open", function (e) { log("select2:open"); });
-$eventSelect.on("select2:close", function (e) { log("select2:close"); });
+$eventSelect.on("select2:open", function (e) { log("select2:open", e); });
+$eventSelect.on("select2:close", function (e) { log("select2:close", e); });
+$eventSelect.on("select2:select", function (e) { log("select2:select", e); });
+$eventSelect.on("select2:unselect", function (e) { log("select2:unselect", e); });
 
 $eventSelect.on("change", function (e) { log("change"); });
 
-function log (name, args) {
-  args = args || {};
-  var $e = $("<li>" + name + " -> " + JSON.stringify(args) + "</li>");
+function log (name, evt) {
+  if (!evt) {
+    var args = "{}";
+  } else {
+    var args = JSON.stringify(evt.params, function (key, value) {
+      if (value && value.nodeName) return "[DOM node]";
+      if (value instanceof $.Event) return "[$.Event]";
+      return value;
+    });
+  }
+  var $e = $("<li>" + name + " -> " + args + "</li>");
   $eventLog.append($e);
   $e.animate({ opacity: 1 }, 10000, 'linear', function () {
     $e.animate({ opacity: 0 }, 2000, 'linear', function () {
@@ -480,7 +500,6 @@ function log (name, args) {
 </script>
     </div>
   </section>
-  -->
 
   <section id="tags" class="row">
     <div class="col-md-4">
@@ -929,7 +948,7 @@ $.fn.select2.amd.require(
   $(".js-example-programmatic").select2();
   $(".js-example-programmatic-multi").select2();
 
-  //$eventSelect.select2();
+  $eventSelect.select2();
 
   $tags.select2({
     tags: ['red', 'blue', 'green']

+ 37 - 4
src/js/select2/core.js

@@ -292,14 +292,14 @@ define([
 
           evt.preventDefault();
         } else if (key === KEYS.ESC || key === KEYS.TAB) {
-          self.close();
+          self.trigger('close');
 
           evt.preventDefault();
         }
       } else {
         if (key === KEYS.ENTER || key === KEYS.SPACE ||
             ((key === KEYS.DOWN || key === KEYS.UP) && evt.altKey)) {
-          self.open();
+          self.trigger('open');
 
           evt.preventDefault();
         }
@@ -321,15 +321,48 @@ define([
     }
   };
 
+  /**
+   * Override the trigger method to automatically trigger pre-events when
+   * there are events that can be prevented.
+   */
+  Select2.prototype.trigger = function (name, args) {
+    var actualTrigger = Select2.__super__.trigger;
+    var preTriggerMap = {
+      'open': 'opening',
+      'close': 'closing',
+      'select': 'selecting',
+      'unselect': 'unselecting'
+    };
+
+    if (name in preTriggerMap) {
+      var preTriggerName = preTriggerMap[name];
+      var preTriggerArgs = {
+        prevented: false,
+        name: name,
+        args: args
+      };
+
+      actualTrigger.call(this, preTriggerName, preTriggerArgs);
+
+      if (preTriggerArgs.prevented) {
+        args.prevented = true;
+
+        return;
+      }
+    }
+
+    actualTrigger.call(this, name, args);
+  };
+
   Select2.prototype.toggleDropdown = function () {
     if (this.options.get('disabled')) {
       return;
     }
 
     if (this.isOpen()) {
-      this.close();
+      this.trigger('close');
     } else {
-      this.open();
+      this.trigger('open');
     }
   };
 

+ 23 - 2
src/js/select2/selection/eventRelay.js

@@ -5,18 +5,39 @@ define([
 
   EventRelay.prototype.bind = function (decorated, container, $container) {
     var self = this;
-    var relayEvents = ['open', 'close'];
+    var relayEvents = [
+      'open', 'opening',
+      'close', 'closing',
+      'select', 'selecting',
+      'unselect', 'unselecting'
+    ];
+
+    var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
 
     decorated.call(this, container, $container);
 
     container.on('*', function (name, params) {
+      // Ignore events that should not be relayed
       if (relayEvents.indexOf(name) === -1) {
         return;
       }
 
-      var evt = $.Event('select2:' + name, params);
+      // The parameters should always be an object
+      params = params || {};
+
+      // Generate the jQuery event for the Select2 event
+      var evt = $.Event('select2:' + name, {
+        params: params
+      });
 
       self.$element.trigger(evt);
+
+      // Only handle preventable events if it was one
+      if (preventableEvents.indexOf(name) === -1) {
+        return;
+      }
+
+      params.prevented = evt.isDefaultPrevented();
     });
   };
 

Неке датотеке нису приказане због велике количине промена