2016-10-19 1 views
2

문자열 내에서 (배열에서) 하위 문자열을 찾고 하위 문자열과 동일한 제목을 가진 드롭 다운 상자로 바꿉니다.JQuery : 문자열 내의 부분 문자열의 여러 인스턴스를 오류없이 html로 바꾸십시오.

문자열은 사용자 입력에서 왔으며 하위 문자열은 작업 코드에서 데이터베이스에서 가져온 것입니다.

는이 질문에 DavidTonarini에 의해 주어진 대답에서 일한 : Javascript: replace() all but only outside html tags

그러나 이것은 단지 '<'과 '<'사이에 포함되는 텍스트를 제외합니다.

입력 한 경우 : '레벨을 한 레벨'로 포함 시키면 '레벨'이 드롭 다운 상자로 반환되지만 '레벨'이 일반 텍스트로 반환됩니다. 배열의 항목과 일치해야하고 드롭 다운 상자로 대체됩니다. 사용자 입력 내에서 동일한 문자열을 반복 할 때도 문제가 발생합니다. 사용자 입력 내에서 동일한 하위 문자열을 여러 번 일치시키는 기능이 필요합니다. ,

var regEx = new RegExp("(" + searchWord + ")(?!([^<]+)?>)", "gi") 

문제, 당신은 이미 자신을 발견하는 것 같이

var data = { 
    "a_levels": { 
    "a_level": { 
     id: 1, 
     units: 2, 
     created: "2016-10-04 19:00:05", 
     updated: "2016-10-05 09:37:46" 
    }, 
    "a_levels": { 
     id: 2, 
     units: 2, 
     created: "2016-10-05 08:19:27", 
     updated: "2016-10-05 09:37:39" 
    } 
    }, 
    "a_level": { 
    "a_level": { 
     id: 1, 
     units: 2, 
     created: "2016-10-04 19:00:05", 
     updated: "2016-10-05 09:37:46" 
    }, 
    "a_levels": { 
     id: 2, 
     units: 2, 
     created: "2016-10-05 08:19:27", 
     updated: "2016-10-05 09:37:39" 
    } 
    } 
}; 
var input, // Create empty variables. 
    response; 

