Accessing DOM object properties from Chrome's content script - google-chrome

I ran into a strange problem with a content script. The content script is defined as "run_at" : "document_end" in the manifest. After a page is loaded the script inserts an object tag into the page (if the tag with predefined id does not exist yet), and sets some properties in it, such as type, width, height, innerHTML, and title. All works fine here.
function checkForObject()
{
var obj = document.getElementById("unique_id");
if(obj == null)
{
var d = document.createElement("object");
d.id = "unique_id";
d.width = "1";
d.height = "1";
d.type = "application/x-y-z";
d.title = "1000";
d.style.position = "absolute";
d.style.left = "0px";
d.style.top = "0px";
d.style.zIndex = "1";
document.getElementsByTagName("body")[0].appendChild(d);
}
}
checkForObject();
I see the new object in the page html-code with proper values in its properties.
Some time later I need to read the title property of the object in the same content script. The code is simple:
function ReadTitle()
{
var obj = document.getElementById("unique_id");
var value = obj.title; // breakpoint
console.log(value);
// TODO: want to use proper title value here
}
The function is called from background.html page:
chrome.tabs.onActivated.addListener(
function(info)
{
chrome.tabs.executeScript(info.tabId, {code: 'setTimeout(ReadTitle, 250);'});
});
Unfortunately, in ReadTitle I'm getting not what I expect. Instead of current value of the title I see the logged value is:
function title() { [native code] }
If I set a breakpoint at the line marked by // breakpoint comment, I see in the watcher that all object properties including the title are correct. Nevertheless, the variable value gets the abovementioned descriptive string.
Apparently, I have missed something simple, but I can't figure it out.
The answer. It was a bug in the npapi plugin, which hosts the object of used type. My apologies for all who have read the question with intention to help.

The NPAPI plugin used in the object erroneously reported title as supported method.

Related

LexResponse output does not understand HTML data

