2012-06-07 16 views
5

He estado intentando crear un encuadernador de encuadernación personalizado que pueda usar para dar un comportamiento de marca de agua a los campos de entrada de texto.marca de agua de entrada de texto utilizando el encuadernador de encuadernación personalizado

Por watermark quiero decir: añadir valores por defecto para los campos que se eliminan en el enfoque de texto, y se sustituye en la falta de definición si el campo de texto sigue vacío

He conseguido que esto funcione como se ha demostrado en este jsFiddle : http://jsfiddle.net/rpallas/nvxuw/

tengo 3 preguntas acerca de esta solución:

  1. ¿hay alguna manera de cambiarlo por lo que sólo tengo que declarar el valor de marca de agua de una vez? Actualmente tengo que ponerlo en el lugar donde declaro el enlace y también tengo que inicializar el observable con el mismo valor en viewModel, ya que de lo contrario no tendría valor inicial.
  2. ¿Hay alguna manera mejor de llegar al observable subyacente al que está obligado el valor de los elementos? Actualmente estoy agarrándolo usando allBindingsAccessor, pero esto me parece incorrecto. Originalmente solo estaba estableciendo el valor usando jquery $(element).val(''), pero esto también me pareció incorrecto. ¿Cuál es el mejor, o hay una mejor manera?
  3. ¿Alguien tiene o conoce una solución existente para este problema? ¿Estoy reinventando la rueda?

Respuesta

14

Creo que su uso de allbindings es innecesario. De hecho, no creo que la marca de agua deba tener en cuenta lo observable, ya que eso es lo que generalmente hace una marca de agua, es decir, el atributo placeholder.

¿Funcionaría para usted?

ko.bindingHandlers.watermark = { 
    init: function (element, valueAccessor, allBindingsAccessor) { 
     var value = valueAccessor(), allBindings = allBindingsAccessor(); 
     var defaultWatermark = ko.utils.unwrapObservable(value); 
     var $element = $(element); 

     setTimeout(function() { 
      $element.val(defaultWatermark);}, 0); 

     $element.focus(
      function() { 
       if ($element.val() === defaultWatermark) { 
        $element.val(""); 
       } 
      }).blur(function() { 
       if ($element.val() === '') { 
        $element.val(defaultWatermark) 
       } 
      }); 
    } 
}; 

http://jsfiddle.net/madcapnmckay/Q5yME/1/

Espero que esto ayude.

+1

Sí, eso es casi exactamente lo que tenía antes de cambiarlo para utilizar allBindingsAccessor. Me faltaba el 'setTimeout' cuando intento establecer el valor inicial. ¿Podría explicar brevemente por qué es necesario? Además, ¿sabes si hay una mejor manera? ¿o crees que esta es una buena (suficiente) forma (en términos de toda la solución)? Por ejemplo, noto que hay un enlace hasfocus (incorporado). ¿Podría ser ese un mejor enfoque? – Robbie

+2

Creo que este enfoque está bien si quieres admitir navegadores más antiguos. Para los nuevos simplemente use el atributo marcador de posición. El setTimeout es necesario porque internamente KO usa setTimeout antes de establecer el valor de la entrada. Esto significa que su código se estaba ejecutando antes de que el código KO establezca el valor, por lo tanto, necesita el setTimeout para asegurarse nuevamente de que su código sea el último en la ejecución. – madcapnmckay

+0

Muchas gracias por la explicación y ayuda. – Robbie

1

El enfoque anterior está bien siempre que la lógica de su aplicación sea realmente simple, tenga en cuenta que la solución está jugando con los valores de su Modelo de Vista, esos valores pueden ser observables y pueden tener suscripciones o cálculos asociados a él, por lo al cambiar el valor, cambia su Modelo de Vista. Aquí hay una solución diferente sin actualizar su modelo de vista

ko.bindingHandlers.fakePlaceHolderWhenNeedIt = { 
    init: function (element, valueAccessor, allBindings, vm) { 
    if (!Modernizr.input.placeholder) { 
     var placeHolderVal = $(element).attr("placeholder"); 

     if (placeHolderVal != null || placeHolderVal != '') { 

      var $element = $(element); 
      var value = valueAccessor() 
      var valueUnwrapped = ko.utils.unwrapObservable(value); 


      $element.keyup(function() { 
       var inputValue = $(this).val(); 
       var $watermark = $(this).prev('.ie-placeholder'); 
       if (inputValue == null || inputValue == '') { 
        $watermark.show(); 
       } 
       else { 
        $watermark.hide(); 
       } 
      }); 

      var display = valueUnwrapped != null || valueUnwrapped != '' ? "block" : "none"; 
      var left = $element.position().left; 
      var top = $element.position().top; 
      var paddingLeft = $element.css('padding-left'); 
      var paddingRight = $element.css('padding-right'); 
      var paddingTop = $element.css('padding-top'); 
      var paddingBottom = $element.css('padding-bottom'); 

      var height = $element.css('height'); 
      var placeHolder = '<div class="ie-placeholder" style="position:absolute;left:' + left + ';top:' + top + ';padding-top: ' + paddingTop + ';padding-bottom: ' + paddingBottom + ';padding-left: ' + paddingLeft + ';padding-right: ' + paddingRight + ';height: ' + height + ';line-height:' + height + ';display:' + display + ';">' + placeHolderVal + '</div>'; 

      $(placeHolder).click(function() { $element.focus(); }).insertBefore(element); 
     } 
    } 
}, 
update: function (element, valueAccessor, allBindings, vm) { 
    if (!Modernizr.input.placeholder) { 
     var placeHolderVal = $(element).attr("placeholder"); 

     if (placeHolderVal != null || placeHolderVal != '') { 
      var $element = $(element); 
      var value = valueAccessor() 
      var valueUnwrapped = ko.utils.unwrapObservable(value); 

      var $watermark = $element.prev('.ie-placeholder'); 
      if (valueUnwrapped == null || valueUnwrapped == '') { 
       $watermark.show(); 
      } 
      else { 
       $watermark.hide(); 
      } 
     } 
    } 
} 
Cuestiones relacionadas