Часть в JavaScript регулярное выражение тестер


Я совсем новичок в JavaScript и я хотел бы пересмотреть структуру кода и синтаксиса. Она служит в этом мало онлайн обработать тест (еще в разработке).

Весь код (JavaScript, HTML и CSS) находится на GitHub.

application.js:

function update_result_for(input, regexp_value) {
  var input_value   = input.val();
  var result_spans  = input.parent().children('span');        
  if(!input_value || !$('#regexp').val()) {
    result_spans.hide();
  } else {
    var regexp = new RegExp(regexp_value);
    var result = regexp.exec(input_value);
    if(result) {
      var matched_string = result.shift();

      var submatches_list_string = jQuery.map(result, function(submatch, index) {
        return '$' + (index + 1) + ' = ' + submatch;
      }).join('; ');

      var regexp_to_highlight_matched_string          = new RegExp('(.*)' + matched_string + '(.*)');
      var regexp_to_highlight_matched_string_result   = regexp_to_highlight_matched_string.exec(input_value);
      var before_matched_string                       = regexp_to_highlight_matched_string_result[1];
      var after_matched_string                        = regexp_to_highlight_matched_string_result[2];
      var input_value_with_matched_string_highlighted   = 'matched: ' + before_matched_string + '<span class="matched">' + matched_string + '</span>' + after_matched_string;

      result_spans.filter(".submatches").text(submatches_list_string);
      result_spans.filter(".match").html(input_value_with_matched_string_highlighted);
      result_spans.filter(".ok").show('fast');            
      result_spans.filter(".not_ok").hide();
    } else {
      result_spans.filter(".not_ok").show('fast');
      result_spans.filter(".ok").hide();
    }
  }
}       

// from http://www.scottklarr.com/topic/126/how-to-create-ctrl-key-shortcuts-in-javascript/
var isCtrl = false;
$(document).keyup(function (e) {
    if(e.which === 17) isCtrl=false;
}).keydown(function (e) {
    if(e.which === 17) isCtrl=true;
    if(e.which === 69 && isCtrl) {
    $('#regexp').focus();          
        return false;
    }
});

$(document).ready(function() {
  $('#regexp').focus();
  $('span.result').hide();
  $('input:not(#regexp)').live("keyup", function() {
    update_result_for($(this), $('#regexp').val());
  });        
  $('input#regexp').keyup(function() {
    $('input:not(#regexp)').each(function(i) {
      update_result_for($(this), $('#regexp').val());
    });          
  });
  $('a.add_example').click(function() {
    new_example = $('div#examples p:last').clone();
    new_example.children('input').attr('value', '');
    new_example.children('span').hide();
    new_example.insertBefore($(this));
    new_example.children("input").focus();
  });
});


369
7
задан 24 февраля 2011 в 03:02 Источник Поделиться
Комментарии
1 ответ

Этот код выглядит нормально для меня для проекта игрушки. Я особенно ценю длинные имена для идентификаторов.

Теперь, она могла бы выглядеть лучше:


  • с больше комментариев. Вы должны описать цель (зачем за сколько) и ожидаемое случае использовать функции: тип и диапазон значений параметров, чтобы описать то, что он делает, и еще один пункт для уточнения деталей, если это необходимо.

  • мое личное предпочтение было бы использовать camelCase вместо underscore_between_words для длинных имен. Хотя это открыто для обсуждения.

  • маленькая хитрость: конец если ветка с возвращением; чтобы избежать вложенности весь остальной код в другой ветке:

    function update_result_for(input, regexp_value) {
    var input_value = input.val();
    var result_spans = input.parent().children('span');
    if(!input_value || !$('#regexp').val()) {
    result_spans.hide();
    return; // return as soon as possible to avoid deep nesting
    }
    // no need for else
    var regexp = new RegExp(regexp_value);
    var result = regexp.exec(input_value);
    // ...
    }

  • в том же духе, относиться к исключительных случаях первая и обычных случаях после. Это полезный конвенции, которая помогает читателю, и обработка исключений, как правило, короче (или должны быть извлечены в отдельную функцию, если больше), которая избегает длинных вложенных код:

    if (!result) {
    result_spans.filter(".not_ok").show('fast');
    result_spans.filter(".ok").hide();
    return;
    }
    // reduced nesting
    var matched_string = result.shift();
    // ...

  • используйте только анонимные функции, когда вы на самом деле нуждаются в закрытии доступа к контексту: цель, функции будет понятнее с именем, вы сможете избежать вложенности, и может повторно использовать легко функция, в том числе для модульного тестирования. Есть много анонимных функций в коде, который делает это тяжелее, чтобы понять:

    function(submatch, index) {
    return '$' + (index + 1) + ' = ' + submatch;
    })

    function(e) {
    if(e.which === 17) isCtrl=false;
    }

    function(e) {
    if(e.which === 17) isCtrl=true;
    if(e.which === 69 && isCtrl) {
    $('#regexp').focus();
    return false;
    }
    })

    function() {
    $('#regexp').focus();
    $('span.result').hide();
    // ...
    }

    function() {
    update_result_for($(this), $('#regexp').val());
    }

    function() {
    $('input:not(#regexp)').each(function(i) {
    update_result_for($(this), $('#regexp').val());
    });
    }

    function() {
    new_example = $('div#examples p:last').clone();
    new_example.children('input').attr('value', '');
    new_example.children('span').hide();
    new_example.insertBefore($(this));
    new_example.children("input").focus();
    }


  • как только вы определите более чем одну функцию, то вы должны обернуть ваш код в замыкание, чтобы избежать загромождения глобальное пространство имен, после модуля картины:

    (function(){
    // private scope for your code
    }());

  • разбить длинные строки, чтобы соответствовать примерно 80 символов, чтобы избежать необходимости горизонтальной прокрутки в типичных консольных окнах и в помещениях, код на этом сайте:

    var regexp_to_highlight_matched_string =
    new RegExp('(.*)' + matched_string + '(.*)');
    var regexp_to_highlight_matched_string_result =
    regexp_to_highlight_matched_string.exec(input_value);
    var before_matched_string =
    regexp_to_highlight_matched_string_result[1];
    var after_matched_string =
    regexp_to_highlight_matched_string_result[2];
    var input_value_with_matched_string_highlighted =
    'matched: ' +
    before_matched_string +
    '<span class="matched">' + matched_string + '</span>' +
    after_matched_string;

Чтобы идти дальше, я бы посоветовал прочитать "JavaScript: в хорошие части" и начать использовать JSLint, в таком порядке: это поучительный опыт на вашем пути к овладению языке JavaScript. Наоборот, используя инструмент без понимания мировоззрения его автора, очень неприятно.

Я побежал JSLint на ваш код. Он имеет один важный жалобы, спрятанные среди расщеплений волос: декларация new_example отсутствует, поэтому глобальная переменная, которая подвержена привести к неожиданным ошибкам.

   // var keyword added:
var new_example = $('div#examples p:last').clone();

4
ответ дан 26 февраля 2011 в 03:02 Источник Поделиться