I'm having a problem trying to get my AWS Lambda function to successfully output a series of HTML links when its running a SQL Query.
private string GetEventSearchResults(ILambdaContext context, List<Event> events, string CustomerNumber)
{
var result = string.Empty;
var link = string.Empty;
if (events.Count > 0)
{
result = $"Events for {CustomerNumber}:";
foreach (var evt in events)
{
link = "http://localhost/event/" + $"{evt.ID}";
result += $"<br>Event: {evt.ID} - Status: {evt.Status}";
}
}
else
{
result = "No Data found matching your query";
}
return result;
}
When this method is called by my Lambda function as a LexResponse,
replyMessage = GetEventSearchResults(context, eventList, query.CustomerNumber);
return Close(
sessionAttributes,
"Fulfilled",
new LexResponse.LexMessage
{
ContentType = "PlainText",
Content = replyMessage
}
);
This response is then rendered in my HTML page by a Javascript function. Relevant portion of the Javascript that renders the response:
function showResponse(lexResponse) {
var conversationDiv = document.getElementById('conversation');
var responsePara = document.createElement("P");
responsePara.className = 'lexResponse';
if (lexResponse.message) {
responsePara.appendChild(document.createTextNode(lexResponse.message));
responsePara.appendChild(document.createElement('br'));
}
if (lexResponse.dialogState === 'ReadyForFulfillment') {
responsePara.appendChild(document.createTextNode(
'Ready for fulfillment'));
// TODO: show slot values
}
conversationDiv.appendChild(responsePara);
conversationDiv.scrollTop = conversationDiv.scrollHeight;
}
However, the output shown by the Lex bot is as shown below:
Lex Bot Output
Can anyone please help me understand what exactly is going on? Is the content type of the Lex Response responsible for this? (there's only plaintext and SSML available for Lex Response so I can't change that)
Also, if possible, can anyone please explain how to fix this if at all possible? Thanks!
Your code is correct and output is also correct.
However the console window is not able to render the HTML part of your result.
The client on which you will deploy the chatbot, is responsible for rendering the output. For example, if you respond with a ResponseCard, console or website will not be able to render it correctly but it will be displayed correctly on Facebook and Slack. So, if you integrate your chatbot on some website it will show the links in your output correctly as you desired.
You can try to integrate your chatbot with Slack or Facebook first, to see the rendering of output.
Hope it helps.
After further trial and error, I managed to get a solution that works for me.
function showResponse(lexResponse) {
var conversationDiv = document.getElementById('conversation');
var responsePara = document.createElement("P");
responsePara.className = 'lexResponse';
if (lexResponse.message) {
var message = lexResponse.message.replace(/"/g, '\'');
responsePara.innerHTML = message;
responsePara.appendChild(document.createElement('br'));
}
conversationDiv.appendChild(responsePara);
conversationDiv.scrollTop = conversationDiv.scrollHeight;
}
By making the LexResponse an Inner HTML, it fixed the markup of the text and thus the link can be seen everytime.

Error with custom Search and Replace function for Google Sites

I'm trying to use a script to replace a particular string with a different string. I think the code is right, but I keep getting the error "Object does not allow properties to be added or changed."
Does anyone know what could be going wrong?
function searchAndReplace() {
var teams = SitesApp.getPageByUrl("https://sites.google.com/a/directory/teams");
var list = teams.getChildren();
list.forEach(function(element){
page = element.getChildren();
});
page.forEach(function(element) {
var html = element.getHtmlContent();
html.replace(/foo/, 'bar');
element.setHtmlContent = html;
});
};
Try This:
Javascript reference:
The replace() method returns a new string with some or all matches of a pattern replaced by a replacement.
I think the issue here is that forEach cannot change the array that it is called upon. From developer.mozilla.org "forEach() does not mutate the array on which it is called (although callback, if invoked, may do so)."
Try doing it with a regular loop.

CodeMirror textarea.getAttribute is not a function error in mvc3 application

I'm using CodeMirror in my ASP.NET MVC 3 application,
CodeMirror's version is up to date(2.34)
my textarea looks like this:
#Html.TextAreaFieldFor(s => s.Data.CodeBehind, htmlAttributes: new Dictionary<string, object> { { "class", "textbox codeBehind nffp-code" } })
I use CodeMirror like this:
var a = CodeMirror.fromTextArea($code, {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-csharp"
});
where $code is
var $code = jQuery('.nffp-code', $root);
And after page load I have this error:
TypeError: textarea.getAttribute is not a function
codemirror.js
Line 2209
textarea.getAttribute("autofocus") != null && hasFocus == document.body;
I used this manual for using CodeMirror:
manual
Even thought, I'm a total noob in JS, I guess it's hard to do it wrong, still I did.
Any Ideas how to fix the problem?
You need to use document.getElementById() instead of the jQuery lookup.
document.getElementById('contents'); //returns a HTML DOM Object
var contents = $('#contents'); //returns a jQuery Object
In jQuery, to get the same result as document.getElementById(), you can access the jQuery Object and get the first element in the object (Remember JavaScript objects act similar to associative arrays).
var contents = $('#contents')[0]; //returns a HTML DOM Object

JSON results into a variable and store in hidden input field

I wrote code below that is working perfectly for displaying the results of my sales tax calculation into a span tag. But, I am not understanding how to change the "total" value into a variable that I can work with.
<script type="text/javascript">
function doStateTax(){
var grandtotalX = $('#GRANDtotalprice').val();
var statetaxX = $('#ddl').val();
$.post('statetax.php',
{statetaxX:statetaxX, grandtotalX:grandtotalX},
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
// ...
});
return false;
};
</script>
Currently, $('.total-placeholder').html(data.total); is successfully placing the total number into here:
<span class="total-placeholder"></span>
but how would I make the (data.total) part become a variable? With help figuring this out, I can pass that variable into a hidden input field as a "value" and successfully give a proper total to Authorize.net
I tried this and id didn't work (see the testtotal part to see what I'm trying to accomplish)..
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
$testtotal = (data.total);
// ...
If you are using a hidden field inside a form, you could do:
//inside $.post -> success handler.
$('.total-placeholder').html(data.total);
$('input[name=yourHiddenFieldName]', yourForm).val(data.total);
This will now be submitted along with the usual submit. Or if you want to access the data elsewhere:
var dataValue = $('input[name=yourHiddenFieldName]', yourForm).val();
The "data" object you are calling can be used anywhere within the scope after you have a success call. Like this:
$.post('statetax.php',
{statetaxX:statetaxX, grandtotalX:grandtotalX},
function(data) {
data = $.parseJSON(data);
var total = data.total;
var tax = data.total * 0.19;
});
return false;
};
Whenever you get an object back always try to see with an alert() or console.log() what it is.
alert(data); // This would return <object> or <undefined> or <a_value> etc.
After that try to delve deeper (when not "undefined").
alert(data.total); // <a_value>?
If you want 'testotal' to be recognized outside the function scope, you need to define it outside the function, and then you can use it somewhere else:
var $testtotal;
function(data) {
data = $.parseJSON(data);
$('.products-placeholder').html(data.products);
$('.statetax-placeholder').html(data.statetax);
$('.total-placeholder').html(data.total);
$testtotal = (data.total);
EDIT:
The comments are becoming too long so i'll try and explain here:
variables defined in javascript cannot be accessed by PHP and vice versa, the only way PHP would know about your javascript variable is if you pass it that variable in an HTTP request (regular or ajax).
So if you want to pass the $testtotal variable to php you need to make an ajax request(or plain old HTTP request) and send the variable to the php script and then use $_GET/$_POST to retrieve it.
Hope that answers your question, if not then please edit your question so it'll be clearer.

Extract the contents of a div using Flash AS3

I have a SFW embedded in a PHP page. There is also a div on the page with id="target".
I want to access the content of that div (ie: the characters inside it) and hold them as a String variable in AS3. How can I do this?
My attempt so far
import flash.external.ExternalInterface;
var myDivContent = ExternalInterface.call("function(){ return document.GetElementById('target');}");
var myDivContent2:String = myDivContent.toString();
test_vars.text = myDivContent2; //Dynamic text output
I don't think you can define a function in the ExternalInterface.call() method. You have to call a function by name which already exists in the JavaScript.
So I'd create some JavaScript code like this:
function getTargetContent()
{
return document.getElementById('target').innerHTML;
}
And then in your Flash,
var myDivContent = ExternalInterface.call("getTargetContent");
Note that document.getElementById('target') only returns the reference to that div, not the contents within. So if you don't return .innerHTML then the Flash will get an object which may not be usable (although I haven't actually tried doing this).
The easiest way to do this is as Allan describes, write a Javascript function to sit on the page and return the required value to you.
Of course, if you can't edit the page content, only the flash, then you do need to pass the function itself, which will actually have to be forced into the page though JavaScript injection. An example for your case, which I have not tested:
//prepare the JavaSctipt as an XML object for Dom insertion
var injectCode:XML =
<script>
<![CDATA[
function() {
getElementContent = function(elementID) {
return document.getElementById(elementID).innerHTML;
}
}
]]>
</script>;
//inject code
ExternalInterface.call(injectCode);
//get contents of 'divA'
var divAContent:String = ExternalInterface.call('getElementContent','divA') as String;
//get contents of 'spanB'
var spanBContent:String = ExternalInterface.call('getElementContent','spanB') as String;
You're almost there :
var res : String = ExternalInterface.call("function(){return document.getElementById('target').outerHTML}");
If you only want the content of your target, use innerHTML instead of outerHTML.