// Copyright 2007-2012 The MathWorks, Inc. function createHighlightSpanStart(num) { return ""; } var str2pos; // This is a map between a tag stripped string and the original string. function getTagStrippedStringAndMap(aString) { var tagStrippedString = new String(); str2pos = new Array(); var inTag = false; var inScript = false; for (var strPos = 0; strPos < aString.length; strPos++) { if (inTag && aString.charAt(strPos) == '>') { inTag = false; if (inScript && (strPos > 8) && (aString.slice(strPos, strPos - 8) == '/script>')) { inScript = false; } continue; } else if (!inTag && aString.charAt(strPos) == '<') { inTag = true; if (!inScript && aString.slice(strPos, strPos + 7) == ' str2posprev+1) // we have jumped some text, so there must be a tag { // insert end tag newText += highlightEndTag; // insert intermediate body text tags newText += bodyText.slice(str2posprev+1, str2pos[cnt]); // insert start tag newText += highlightStartTag; } newText += bodyText.charAt(str2pos[cnt]); str2posprev=str2pos[cnt]; } // insert end newText += highlightEndTag; return newText; } // check to see if the sequence at position 'i' in taglessString is actually in // the middle of an escape sequence. We assume escape sequences follow the pattern // &;. We check for  , <, > and & function isInEscapedSequence(i, taglessString, searchTerm) { var escapeSeq = / |<|>|&/gi; var maxEscapeSeqLength = 6; var startPos = 0; var endPos = 0; // exit if the search term has an escape sequence inside it if (escapeSeq.test(searchTerm)) { return false; } // reset the escape sequence escapeSeq = / |<|>|&/gi; // go back in the string until we find an ampersand or we hit maxEscapeSeqLength characters tempI = i; var bFound = false; while (tempI >= 0 && tempI > (i-maxEscapeSeqLength)) { if (taglessString.charAt(tempI) == "&") { startPos = tempI; bFound = true; break; } tempI = tempI-1; // if we hit a ';' in any position other than the first while searching // for an ampersand, then we cannot be inside an escape sequence if (tempI >= 0 && taglessString.charAt(tempI) == ";") { return false; } } if (!bFound) { return false; } // reset the escape sequence escapeSeq = / |<|>|&/gi; var subString = taglessString.substring(startPos, startPos + maxEscapeSeqLength); return escapeSeq.test(subString); } // Adds highlighting to bodyText around searchTerm. Case sensitivity is optional. // hitCount is used to a) count the number of search matches and b) Generate unique // name strings for each highlighting SPAN element. function addHighlight(bodyText, searchTerm, caseSensitive, hitCount) { var highlightStartTag = ""; var highlightEndTag = ""; var newText = ""; var i = 0; var previ = 0; var bodyTextUC = bodyText.toUpperCase(); if (caseSensitive) { var taglessString = getTagStrippedStringAndMap(bodyText); } else { var taglessString = getTagStrippedStringAndMap(bodyTextUC); } // escape the search term in case the user input '<' or '>' etc searchTerm = escapeSpecialChars(searchTerm); if (!caseSensitive) { var searchTermUC = searchTerm.toUpperCase(); } // search for subsequent matches while (true) { if (caseSensitive) { i = taglessString.indexOf(searchTerm, i); } else { i = taglessString.indexOf(searchTermUC, i); } if (i < 0) break; // we have a match! // make sure that the match is not inside an escaped sequence of text // such as   if (isInEscapedSequence(i, taglessString, searchTerm)) { i=i+1; continue; } // insert highlight tags that cross tag boundaries highlightStartTag = createHighlightSpanStart(hitCount); hitCount = hitCount+1; newText += insertHighlighting(bodyText, previ, i, searchTerm.length, highlightStartTag, highlightEndTag); previ = str2pos[i+searchTerm.length-1]+1; i = i + searchTerm.length; } newText += bodyText.slice(previ, bodyText.length); return [newText, hitCount]; } function removeHighlight(bodyText) { // We use regular expressions here rather than a straight text search because // some browsers actually insert double quotes and capitalize. Also, each highlight // name is uniquely numbered in order of discovery var highlightStartTag = //i; var highlightEndTag = /<\/span>/i; var newText = ""; var startPatternFirstIndex = -1; var startPatternLastIndex = -1; var endPatternFirstIndex = -1; var endPatternLastIndex = -1; while (highlightStartTag.test(bodyText) === true) { startPatternFirstIndex = bodyText.search(highlightStartTag); newText += bodyText.substring(0, startPatternFirstIndex); startPatternLastIndex = bodyText.indexOf('>', startPatternFirstIndex+1); bodyText = bodyText.substr(startPatternLastIndex+1); endPatternFirstIndex = bodyText.search(highlightEndTag); newText += bodyText.substring(0, endPatternFirstIndex); endPatternLastIndex = endPatternFirstIndex+7; bodyText = bodyText.substr(endPatternLastIndex); } if (startPatternFirstIndex < 0) { return bodyText; } else { return newText+bodyText; } } function removeHighlightInAllDocs() { if (top) { for (var i = 0; i < top.frames.length; i++) { if (top.frames[i].name === "rtwreport_contents_frame" || top.frames[i].name === "rtwreport_document_frame") { var currentDoc = top.frames[i].document; if (typeof currentDoc.body !== "undefined" && currentDoc.body !== null) currentDoc.body.innerHTML=removeHighlight(currentDoc.body.innerHTML); } } } } function findInDoc(searchStringFromSubmitBox, doc, caseSensitive, hitCount) { var searchBody = doc.body.innerHTML; // if the document is empty, or the documents is invalid, return if (!doc.body || typeof(searchBody) === "undefined") { return [false, hitCount]; } // inject highlighting code into html var result = addHighlight(searchBody, searchStringFromSubmitBox, caseSensitive, hitCount); doc.body.innerHTML = result[0]; return [true, result[1]]; } var currentlyHighlightedHit; function getSpansByName(name) { var allSpans = []; for (i = 0; i < top.frames.length; i++) { if (top.frames[i].name === "rtwreport_contents_frame" || top.frames[i].name === "rtwreport_document_frame") { var currentDoc = top.frames[i].document; var highlightedSpans = currentDoc.getElementsByName(name); if (highlightedSpans && highlightedSpans.length && highlightedSpans.length > 0) { for (j = 0; j < highlightedSpans.length; j++) { allSpans = allSpans.concat(highlightedSpans[j]); } } } } return allSpans; } function isVisibleElement(elementID) { if (elementID) return elementID.offsetWidth > 0 || elementID.offsetHeight > 0; else return false; } function areAllSpansVisible(spans) { isVisible = true; for (i = 0; i < highlightedSpans.length; i++) { isVisible = isVisible && isVisibleElement(highlightedSpans[i]); } return isVisible; } function getNextVisible() { var isVisible = false; var foundVisible = false; while (!isVisible) { currentlyHighlightedHit = currentlyHighlightedHit + 1; highlightedSpans = setCurrentSearchMatchIfVisible(currentlyHighlightedHit); if (highlightedSpans && highlightedSpans.length > 0) { isVisible = true; } else if (currentlyHighlightedHit < totalHits) { continue; } else { // we have reached the end isVisible = false; currentlyHighlightedHit = 0; highlightedSpans = null; break; } } return highlightedSpans; } function clearCurrentSearchMatch() { // clear prior highlighting spanName = "highlight" + currentlyHighlightedHit; highlightedSpans = getSpansByName(spanName); if (highlightedSpans && highlightedSpans.length) { for (i = 0; i < highlightedSpans.length; i++) { if (highlightedSpans[i]) { highlightedSpans[i].setAttribute("class", "highlighted"); } } } } function setCurrentSearchMatchIfVisible(hitNum){ currentlyHighlightedHit = hitNum; var spanName = "highlight" + currentlyHighlightedHit; var highlightedSpans = getSpansByName(spanName); if (highlightedSpans && highlightedSpans.length) { for (i = 0; i < highlightedSpans.length; i++) { if (!isVisibleElement(highlightedSpans[i])) { highlightedSpans = null; break; } } } return highlightedSpans; } // this takes in an option integer 'hitNum'. If not specified, it scrolls // to the next hit function scrollToNextHit(hitNum) { var i = 0; var found = false; var spanName = ""; var highlightedSpans; var searchBox = findElement('searchTxtBox'); clearCurrentSearchMatch(); if (hitNum) { // if a number is provided, use it highlightedSpans = setCurrentSearchMatchIfVisible(hitNum); } else { // start working on next element to highlight highlightedSpans = getNextVisible(); } // we found the current if (highlightedSpans && highlightedSpans.length > 0) { highlightedSpans[0].scrollIntoView(); for (i = 0; i < highlightedSpans.length; i++) { highlightedSpans[i].setAttribute("class", "highlightedCurrent"); } searchBox.setAttribute("class", "search"); // if highlightedSpans is invalid, then we did not find any valid, visible subsequent matches // wrap to beginning or indicate no matches } else { // Element not found. Scroll to first visible element currentlyHighlightedHit = 0; var highlightedSpans = getNextVisible(currentlyHighlightedHit); if (highlightedSpans && highlightedSpans.length > 0) { highlightedSpans[0].scrollIntoView(); for (i = 0; i < highlightedSpans.length; i++) { highlightedSpans[i].setAttribute("class", "highlightedCurrent"); } searchBox.setAttribute("class", "search"); } else { // there aren't any matches searchBox.setAttribute("class", "failedSearch"); } } } // find search box function findElement(element) { var i = 0; for (i = 0; i < top.frames.length; i++) { if (top.frames[i].name === "rtwreport_contents_frame" || top.frames[i].name === "rtwreport_document_frame") { var elem = top.frames[i].document.getElementById(element); if (elem) { return elem; } } } } // Restore search term once form is submitted function initSearchBox(strInitValue) { var txtBox = findElement('searchTxtBox'); if (txtBox) { txtBox.value = strInitValue; } } // Sets focus back on to the text box function setFocusOnTxtBox() { var txtBox = findElement('searchTxtBox'); if (txtBox) { txtBox.focus(); txtBox.select(); } return txtBox; } var previousSearchString; var totalHits; function findInAllDocs(searchStringFromSubmitBox, caseSensitive) { if (previousSearchString != searchStringFromSubmitBox) { // If the search string has changed or a new page has been loaded, do a new search var hitCount = 1; var i = 0; var success = false; previousSearchString = searchStringFromSubmitBox; // start by removing traceinfo highlighting rtwRemoveHighlighting(); // remove all previous search highlighting removeHighlightInAllDocs(); // 1. Iterate through all frames in window and search for (i = 0; i < top.frames.length; i++) { var currentDoc = top.frames[i].document; // if we have no search term, restore if (searchStringFromSubmitBox !== "") { // search and highlight in all frames var srchResult = findInDoc(searchStringFromSubmitBox, currentDoc, caseSensitive, hitCount); hitCount = srchResult[1]; totalHits = srchResult[1]; } } // 2. Restore search term once form is submitted and text highlighted if (searchStringFromSubmitBox != "") { strInitValue = searchStringFromSubmitBox; } initSearchBox(strInitValue); // 3. Scroll to the first hit encountered scrollToNextHit(1); // 4. Set focus back to text box and select text var txtBox = setFocusOnTxtBox(); if (txtBox) { txtBox.select(); } } else { // If the search string is the same, then scroll to the next // hit if the hit is valid. Else wrap back. scrollToNextHit(); } return false; } // if the search box is empty, clear highlighting function clearIfEmpty() { txtBox = findElement('searchTxtBox'); if (txtBox.value == "") { txtBox.setAttribute("class", "search"); removeHighlightInAllDocs(); previousSearchString=""; setFocusOnTxtBox(); } } function keyPressSwitchyard(keyPressEvent) { var kc; keyPressEvent = (keyPressEvent == null ? window.keyPressEvent : keyPressEvent); // typically IE does not support this if (!keyPressEvent || (typeof keyPressEvent == "undefined")) { return; } if (keyPressEvent.keyCode) { kc=keyPressEvent.keyCode; } else if (keyPressEvent.which) { kc=keyPressEvent.which; } else { return; } // we do not care about the browser find appearing. If it does appear, then // we are running an external browser and that is okay. // handle Ctrl-Key combinations if (keyPressEvent.ctrlKey) { switch (kc) { case 70: // Ctrl-F { setFocusOnTxtBox(); break; } default: break; } } } function installDocumentKeyPressHandler() { var i = 0; for (i = 0; i < top.frames.length; i++) { var currentDoc = top.frames[i].document; currentDoc.onkeydown = keyPressSwitchyard; } top.document.onkeydown = keyPressSwitchyard; // This also clears search related highlighting removeHighlightInAllDocs(); currentlyHighlightedHit = 0; if (previousSearchString) initSearchBox(previousSearchString); previousSearchString = ""; } // This function is a onresize callback for the rtwreport_contents_frame // It is used to dynamically resize the searchbox based on the size of the frame. function setWidthDynamic(frameID, elementID, extraSpace, minSize) { var frame = document.getElementById(frameID); // sanity check input args if (frame && extraSpace > 0 && minSize > 0) { var frameWidth = frame.scrollWidth; var newSize = extraSpace + minSize + 40; // 40 is the extra whitespace var element = findElement(elementID); if (element) { if (frameWidth < newSize) { element.style.width = minSize; } else { element.style.width = frameWidth - extraSpace - 40; } } } }