How can I get the iframes on the page? I want to get an external options(width, height, id, src) and inner HTML.
It's all I can get only if the iframes on the page are not dynamically added. If they are dynamically added, the order of the IFRAME in the DOM and in the frameid (switchToFrame(frameid)) differs, and I can not compare them.
HTML:
<iframe src="iframe.php?id=1"></iframe>
<iframe src="iframe.php?id=2"></iframe>
<div id="dynamic_iframe"></div>
<div id="dynamic_iframe2"></div>
<iframe src="iframe.php?id=3"></iframe>
<script>
var el = document.createElement("iframe");
el.src = 'iframe.php?id=21';
document.getElementById('dynamic_iframe').appendChild(el);
var el = document.createElement("iframe");
el.src = 'iframe.php?id=22';
document.getElementById('dynamic_iframe2').appendChild(el);
</script>
PhantomJS:
getAllIFramesFromPage = function(page){
return page.evaluate(function() {
var matches = document.querySelectorAll('iframe');
ifames = [];
for(var i = 0; i < matches.length; ++i){
ifames.push(matches[i].src);
}
return ifames;
});
};
out:
iframe.php?id=1
iframe.php?id=2
iframe.php?id=21
iframe.php?id=22
iframe.php?id=3
PhantomJS:
var cnt = page.framesCount;
for(var i = 0; i < cnt; i++){
page.switchToFrame(i);
console.log(page.framePlainText);
page.switchToMainFrame();
}
out:
1
2
3
21
22
I was able to get out of a problem like this:
When I pass all the iframe into the DOM I put in them hidden value
page.switchToMainFrame();
page.evaluate(function() {
var matches = document.querySelectorAll('iframe');
ifames = [];
for(var i = 0; i < matches.length; ++i){
var iframeWindow = matches[i].contentWindow || matches[i].contentDocument.parent;
var frmBody = iframeWindow.document.getElementsByTagName("body")[0].frame_id = i;
}
});
Already inside an iframe I can get this value as follows:
var cnt = this.page.framesCount;
for(var i = 0; i < cnt; i++){
page.switchToFrame(i);
frameIndex = this.page.evaluate(function() {
if (document.getElementsByTagName("body")[0].frame_id !== undefined){
return document.getElementsByTagName("body")[0].frame_id;
}
return false;
});
this.page.switchToParentFrame();
}
Related
I have used AjaxToolkit HtmlEditor and want to add the capability adding table to it.
How to add Table Item in toolbar?
%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit.HTMLEditor" TagPrefix="cc1" %>
<cc1:Editor runat="server" Width="700px" Style="margin: 0px auto; direction: rtl;" ID="Editor" Height="500px" CssClass="ajax__htmleditor_editor_container"
/>
I have found an approach in following link but I can't add table Item.
This solution adds an "insert table button" to the AjaxControlToolKit's "Editor" control (functionality is modeled and similar to that in Microsoft Word).
Now, I'm not saying this is a great solution (or code for that matter), since I just quickly whipped it together -- but it should give you the solution you want, with a solid base to refactor, etc.
Use the following steps to accomplish this:
1.)Create a new class file (Extended_AjaxToolkitHtmlEditor.cs) in your App_Code folder (if the folder does not exist, create it) and paste the following code into it:
using System;
using System.Text;
using System.Web.UI.WebControls;
using AjaxControlToolkit.HTMLEditor;
using AjaxControlToolkit.HTMLEditor.ToolbarButton;
namespace Extended_AjaxToolkitHtmlEditor
{
public class Extended_AjaxToolkitHtmlEditor : Editor
{
protected override void FillTopToolbar()
{
base.FillTopToolbar();
TopToolbar.Buttons.Add(new AddHtmlTable_HtmlEditorToolbarButton());
}
}
public class AddHtmlTable_HtmlEditorToolbarButton : MethodButton
{
private const string _strHtmlTableBase64Image = #"iVBORw0KGgoAAAANSUhEUgAAABYAAAAUCAYAAACJfM0wAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAABMSURBVDhPY0xISPjPQAPABKWpDoaewQygMMYFNm/eDGVhAnxyIDOHXlCAk1twcDCUSx2wdu3a0TBGgNEwhoPRMAaDIRzGUDYVAQMDADlBXF6jlWZpAAAAAElFTkSuQmCC";
private string _strJavaScript;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
CssClass += " HtmlEditorAddTable";
Attributes.Add("onclick", #"Extended_AjaxToolKitEditorControl.ShowTablePopUp();");
_strJavaScript = #"<script>
var Extended_AjaxToolKitEditorControl = {
hasBeenInitialized : false,
divMainTable : {},
divMainTable_ChildElements : [],
Initialize_Elements : function(){
Extended_AjaxToolKitEditorControl.hasBeenInitialized = true;
var imgTableButtonElement = document.getElementById('" + ClientID + #"');
var imgTableButtonElement_boundingRectangle = imgTableButtonElement.getBoundingClientRect();
var divChildTableElement_toClone = document.createElement('div');
var divSpacerElement = {};
Extended_AjaxToolKitEditorControl.divMainTable = document.createElement('div');
Extended_AjaxToolKitEditorControl.divMainTable.id = 'divAjaxToolKit_editorControlExtended_mainTable';
Extended_AjaxToolKitEditorControl.divMainTable.style.background = 'white';
Extended_AjaxToolKitEditorControl.divMainTable.style.border = '1px solid black';
Extended_AjaxToolKitEditorControl.divMainTable.style.position = 'absolute';
Extended_AjaxToolKitEditorControl.divMainTable.style.visibility = 'hidden';
Extended_AjaxToolKitEditorControl.divMainTable.style.width = '220px';
Extended_AjaxToolKitEditorControl.divMainTable.style.height = '185px';
Extended_AjaxToolKitEditorControl.divMainTable.style.top = (imgTableButtonElement_boundingRectangle.bottom + window.pageYOffset) + 'px';
Extended_AjaxToolKitEditorControl.divMainTable.style.left = (imgTableButtonElement_boundingRectangle.left + window.pageXOffset) + 'px';
Extended_AjaxToolKitEditorControl.divMainTable.style.right = (imgTableButtonElement_boundingRectangle.right + window.pageXOffset) + 'px';
Extended_AjaxToolKitEditorControl.divMainTable.onmouseleave = function() { Extended_AjaxToolKitEditorControl.HideTablePopUp(); };
divChildTableElement_toClone.style.width = '10px';
divChildTableElement_toClone.style.height = '10px';
divChildTableElement_toClone.style.background = 'white';
divChildTableElement_toClone.style.border = '1px solid black';
divChildTableElement_toClone.style.marginRight = '5px';
divChildTableElement_toClone.style.marginLeft = '5px';
divChildTableElement_toClone.style.marginTop = '5px';
divChildTableElement_toClone.style.marginBottom = '5px';
divChildTableElement_toClone.style.display = 'inline-block';
for (var i = 0; i < 8; i++){ Extended_AjaxToolKitEditorControl.divMainTable_ChildElements.push([divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true), divChildTableElement_toClone.cloneNode(true)]); }
for (var rowCounter in Extended_AjaxToolKitEditorControl.divMainTable_ChildElements){
for (var columnCounter in Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[rowCounter]){
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[rowCounter][columnCounter].id = 'newDArr_' + rowCounter + '_' + columnCounter;
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[rowCounter][columnCounter].setAttribute('data-rowCounter', rowCounter);
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[rowCounter][columnCounter].setAttribute('data-columnCounter', columnCounter);
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[rowCounter][columnCounter].onclick = function(){ Extended_AjaxToolKitEditorControl.InsertHtmlTable(this.id); };
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[rowCounter][columnCounter].onmouseover = function(){ Extended_AjaxToolKitEditorControl.SelectElementsInPopup(this.id); };
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[rowCounter][columnCounter].onmouseout = function(){ Extended_AjaxToolKitEditorControl.UnSelectElementsInPopup(this.id); };
Extended_AjaxToolKitEditorControl.divMainTable.appendChild(Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[rowCounter][columnCounter]);
}
divSpacerElement = document.createElement('div');
divSpacerElement.style.display = 'block';
divSpacerElement.style.height = '1px';
Extended_AjaxToolKitEditorControl.divMainTable.appendChild(divSpacerElement);
}
imgTableButtonElement.parentNode.appendChild(Extended_AjaxToolKitEditorControl.divMainTable);
},
SelectElementsInPopup : function(paramDivId){
var divParameter = document.getElementById(paramDivId);
var divAttributeParamRowCount = divParameter.getAttribute('data-rowCounter');
var divAttributeParamColumnCount = divParameter.getAttribute('data-columnCounter');
for (var i = 0; i <= divAttributeParamRowCount; i++){
for (var j = 0; j <= divAttributeParamColumnCount; j++){
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[i][j].style.background = 'yellow';
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[i][j].style.border = '1px solid black';
}
}
},
UnSelectElementsInPopup : function(paramDivId){
var divParameter = document.getElementById(paramDivId);
var divAttributeParamRowCount = divParameter.getAttribute('data-rowCounter');
var divAttributeParamColumnCount = divParameter.getAttribute('data-columnCounter');
for (var i = 0; i <= divAttributeParamRowCount; i++){
for (var j = 0; j <= divAttributeParamColumnCount; j++){
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[i][j].style.background = 'white';
Extended_AjaxToolKitEditorControl.divMainTable_ChildElements[i][j].style.border = '1px solid black';
}
}
},
InsertHtmlTable : function(paramDivId){
var tableElement = document.createElement('table');
tableElement.style.width = '250px';
tableElement.style.height = '200px';
tableElement.border = '1';
var tableRowElement = {};
var tableColumnElement = {};
var divParameter = document.getElementById(paramDivId);
var divAttributeParamRowCount = divParameter.getAttribute('data-rowCounter');
var divAttributeParamColumnCount = divParameter.getAttribute('data-columnCounter');
for (var i = 0; i <= divAttributeParamRowCount; i++){
tableRowElement = tableElement.insertRow(i);
for (var j = 0; j <= divAttributeParamColumnCount; j++){ tableColumnElement = tableRowElement.insertCell(j); }
}
var editPanelElement = document.getElementById('" + this.Parent.Parent.Parent.Parent.Parent.ClientID + #"').control.get_editPanel().get_modePanels()[0].insertHTML(tableElement.outerHTML);
},
HideTablePopUp : function(){
var divMainTableElement = document.getElementById('divAjaxToolKit_editorControlExtended_mainTable');
divMainTableElement.style.visibility = 'hidden';
},
ShowTablePopUp : function(){
if (Extended_AjaxToolKitEditorControl.hasBeenInitialized != true){ Extended_AjaxToolKitEditorControl.Initialize_Elements(); }
var divMainTableElement = document.getElementById('divAjaxToolKit_editorControlExtended_mainTable');
divMainTableElement.style.visibility = 'visible';
}
};
</script>";
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
var literalNewCSS = new Literal();
var strbldrStyleElement = new StringBuilder();
strbldrStyleElement.AppendLine(#"<style>");
strbldrStyleElement.AppendLine(#".HtmlEditorAddTable");
strbldrStyleElement.AppendLine(#"{");
strbldrStyleElement.AppendLine(#" width:23px !important;");
strbldrStyleElement.AppendLine(#" height:21px !important;");
strbldrStyleElement.AppendLine(#" margin-left:2px !important;");
strbldrStyleElement.AppendLine(#" background-image: url(data:image/png;base64," + _strHtmlTableBase64Image + ");");
strbldrStyleElement.AppendLine(#" background-repeat: no-repeat;");
strbldrStyleElement.AppendLine(#"}");
strbldrStyleElement.AppendLine(#"</style>");
literalNewCSS.Text = strbldrStyleElement.ToString();
Page.Header.Controls.Add(literalNewCSS);
Page.RegisterClientScriptBlock("Register_Extended_AjaxToolKitEditorControlJS", _strJavaScript);
}
}
}
2.)Then in the ASPX page, that you want to use this control, add the following at top of the file:
<%# Register Namespace="Extended_AjaxToolkitHtmlEditor" TagPrefix="extendedEditor" %>
3.)Then finally in form element to the ASPX page add the control like so below:
<extendedEditor:Extended_AjaxToolkitHtmlEditor runat="server" />
Notes:
1.)Be careful of the "aspx.designer.cs" file of the page you are adding this control to (if you are using one) -- when you put an ID on this new control element, errors get thrown. However, if you simply remove the entry that gets added in, it will still work and remove the errors.
2.)This solution assumes you have the AjaxControlToolkit downloaded and added into your project/references already. You can download it at: http://ajaxcontroltoolkit.codeplex.com/
You can do it in Javascript with an external button
<script type="text/JavaScript">
function insertTable() {
var editor = $find("<%= myEditor.ClientID %>");
var editPanel = editor.get_editPanel();
var designMode = AjaxControlToolkit.HTMLEditor.ActiveModeType.Design;
if(editPanel.get_activeMode() == designMode) {
var designPanel = editPanel.get_modePanels()[designMode];
designPanel.insertHTML("<table><tr><td></td></tr></table>");
}
}
</script>
On the aspx page
<cc1:Editor runat="server" id="myEditor" />
<input type="button" value="Insert html table" onclick="insertTable();" />
I have a route that is a combination of multiple sub routes. (By sub routes i mean multiple DirectionsRenderer objects)
I also have a loop where i go throught all of the DirectionsRenderer objects and attach "directions_changed" event to all of them.
Unfortunatelly only that last DirectionsRenderer object fires the event when i try to test what happens when i drag the polyline.
Here is a part of my code:
for(var k=0; k<directionsRenderers.length; k++)
{
var directionsRenderer = directionsRenderers[k];
var a = registerDirectionsChangedEvent(k,directionsRenderer);
}
function registerDirectionsChangedEvent(index, directionsRenderer)
{
this.index = index;
this.directionsRenderer = directionsRenderer;
var that = this;
var a = google.maps.event.addListener(this.directionsRenderer, "directions_changed", function()
{
var newStopPoint;
var directionsResult = that.directionsRenderer.getDirections();
var route = directionsResult.routes[0];
var legs = route.legs;
var legsIndex = 0;
for(var i=0; i<legs.length; i++)
{
var cLeg = legs[i];
var viaWaypoints = cLeg.via_waypoints;
if(viaWaypoints.length > 0)
{
newStopPoint = viaWaypoints[0];
if(that.index === 1) legsIndex += 9;
else if(that.index === 2) legsIndex += 18;
break;
}
legsIndex++;
}
addNewStopPoint(newStopPoint,legsIndex);
});
return a;
}
As i have mentioned above not only the last DirectionsRenderer object get fired but the ones before the last event do not implement the default behaviour.
Maybe you have noticed that i use:
this.index = index;
this.directionsRenderer = directionsRenderer;
var that = this;
event without it it still does not work.
I also tried to use a function created inside the loop like this:
(function someFunction(a,b){//do something here})(a,b);
but still no luck!
any advice how to make it works?
Use function closure, this is probably a duplicate (not tested):
for(var k=0; k<directionsRenderers.length; k++)
{
var directionsRenderer = directionsRenderers[k];
var a = registerDirectionsChangedEvent(k,directionsRenderer);
}
function registerDirectionsChangedEvent(index, directionsRenderer)
{
var a = google.maps.event.addListener(directionsRenderer, "directions_changed", function()
{
var newStopPoint;
var directionsResult = directionsRenderer.getDirections();
var route = directionsResult.routes[0];
var legs = route.legs;
var legsIndex = 0;
for(var i=0; i<legs.length; i++)
{
var cLeg = legs[i];
var viaWaypoints = cLeg.via_waypoints;
if(viaWaypoints.length > 0)
{
newStopPoint = viaWaypoints[0];
if(index === 1) legsIndex += 9;
else if(index === 2) legsIndex += 18;
break;
}
legsIndex++;
}
addNewStopPoint(newStopPoint,legsIndex);
});
return a;
}
I have seen lots of questions about resizing iframes but all of those do not have access to the external url. In this case I do. I can insert a script into the head tag. I was trying to use this script inserted into the main page header containing the iframe (i know the opening and closing frame tags are wrong - it would not let me leave them in:
iframe id="frame-one" scrolling="no" frameborder="0" src="yoursitehereexample" onload="FrameManager.registerFrame(this)" /iframe
and this the js in the header (linked FrameManager.js file)
var FrameManager =
{
currentFrameId : '',
currentFrameHeight : 0,
lastFrameId : '',
lastFrameHeight : 0,
resizeTimerId : null,
init : function()
{
if (FrameManager.resizeTimerId == null)
{
FrameManager.resizeTimerId = window.setInterval(FrameManager.resizeFrames, 500);
}
},
resizeFrames : function()
{
FrameManager.retrieveFrameIdAndHeight();
if ((FrameManager.currentFrameId != FrameManager.lastFrameId) ||
(FrameManager.currentFrameHeight != FrameManager.lastFrameHeight))
{
var iframe = document.getElementById(FrameManager.currentFrameId.toString());
if (iframe == null) return;
iframe.style.height = FrameManager.currentFrameHeight.toString() + "px";
FrameManager.lastFrameId = FrameManager.currentFrameId;
FrameManager.lastFrameHeight = FrameManager.currentFrameHeight;
window.location.hash = '';
}
},
retrieveFrameIdAndHeight : function()
{
if (window.location.hash.length == 0) return;
var hashValue = window.location.hash.substring(1);
if ((hashValue == null) || (hashValue.length == 0)) return;
var pairs = hashValue.split('&');
if ((pairs != null) && (pairs.length > 0))
{
for(var i = 0; i < pairs.length; i++)
{
var pair = pairs[i].split('=');
if ((pair != null) && (pair.length > 0))
{
if (pair[0] == 'frameId')
{
if ((pair[1] != null) && (pair[1].length > 0))
{
FrameManager.currentFrameId = pair[1];
}
}
else if (pair[0] == 'height')
{
var height = parseInt(pair[1]);
if (!isNaN(height))
{
FrameManager.currentFrameHeight = height;
FrameManager.currentFrameHeight += 15;
}
}
}
}
}
},
registerFrame : function(frame)
{
var currentLocation = location.href;
var hashIndex = currentLocation.indexOf('#');
if (hashIndex > -1)
{
currentLocation = currentLocation.substring(0, hashIndex);
}
frame.contentWindow.location = frame.src + '?frameId=' + frame.id + '#' + currentLocation;
}
};
window.setTimeout(FrameManager.init, 300);
Then...I put this in the framed page header ResizeFrame.js as a link:
//orig frame mgr script
$.getScript("http://www.yoursitehereexamle.com/js/FrameManager.js", function(){
});
// external heights load
function publishHeight()
{
if (window.location.hash.length == 0) return;
var frameId = getFrameId();
if (frameId == '') return;
var actualHeight = getBodyHeight();
var currentHeight = getViewPortHeight();
if (Math.abs(actualHeight - currentHeight) > 15)
{
var hostUrl = window.location.hash.substring(1);
hostUrl += "#";
hostUrl += 'frameId=' + frameId;
hostUrl += '&';
hostUrl += 'height=' + actualHeight.toString();
window.top.location = hostUrl;
}
}
function getFrameId()
{
var qs = parseQueryString(window.location.href);
var frameId = qs["frameId"];
var hashIndex = frameId.indexOf('#');
if (hashIndex > -1)
{
frameId = frameId.substring(0, hashIndex);
}
return frameId;
}
function getBodyHeight()
{
var height;
var scrollHeight;
var offsetHeight;
if (document.height)
{
height = document.height;
}
else if (document.body)
{
if (document.body.scrollHeight)
{
height = scrollHeight = document.body.scrollHeight;
}
if (document.body.offsetHeight)
{
height = offsetHeight = document.body.offsetHeight;
}
if (scrollHeight && offsetHeight)
{
height = Math.max(scrollHeight, offsetHeight);
}
}
return height;
}
function getViewPortHeight()
{
var height = 0;
if (window.innerHeight)
{
height = window.innerHeight - 18;
}
else if ((document.documentElement) && (document.documentElement.clientHeight))
{
height = document.documentElement.clientHeight;
}
else if ((document.body) && (document.body.clientHeight))
{
height = document.body.clientHeight;
}
return height;
}
function parseQueryString(url)
{
url = new String(url);
var queryStringValues = new Object();
var querystring = url.substring((url.indexOf('?') + 1), url.length);
var querystringSplit = querystring.split('&');
for (i = 0; i < querystringSplit.length; i++)
{
var pair = querystringSplit[i].split('=');
var name = pair[0];
var value = pair[1];
queryStringValues[name] = value;
}
return queryStringValues;
}
// window load
window.onload = function(event)
{
window.setInterval(publishHeight, 300);
}
But no luck on getting it to work - can anyone see where I went wrong. The iframe still appears but does not scale. Many Thanks!
Here is my code to resize an iframe with an external website. You need insert a code into the parent (with iframe code) page and in the external website as well, so, this won't work with you don't have access to edit the external website.
local (iframe) page: just insert a code snippet
remote (external) page: you need a "body onload" and a "div" that holds all contents. And body needs to be styled to "margin:0"
Local:
<IFRAME STYLE="width:100%;height:1px" SRC="http://www.remote-site.com/" FRAMEBORDER="no" BORDER="0" SCROLLING="no" ID="estframe"></IFRAME>
<SCRIPT>
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent,function(e) {
if (e.data.substring(0,3)=='frm') document.getElementById('estframe').style.height = e.data.substring(3) + 'px';
},false);
</SCRIPT>
You need this "frm" prefix to avoid problems with other embeded codes like Twitter or Facebook plugins. If you have a plain page, you can remove the "if" and the "frm" prefix on both pages (script and onload).
Remote:
You need jQuery to accomplish about "real" page height. I cannot realize how to do with pure JavaScript since you'll have problem when resize the height down (higher to lower height) using body.scrollHeight or related. For some reason, it will return always the biggest height (pre-redimensioned).
<BODY onload="parent.postMessage('frm'+$('#master').height(),'*')" STYLE="margin:0">
<SCRIPT SRC="path-to-jquery/jquery.min.js"></SCRIPT>
<DIV ID="master">
your content
</DIV>
So, parent page (iframe) has a 1px default height. The script inserts a "wait for message/event" from the iframe. When a message (post message) is received and the first 3 chars are "frm" (to avoid the mentioned problem), will get the number from 4th position and set the iframe height (style), including 'px' unit.
The external site (loaded in the iframe) will "send a message" to the parent (opener) with the "frm" and the height of the main div (in this case id "master"). The "*" in postmessage means "any source".
Hope this helps. Sorry for my english.
I have a string variable assigned with some Content in HTML format.
Some thing like this var strLabel:String = "This is <b>Test</b>;
But in run time i have get the first 10 characters of the string and display it in another control.
For this, what did was
txtLabelName.Text = String(strLabel).substr(0,10) + ' ...';
But in the output i am getting as This is <b. Basically it considering HTML related tags also as text. But my code has to omit the HTML tags while calculating sub string.
Please anybody help me to do this?
Use this regexp to strip html tags (more or less):
txtLabelName.text = strLabel.replace(/\<.+?\>/g, '').substr(0, 10) + ' ...';
It's a very simple regexp to strip all tags so it won't work on more complex tags (probably).
I got this code from some blog. This is working Perfectly
public static function stripHtmlTags(html:String, tags:String = ""):String
{
var tagsToBeKept:Array = new Array();
if (tags.length > 0)
tagsToBeKept = tags.split(new RegExp("\\s*,\\s*"));
var tagsToKeep:Array = new Array();
for (var i:int = 0; i < tagsToBeKept.length; i++)
{
if (tagsToBeKept[i] != null && tagsToBeKept[i] != "")
tagsToKeep.push(tagsToBeKept[i]);
}
var toBeRemoved:Array = new Array();
var tagRegExp:RegExp = new RegExp("<([^>\\s]+)(\\s[^>]+)*>", "g");
var foundedStrings:Array = html.match(tagRegExp);
for (i = 0; i < foundedStrings.length; i++)
{
var tagFlag:Boolean = false;
if (tagsToKeep != null)
{
for (var j:int = 0; j < tagsToKeep.length; j++)
{
var tmpRegExp:RegExp = new RegExp("<\/?" + tagsToKeep[j] + "( [^<>]*)*>", "i");
var tmpStr:String = foundedStrings[i] as String;
if (tmpStr.search(tmpRegExp) != -1)
tagFlag = true;
}
}
if (!tagFlag)
toBeRemoved.push(foundedStrings[i]);
}
for (i = 0; i < toBeRemoved.length; i++)
{
var tmpRE:RegExp = new RegExp("([\+\*\$\/])","g");
var tmpRemRE:RegExp = new RegExp((toBeRemoved[i] as String).replace(tmpRE, "\\$1"),"g");
html = html.replace(tmpRemRE, "");
}
return html;
}
I have flex 4 and writing my own autocomplete component (based on the popupanchor) to search for different books. In the dropdown box, how can I highlight the text that matches? For instance, a user types in "ema" and the search returns "Pet Sematary"....I want to highlight the letters "ema" within "Pet Sematary"
Wrote auto-complete a week ago :) You need to use Spark text components and pass custom TextFlow to them:
private function init():void
{
var textFlow:TextFlow = new TextFlow();
var paragraph:ParagraphElement = new ParagraphElement();
textFlow.addChild(paragraph);
var elements:Vector.<FlowElement> = highlight("Pet Sematary", "Se");
var n:int = elements.length;
for (var i:int = 0; i < n; i++)
{
paragraph.addChild(elements[i]);
}
label.textFlow = textFlow;
}
private function highlight(text:String, query:String):Vector.<FlowElement>
{
var result:Vector.<FlowElement> = new Vector.<FlowElement>();
// since we need to compare ignore-case we can not use split()
// and have to collect indexes of "query" matches in "text"
var indexes:Vector.<int> = new Vector.<int>();
var index:int = 0;
var textLowerCase:String = text.toLocaleLowerCase();
var queryLowerCase:String = query.toLocaleLowerCase();
var queryLength:int = query.length;
while (true)
{
index = textLowerCase.indexOf(queryLowerCase, index);
if (index == -1)
break;
indexes.push(index);
index += queryLength;
}
// now add SpanElement for each part of text. E.g. if we have
// text="aBc" and query is "b" then we add "a" and "c" as simple
// span and "B" as highlighted span.
var backgroundColor:uint = 0xFFCC00;
var n:int = indexes.length;
if (n == 0) // no matches
{
addSpan(result, text);
}
else
{
var startIndex:int = 0;
for (var i:int = 0; i < n; i++)
{
if (startIndex != indexes[i])
addSpan(result, text.substring(startIndex, indexes[i]));
addSpan(result, text.substr(indexes[i], queryLength),
backgroundColor);
startIndex = indexes[i] + queryLength;
}
if (startIndex != text.length)
addSpan(result, text.substr(startIndex));
}
return result;
}
private function addSpan(vector:Vector.<FlowElement>, text:String,
backgroundColor:* = "transparent"):void
{
var span:SpanElement = new SpanElement();
span.text = text;
span.backgroundColor = backgroundColor;
vector.push(span);
}
MXML code:
<s:RichEditableText editable="false" multiline="false"
selectable="false" id="label"
horizontalCenter="0" verticalCenter="0"/>
P.S: If you will have troubles with popup taking focus - add it manually to the toolTipChildren:
systemManager.toolTipChildren.addChildAt(child, 0);