$('#submit').click(function() { 
    input = $('#userInput').val(); 
    response = input; 
    // CREATE DROPDOWN BOXES. 
    var strings_used = []; 
    $.each(data, function(i, v) { // Iterate over first level of output. 

    for (var itr = 0; itr < strings_used.length; ++itr) { 
     if (strings_used[itr].indexOf(i) !== -1) { 
     return true; 
     } 
    } 
    var searchWord = i.replace(/_/g, " "); // Replace underscores in matches with blank spaces. 
    var regEx = new RegExp("(" + searchWord + ")(?!([^<]+)?>)", "gi"); // Create regular expression which searches only for matches found outside html tags. 
    var tmp = response.replace(regEx, "<span class='btn-group'><button class='btn btn-primary dropdown-toggle' type='button' data-toggle='dropdown'>" + searchWord + "<span class='caret'></span></button><ul class='" + i + " dropdown-menu'></ul></span>"); // Replace matching substrings with dropdown boxes. 
    if (tmp !== response) { // Check if replacement is complete. 
     response = tmp; // Update response. 
     strings_used.push(i); 
    } 
    }); 
    $('#template').empty().append(response); // Populate template container with completed question response including dropdown boxes. 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

<body> 

    <div id="searchbox"> 
    <div class="input-group"> 
     <input id="userInput" type="text" class="form-control" placeholder="type here..."> 
     <span id="submit" class="input-group-btn"> 
\t \t \t <button class="btn btn-default" type="submit">GO!</button> 
\t \t \t </span> 
    </div> 
    </div> 

    <div class="row"> 
    <div id="template" class="col-sm-10 col-md-offset-1 text-left"></div> 
    </div> 

</body>

답변

1

버그는 정규식에서 유래하고, 방법은 당신이 그것을 사용하는 "a levels""...toggle='dropdown'>a levels<span class='caret'>..."으로 바꾼 후에이 패턴 은 앞으로 루프의 미래의 반복과 일치합니다 (즉,의 경우). 0) - 결과 HTML을 망쳤습니다.

당신은 패치를 추가하여이 문제를 해결하려고 :

for (var itr = 0; itr < strings_used.length; ++itr) { 
    if (strings_used[itr].indexOf(i) !== -1) { 
    return true; 
    } 
} 

그러나이 또한 작동하지 않습니다 - 만 원래 오류를 모호하게 봉사했다. 이제 의 패턴 일치로이 종료됩니다. 따라서 "a level"은 (는) "a levels"과 일치하는 경우 검색되지 않습니다. 완전히 당신의 방법을 작동 방식을 변경하지 않고

, 여기에 빠른 패치입니다 - 나는 단순히 strings_used 논리를 제거하여 정규 표현식을 대체했습니다

var regEx = new RegExp("(\\b" + searchWord + "\\b)(?!<)", "gi"); 

var data = { 
 
    "a_levels": { 
 
    "a_level": { 
 
     id: 1, 
 
     units: 2, 
 
     created: "2016-10-04 19:00:05", 
 
     updated: "2016-10-05 09:37:46" 
 
    }, 
 
    "a_levels": { 
 
     id: 2, 
 
     units: 2, 
 
     created: "2016-10-05 08:19:27", 
 
     updated: "2016-10-05 09:37:39" 
 
    } 
 
    }, 
 
    "a_level": { 
 
    "a_level": { 
 
     id: 1, 
 
     units: 2, 
 
     created: "2016-10-04 19:00:05", 
 
     updated: "2016-10-05 09:37:46" 
 
    }, 
 
    "a_levels": { 
 
     id: 2, 
 
     units: 2, 
 
     created: "2016-10-05 08:19:27", 
 
     updated: "2016-10-05 09:37:39" 
 
    } 
 
    } 
 
}; 
 
var input, // Create empty variables. 
 
    response; 
 

 
$('#submit').click(function() { 
 
    input = $('#userInput').val(); 
 
    response = input; 
 
    // CREATE DROPDOWN BOXES. 
 
    $.each(data, function(i, v) { // Iterate over first level of output. 
 

 
    // ** REMOVED: ** 
 
    // for (var itr = 0; itr < strings_used.length; ++itr) { 
 
    // if (strings_used[itr].indexOf(i) !== -1) { 
 
    //  return true; 
 
    // } 
 
    // } 
 

 
    var searchWord = i.replace(/_/g, " "); // Replace underscores in matches with blank spaces. 
 

 
    // ** CHANGED: ** 
 
    var regEx = new RegExp("(\\b" + searchWord + "\\b)(?!<)", "gi"); 
 

 
    var tmp = response.replace(regEx, "<span class='btn-group'><button class='btn btn-primary dropdown-toggle' type='button' data-toggle='dropdown'>" + searchWord + "<span class='caret'></span></button><ul class='" + i + " dropdown-menu'></ul></span>"); // Replace matching substrings with dropdown boxes. 
 
    if (tmp !== response) { // Check if replacement is complete. 
 
     response = tmp; // Update response. 
 
    } 
 
    }); 
 
    $('#template').empty().append(response); // Populate template container with completed question response including dropdown boxes. 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<body> 
 

 
    <div id="searchbox"> 
 
    <div class="input-group"> 
 
     <input id="userInput" type="text" class="form-control" placeholder="type here..."> 
 
     <span id="submit" class="input-group-btn"> 
 
     <button class="btn btn-default" type="submit">GO!</button> 
 
     </span> 
 
    </div> 
 
    </div> 
 

 
    <div class="row"> 
 
    <div id="template" class="col-sm-10 col-md-offset-1 text-left"></div> 
 
    </div> 
 

 
</body>

그러나, 훨씬 깨끗한 해결책은 한 번에 찾기 및 바꾸기를 수행하는 것입니다. 따라서 "ar e는 HTML 요소 안에 있지 않습니다. " 복사 한 솔루션의 게시물에 대한 의견이 올바르게 지적되었으므로이 상황이 정확하게 발생했기 때문에 a bad idea to parse HTML with regex입니다!

당신이에서 이동을하는 내가 운동으로이를 떠나 겠지만, 기본적으로 내가 코드를 간단하게 검색하는 것이 좋습니다 것 :

var regEx = new RegExp("\\b(a level|a levels)\\b", "gi"); 

와 함께 대체

... data-toggle='dropdown'>$1<span class='caret'> ... 

편집 : 생에 대한

$('#submit').click(function() { 
    var input = $('#userInput').val(); 
    var regEx = new RegExp("\\b(" + Object.keys(data).join('|').replace(/_/g, " ") + ")\\b", "gi"); 
    $('#template').html(
    input.replace(
     regEx, 
     "<span class='btn-group'><button class='btn btn-primary dropdown-toggle' type='button' data-toggle='dropdown'>$1<span class='caret'></span></button><ul class='" + "$1".replace(/ /g, "_") + "' dropdown-menu'></ul></span>" 
    ) 
); 
}); 
+0

감사합니다 아래에 설명하고있는 바와 같이, 여기에 훨씬 짧은, 간단하고 버그가없는 구현 가능한 스케치입니다 에스. 나는 인터넷에 대한 접근이 제한적 이었지만, 이것이 정확하다는 것을 보았다. 잠시 후 곧 업데이트됩니다. 더 많은 정규 표현식을 연습 할 필요가 있습니다. –

+0

Woah woah woah, 잠시만 기다려주세요. 패치 된 버전의 코드를 사용하고 복잡한 요구 사항을 수정하기보다는 코드를 리팩터링하는 것이 좋습니다. 올바른 트랙을 찾으려면 다음과 같은 간단한 스케치가 필요합니다. https://jsfiddle.net/huwwefa0/15/ –

+0

여기에 더 필요한 버전이 있습니다 .... 깔끔하게 작성된 코드를 변경하는 것이 훨씬 쉽습니다.) https://jsfiddle.net/huwwefa0/16/ –

관련 문제