UIWebView: get attributes from hyperlink clicked - html

I have html page loaded via UIWebView. If user selects link that looks like:
<a webview="2" href="#!/accounts-cards/<%= item.acctno %>"></a>
I can get href value clicked in UIWebViewDelegate method from NSURLRequest:
webView:shouldStartLoadWithRequest:navigationType:
But how I can get attribute value from this hyperlink (webview="2") assuming that attribute name "webview" determined?

You can get your attribute "webview", with the help of JavaScript and after that you can send that attribute and its value to native Objective C code.
Add this JavaScript code to your HTML page inside script tag:
function reportBackToObjectiveC(string)
{
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "callback://" + string);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++) {
links[i].addEventListener("click", function() {
var attributeValue=links[i].webview; //this will give you your attribute(webview) value.
reportBackToObjectiveC(attributeValue);
}, true);
}
after this your webViewDelegate method will call:
- (BOOL)webView:(UIWebView *)wView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
{
if (navigationType == UIWebViewNavigationTypeLinkClicked)
{
NSURL *URL = [request URL];
if ([[URL scheme] isEqualToString:#"callback"])
{
//You can get here your attribute's value.
}
}

You need to change href of your links. First inject javascript script, that patches your links.
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *js = #"var allElements = document.getElementsByTagName('a');"
"for (var i = 0; i < allElements.length; i++) {"
" attribute = allElements[i].getAttribute('webview');"
" if (attribute) {"
" allElements[i].href = allElements[i].href + '&' + attribute;"
" }"
"}";
[webView stringByEvaluatingJavaScriptFromString:js];
}
Links will be converted into format (note &2 in href attribute):
<a webview="2" href="#!/accounts-cards/<%= item.acctno %>&2"></a>
Then you can get your callback and parse you webview param value:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSArray *array = [request.URL.absoluteString componentsSeparatedByString:#"&"];
if (array.count > 2) {
NSLog(#"webview value = %#", array[1]);
}
return YES;
}

Related

How to encode odd HTML characters with Xcode?

I need to save a HTML page in my app, and when characters like "€" are found, the saved file displays them wrong.
I tried several encodings but none solves this, is there any solution?
I have also tried to replace the characters for the HTML name, but it still doesn't work.
Here's my code:
NSString *HTML = [web stringByEvaluatingJavaScriptFromString:#"document.getElementsByTagName('html')[0].innerHTML;"];
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [NSString stringWithFormat:#"%#/%#", [path objectAtIndex:0],#"code.html"];
int enc_arr[] = {
NSISOLatin1StringEncoding, // ESP
NSUTF8StringEncoding, // UTF-8
NSShiftJISStringEncoding, // Shift_JIS
NSJapaneseEUCStringEncoding, // EUC-JP
NSISO2022JPStringEncoding, // JIS
NSASCIIStringEncoding // ASCII
};
NSData *urlData= nil;
for (int i=0; i<6; i++) {
urlData = [HTML dataUsingEncoding:enc_arr[i]];
if (urlData!=nil) {
break;
}
}
[urlData writeToFile:filePath atomically:YES];
See these methods of NSString:
- (NSStringEncoding)smallestEncoding
- (NSStringEncoding)fastestEncoding
or just use method below with flag set to YES :
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding allowLossyConversion:(BOOL)flag
but with this one you can loose some characters.
Ok I finally did it, it's not the best way but the only one that worked for me and without using external libraries:
-(NSString*)escapeHTML:(NSString*)code{
NSMutableArray *maExceptions = [[NSMutableArray alloc] initWithObjects: #"Œ", #"œ", #"Š", #"š", #"Ÿ", #"ƒ", #"‘", #"’", #"‚", #"“", #"”", #"„", #"†", #"‡", #"•", #"…", #"‰", #"€", #"™", nil];
for (int i=0; i<[maExceptions count]; i++) {
code = [code stringByReplacingOccurrencesOfString:[maExceptions objectAtIndex:i] withString:[NSString stringWithFormat:#"&#x%x;",[[maExceptions objectAtIndex:i] characterAtIndex:0]]];
}
return code;
}

audio tag cannot be parsed in html5 page

I link this JS page to an XML all element is views but the audio tag in xml file is not views in the html5 page ..any suggestion how to make this function retrieve the audio file and show it as html5 audi player.
init: function () {
//jQuery ajax call to retrieve the XML file
$.ajax({
type: "GET",
url: XMLLIST.xml,
dataType: "xml",
success: XMLLIST.parseXML
});
}, // end: init()
parseXML: function (xml) {
//Grab every single ITEM tags in the XML file
var data = $('item', xml).get();
//Allow user to toggle display randomly or vice versa
var list = (XMLLIST.random) ? XMLLIST.randomize(data) : data;
var i = 1;
//Loop through all the ITEMs
$(list).each(function () {
//Parse data and embed it with HTML
XMLLIST.insertHTML($(this));
//If it reached user predefined total of display item, stop the loop, job done.
if (i == XMLLIST.display) return false;
i++;
});
}, // end: parseXML()
insertHTML: function (item) {
//retrieve each of the data field from ITEM
var url = item.find('url').text();
var image = item.find('image').text();
var audio=item.find('audio').text();
var title = item.find('title').text();
var desc = item.find('desc').text();
var html;
//Embed them into HTML code
html = '<div class="item">';
html += '<a href="' + url + '"><image"' + image + '" alt="' + title + '" />';
html += '<span>' + title + '</span></a>';
html += '<audio control="control"><span> ' +audio+' </span></audio>';
html += '<p>' + desc + '</p>';
html += '</div>';
//Append it to user predefined element
$(html).appendTo(XMLLIST.appendTo);
}, // end: insertHTML()
randomize: function(arr) {
//randomize the data
//Credit to JSFromHell http://jsfromhell.com/array/shuffle
for(var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x);
return arr;
} // end: randomize()
}
AFAIK .each() is used to iterate over a jQuery object, if you want to iterate over an array use $.each()
Here you have
$(list).each(function () {
which should be
$.each(list, function () {
since list is an array of dom nodes and not a jQuery object

How to add url parameter to the current url?

Currently I'm at
http://example.com/topic.php?id=14
and I want to make a link to
http://example.com/topic.php?id=14&like=like
by not defining the current url. Like Like. However this last one shows me http://example.com/&like=like
There is no way to write a relative URI that preserves the existing query string while adding additional parameters to it.
You have to:
topic.php?id=14&like=like
function currentUrl() {
$protocol = strpos(strtolower($_SERVER['SERVER_PROTOCOL']),'https') === FALSE ? 'http' : 'https';
$host = $_SERVER['HTTP_HOST'];
$script = $_SERVER['SCRIPT_NAME'];
$params = $_SERVER['QUERY_STRING'];
return $protocol . '://' . $host . $script . '?' . $params;
}
Then add your value with something like;
echo currentUrl().'&value=myVal';
I know I'm late to the game, but you can just do ?id=14&like=like by using http build query as follows:
http_build_query(array_merge($_GET, array("like"=>"like")))
Whatever GET parameters you had will still be there and if like was a parameter before it will be overwritten, otherwise it will be included at the end.
In case you want to add the URL parameter in JavaScript, see this answer. As suggested there, you can use the URLSeachParams API in modern browsers as follows:
<script>
function addUrlParameter(name, value) {
var searchParams = new URLSearchParams(window.location.search)
searchParams.set(name, value)
window.location.search = searchParams.toString()
}
</script>
<body>
...
<a onclick="addUrlParameter('like', 'like')">Like this page</a>
...
</body>
If you wish to use "like" as a parameter your link needs to be:
Like
More likely though is that you want:
Like
It is not elegant but possible to do it as one-liner <a> element
<a href onclick="event.preventDefault(); location+='&like=like'">Like</a>
Maybe you can write a function as follows:
var addParams = function(key, val, url) {
var arr = url.split('?');
if(arr.length == 1) {
return url + '?' + key + '=' + val;
}
else if(arr.length == 2) {
var params = arr[1].split('&');
var p = {};
var a = [];
var strarr = [];
$.each(params, function(index, element) {
a = element.split('=');
p[a[0]] = a[1];
})
p[key] = val;
for(var o in p) {
strarr.push(o + '=' + p[o]);
}
var str = strarr.join('&');
return(arr[0] + '?' + str);
}
}

Removing parts from HTML page in UIWebVIew

I'm trying to remove text from html page, and I'm using this code:
NSRange *r;
while ((r = [commentsOnly rangeOfString:#"<[^>]+>" options:NSRegularExpressionSearch]).location != NSNotFound) {
commentsOnly = [commentsOnly stringByReplacingCharactersInRange:r withString:#""];
NSLog(#"clearing");
}
It removes html tags perfect, but how can I remove only one tag? For example, title or p. I don't want to remove only my tag. I want to remove start tag (<p>), info between two tags and close tag (<\p>).
If I understand your question, may be this will help you:
NSString *string = #"</body>", *htmlString = #"ddsfsdf_<body>_sdfsfd_<body>ffff</body></body>";
NSRange range = [htmlString rangeOfString:string];
if (range.location != NSNotFound)
{
range.length += range.location;
range.location = 0;
string = #"<body>";
NSRange rangeOpen = [htmlString rangeOfString:string options:NSBackwardsSearch range:range];
if (rangeOpen.location != NSNotFound)
{
range.length -= rangeOpen.location;
range.location = rangeOpen.location;
htmlString = [htmlString stringByReplacingCharactersInRange:range withString:#""];
NSLog(#"%#", htmlString);
}
}
Use stringByEvaluatingJavaScriptFromString: to execute JavaScript within the UIWebView to do this. This is much less work and is also much more reliable, as it will use WebKit's HTML parser instead of naïve string replacement.

How to serialize HTML DOM to XML in IE 8?

Is there a way to do it(serialization of HTML DOM into XML) in IE 8 or any other older version of IE.
In firefox :
var xmlString = new XMLSerializer().serializeToString( doc );
does it.I haven't tried it, though.
XMLSerializer causes error in IE 8, that it is not defined.
var objSerializeDOM = {
//Variable to hold generated XML.
msg : "",
serializeDOM : function() {
dv = document.createElement('div'); // create dynamically div tag
dv.setAttribute('id', "lyr1"); // give id to it
dv.className = "top"; // set the style classname
// set the inner styling of the div tag
dv.style.position = "absolute";
// set the html content inside the div tag
dv.innerHTML = "<input type='button' value='Serialize' onClick='objSerializeDOM.createXML()'/>"
"<br>";
// finally add the div id to ur form
document.body.insertBefore(dv, document.body.firstChild);
},
/**
* XML creation takes place here.
*/
createXML : function() {
objSerializeDOM.msg += "";
objSerializeDOM.msg += "<?xml version='1.0' encoding='UTF-8'?>\n\n";
// Get all the forms in a document.
var forms = document.forms;
for ( var i = 0; i < forms.length; i++) {
// Get all the elements on per form basis.
elements = document.forms[i].elements;
objSerializeDOM.msg += "<FORM name=\"" + forms[i].name + "\" method=\""
+ forms[i].method + "\" action=\"" + forms[i].action + "\">\n\n";
for ( var j = 0; j < elements.length; j++) {
objSerializeDOM.msg += " <" + elements[j].tagName + " type=\""
+ elements[j].type + "\"" + " name=\""
+ elements[j].name + "\"" + " Value =\""
+ elements[j].value + "\" />\n";
}
alert(document.forms[i].elements[1].event);
}
objSerializeDOM.msg += "\n\n</FORM>\n\n";
alert(objSerializeDOM.msg);
objSerializeDOM.writeToFile(objSerializeDOM.msg);
},
/**
* Writes the msg to file at pre-specified location.
* #param msg
* the XML file created.
*/
writeToFile : function(msg) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fh = fso.CreateTextFile("c:\\myXML.xml", true);
fh.WriteLine(msg);
fh.Close();
}
};
objSerializeDOM.serializeDOM();
I wrote this JS, I run this javascript using GreaseMonkey4IE. This simply puts a button on every page of the domain you specify in GM4IE. On click of that button it will parse the HTML document and create an XML file. It will also display the same as an alert first and will save the XML in your local drive on path specified.
There a still many improvements I am planning to do, but yes it works and may be give you guys an idea.The program is self-explanatory, I hope.
please have a look here How to get Events associated with DOM elements?Thanks