diff --git a/l10n_client.js b/l10n_client.js
index c4a9b56..d9fa96b 100644
--- a/l10n_client.js
+++ b/l10n_client.js
@@ -77,7 +77,7 @@ $.extend(Drupal, {
       } else {
         if(search.length > 0) {
           $('#l10n-client-string-select li').hide();
-          $('#l10n-client-string-select li:contains('+search+')').show();
+          $('#l10n-client-string-select li:icontains('+search+')').show();
         }
       }
     }
@@ -174,8 +174,10 @@ Drupal.behaviors.l10nClient.attach = function (context) {
         'form_token': $('#l10n-client-form input[name=form_token]').val()
       },
       success: function (data) {
-        // Store string in local js
-        Drupal.l10nClient.setString(Drupal.l10nClient.selected, $('#l10n-client-form .translation-target').val());
+
+        var source = $('#l10n-client-string-editor .source-text').text(),
+          context = $('#l10n-client-string-editor .context').text(),
+          oldTranslation = Drupal.l10nClient.getString(Drupal.l10nClient.selected, 'target');
 
         // Figure out the display of the new translation in the selection list.
         var newTranslation = $('#l10n-client-form .translation-target').val();
@@ -185,6 +187,22 @@ Drupal.behaviors.l10nClient.attach = function (context) {
                                                    .replace(/&lt;/g, "<")
                                                    .replace(/&gt;/g, ">")
                                                    .replace(/&amp;/g, "&");
+
+        // Instant preview on website
+        if (oldTranslation != '') {
+          htmlreplace(oldTranslation, newTranslation);
+        } else {
+          htmlreplace(source, newTranslation);
+        }
+
+        if (!Drupal.locale.strings[context]) {
+          Drupal.locale.strings[context] = {};
+        }
+        Drupal.locale.strings[context][source] = newTranslation;
+
+        // Store string in local js
+        Drupal.l10nClient.setString(Drupal.l10nClient.selected, $('#l10n-client-form .translation-target').val());
+
         if (newTranslationStripped.length == 0) {
           // Only contains HTML tags (edge case). Keep the whole string.
           // HTML tags will show up in the selector, but that is normal in this case.
@@ -203,7 +221,6 @@ Drupal.behaviors.l10nClient.attach = function (context) {
         // Empty input fields.
         $('#l10n-client-string-editor .source-text').html(data);
         $('#l10n-client-form .translation-target').val('');
-
       },
       error: function (xmlhttp) {
         alert(Drupal.t('An HTTP error @status occured.', { '@status': xmlhttp.status }));
@@ -212,6 +229,60 @@ Drupal.behaviors.l10nClient.attach = function (context) {
     return false;
   });
 
+  // https://gist.github.com/jaygooby/2170045
+  function htmlreplace(a, b, element) {
+    if (!element) element = document.body;
+    // Do not replace inside localization client
+    if (element.id && $.inArray(element.id, ['l10n-client', 'l10n-client-data']) > -1) {
+      return;
+    }
+    var nodes = element.childNodes;
+    for (var n=0; n<nodes.length; n++) {
+      // MSIE doesn't have Node
+      if (nodes[n].nodeType == 3) {
+        var r = new RegExp(a, 'gi');
+
+        // MSIE8 and less doesn't have textContent
+        if (nodes[n].textContent) {
+          // If we assign try and assign a new value to
+          // nodes[n].textContent
+          // then 2011 bulds of MSIE9 crash with "A problem with this
+          // website caused Internet Explorer to close"
+          // (later builds are OK).
+          // To be safe, assign to nodes[n].nodeValue instead.
+          //nodes[n].textContent = nodes[n].textContent.replace(pattern, replacement);
+          nodes[n].nodeValue = nodes[n].textContent.replace(r, b);
+        } else {
+          nodes[n].nodeValue = nodes[n].nodeValue.replace(r, b);
+        }
+      } else {
+        htmlreplace(a, b, nodes[n]);
+      }
+    }
+  }
+
 };
 
+// https://github.com/jquery/sizzle/wiki/Sizzle-Documentation#wiki-back-compat
+// An implementation of a case-insensitive contains pseudo made for all versions of jQuery
+function icontains( elem, text ) {
+  return (
+    elem.textContent ||
+    elem.innerText ||
+    $( elem ).text() ||
+    ""
+  ).toLowerCase().indexOf( (text || "").toLowerCase() ) > -1;
+}
+
+$.expr[':'].icontains = $.expr.createPseudo ?
+  $.expr.createPseudo(function(text) {
+    return function(elem) {
+      return icontains(elem, text);
+    };
+  }) :
+  function(elem, i, match) {
+    return icontains(elem, match[3]);
+  };
+
+
 })(jQuery);
