bookmarklet: cannot find element added to the document - javascript

I am playing with bookmarklets. I add a frame to the document, and load some elements, like so:
var myframe=document.createElement("iframe");
myframe.setAttribute('id','a_frame');
myframe.src='http://localhost:81/nframe.html';
document.body.insertBefore(myframe,document.body.firstChild);
this is what nframe.html looks like:
<form id="sr_cart" name="sr_cart" action="localhost:81/dosomething.php">
Item Number: <input type="text" name="ItemNum" id="sr_item" value="" />
<input type="submit" value="Submit" />
</form>
Looks great so far: when I click on my bookmarklet, the document has been modified correctly
Then I try to look up the item number (or the form)
cart = document.getElementById('sr_cart');
I'm perplexed as to why this comes back a null. (looking up sr_item does the same thing. looking up something that is not in my frame works fine)
TIA

You're searching the wrong document. Start from the iframe's document, like so:
var docEl = myframe.contentDocument || myframe.contentWindow.document || myframe.document;
if (docEl) {
var cart = docEl.getElementById('sr_cart'); // this is what you need
}
I'm pretty sure this is what you need to do - I've done it before but I found verification in Closure Tools' code (Google's JS Library) - http://code.google.com/p/doctype/wiki/ArticleFrameContentDocument

Related

How can I get an HTML tag’s value to send an HTML.Action()

I have these lines of code:
<span
class="close-modal"
onclick="#Html.Action("SaveNotes", "CallCenter", new { activityId = item.callIdKey, noteText = "test1" })">
×
</span>
Notes: <br />
<textarea name="paragraph_text" rows="5" style="width:90%">
#item.NoteText
</textarea>
I would like to replace test1 from the noteText route variable and instead change it to whatever the value in the <textarea> tag is.
Is there an elegant way of doing this without writing a giant block of jQuery code?
#Html.Action() renders a partial view as an HTML string during page processing (on the server side). It doesn't exist any more in the markup, once the page is sent to the browser. You can't do what you are trying to do this way. At the very least, I'm sure you don't want to render a partial view inside the onclick event of your <span> tag.
Why not instead use an HTML helper for the <textarea> tag? Then you can get whatever value the user typed into it on the server code. You'll want to make the form post itself back to the server on the close-modal element:
<span class="close-modal" onclick="$('form').submit()">×</span>
<form method="post" action="#Url.Action("SaveNotes", "CallCenter", new { activityId=item.callIdKey }">
Notes: <br />
#Html.TextArea("noteText", item.NoteText, new { rows="5", style="width:90%" })
</form>
This assumes you have jQuery already (a common assumption with ASP.NET). You may not need the <form> tags if you already have a form on your page.
A #gunr2171 notes in the comments, the only way to dynamically update a link once it's been rendered to the browser is via some form of client-side scripting, typically JavaScript. In your case, I'd recommend doing something like this:
<span
class="close-modal"
data-href-template="#Url.Action("SaveNotes", "CallCenter", new {activityId = item.callIdKey, noteText="{note}"})"
>
×
</span>
Note: As #HBlackorby notes in his answer, you shouldn't be using #Html.Action() here; I assume you meant #Url.Action().
This way, your JavaScript has a template (data-href-template) that it can work against with a clearly defined token ({note}) to replace, instead of needing to parse the URL in order to identify where the previously replaced text is. Otherwise, you potentially end up in a scenario where you type e.g. CallCenter into your <textarea /> and it's now an ambiguous reference that you can't just blindly replace. Or, worse, you type 'a' and it's really ambiguous.
If you are already using jQuery on your site, the actual replacement might be done using something along the lines of:
$(document).ready(function () {
$('span.close-modal').click(function() {
var noteInput = $('textarea[name="paragraph_text"]');
var encodedNote = encodeURI(noteInput.text());
var template = $(this).data("href-template");
var targetUrl = template.replace("{note}", encodedNote);
window.location.href = targetUrl;
});
});
You can also do this without jQuery, obviously—and should if you're not already depending on it. The point is to illustrate that this doesn't necessarily need to be a "giant block of jQuery code". In fact, this could be done in just a few lines—and probably should be. I deliberately broke it out into multiple steps and variables for the sake of readability.

Jquery returns old value for an element on refresh

There is an html as follows:
<input id="currency_factor" type="text" style="display:none;" value="20"/>
And there is a jquery function:
$(document).ready(function(){
var currency_factor = $('#currency_factor').val()
alert(currency_factor);
}
Upon refresh the html line shows on the browser as:
<input id="currency_factor" type="text" style="display:none;" value="0"/>
But jquery returns 20.
Why is this happening?
Try adding this to the header of your html file to disable caching:
<meta http-equiv="Cache-Control" content="no-store" />
There are actually a number of cache control tags that may or may not be needed, depending on the browsers being used. Here's another posting on StackOverflow that lists some of them: Using <meta> tags to turn off caching in all browsers?
Try by first initializing it and then setting it
$(document).ready(function(){
var currency_factor = 0;
currency_factor = $('#currency_factor').val()
alert(currency_factor);
}
Do you perhaps have more than one element with an id of currency_factor. The first one's value will probably be returned.
Another possibility is that the value is changed after the $(document).ready() function has executed. Try running $('#currency_factor').val() in the browser console after load. If it returns 0 then it was changed after the page load.

Missing DOM element

I am using Chrome 30.0.1599.101 and have issue with name element: it has no properties.
<html>
<body>
<form>
<input name="name" id="name" type="text">*<br>
<input name="pass" id="pass" type="text">*<br>
</form>
<script>
var name = document.getElementById("name");
var pass = document.getElementById("pass");
console.log(name); // no properties
console.log(pass); // everything ok
</script>
</body>
</html>
Why has name element has no properties? It's not only the console issue - the properties are not accessible in the code. However, everything works fine in Firefox browser. Even in the fiddle (by Gurpreet Singh) with the very same code in the same browser everything works. I tried <!DOCTYPE html5> as Uooo suggests, tried to reset the browser, but still no luck on localhost.
Here is a screenshot:
If I change the name name to something else, the properties are visible.
name is already a global property (a property of window), and not only that, it is kinda typed (String).
var name = ... is essentially the same as as saying window.name = .... Use another variable name that is actually not taken yet and you should be fine.
Missing <head> and <title>, maybe that helps, it's invalid HTML without them.
jsfiddle does automatically insert those tags, which could explain why it works there but not locally.
Don't get confused by Green arrow answer,
you don't close an input tag, but not the br and vice versa. All single-tags in XHTML need to be closed to be valid, but in HTML4 and HTML5 you don't close any single-tag at all.
I would suggest following changed version which works as intended for me in
navigator.userAgent
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1678.0 Safari/537.36"
Code
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script>
document.addEventListener('readystatechange', function(event) {
if (event.target.readyState !== "complete") {
return;
}
var name = document.getElementById("name");
var pass = document.getElementById("pass");
console.log(name);
console.log(pass);
}, false);
</script>
</head><body>
<form>
<input name="name" id="name" type="text">*<br>
<input name="pass" id="pass" type="text">*<br>
</form>
</body></html>
Explanation
script elements should be in the head element of a HTML document.
script code dealing with the DOM needs to run after the document is fully loaded.
Implicitly Fixed Issues
script code should not run in global scope where var name and pass may clash with existing variables. It now runs in the scope of the anonymous event listener function.
Remaining Problems
Use type="password" for password fields.
Use the value attribute to default input type values.
Better use div elements to layout input elements vertically instead of br elements.
I don't know if that cause the error but you should at least close your input
<html>
<body>
<form>
<input name="name" id="name" type="text"/>*<br>
<input name="pass" id="pass" type="text"/>*<br>
</form>
</body>
</html>
The fiddle works for me too...
Do you have any warnings &/or errors in your chrome console ?
You should also used your script in that function :
<script>
$(function() { //shortcut for document ready
//Get your elements here otherwise you can't be sure that dom is loaded.
});
</script>
if you don't use jquery then it's quite a mission to detect when dom is loaded if you want a Xbrowser solution, a lot of topic are talking about that.

Google Apps Script, UrlFetchApp and JQuery

I would like to load a web page every day (perhaps more times a day), parse its data and email results.
To parse the web page I am using a parse.gs script like the following:
var url="http://http://example.com";
var page = UrlFetchApp.fetch(url).getContentText();
var XmlDoc = Xml.parse(page, true);
When I parse XmlDoc I have only getElement/s functions available and I find it difficult to do an effective job. So I would like to use something more productive, like the JQuery selectors.
As far as I understood I have to add a jquery.html page to the project like:
<html>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
</html>
Then add to parse.gs the function:
function doGet() {
return HtmlService.createHtmlOutputFromFile('jquery');
}
After calling doGet, how do I parse XmlDoc? Using lines like $('#content').html(XmlDoc); doesn't work.
As an alternative to jquery, try building on the capabilities of the Xml Service entirely in apps-script.
A previous answer introduced a utility function that locates elements in the XML Document by searching for properties matching the search criteria.
getElementByVal( body, 'input', 'value', 'Go' )
... will find
<input type="submit" name="btn" value="Go" id="btn" class="submit buttonGradient" />
It also showed one possible specialization, for searching 'id' attributes of <div>s:
getDivById( html, 'tagVal' )
... will find <div id="tagVal">
If you are able to identify an element uniquely, as in the above examples, a simple script can get you that element easily:
var url="http://http://example.com";
var page = UrlFetchApp.fetch(url).getContentText();
// Get <div id="content">
var contentDiv = getDivById( pageDoc.getElement().body, 'content' );
...

Changing Img Src based on value entered in a Textfield

I need help creating a form with the following
TEXTFIELD(will be used to enter 7digit model numbers)
An image placeholder (will change the image placeholder's src based on a url for example it will become src="http://yourwebsite.com/product/TEXTFIELD.jpg)
I need to somehow get the the H1 tag values from within the product's url
#3 IS STILL UNSOLVED !
I'm REALLY desperate for any type of help.
I've googled the entire day REALLY need assistance.
Thank You !
I have some code below that helps visualize what I'm kinda looking for.
Please contact me if you need clarification or if I'm a bit confusing.
<form name="form1" method="post" action="">
<p>7-digit product#
<input type="text" name="model" id="model">
</p>
<p>
<input name="start" type="hidden" id="start" value="http://www.mywebsite.com/Products/">
</p>
<p>
<input name="end" type="hidden" id="end" value=".jpg">
</p>
<p><img name="proudctimage" src="=#start#model#end" width="32" height="32" alt=""></p>
</form>
<script>
var model_input = document.getElementById('model');
var start = document.getElementById('start');
var end = document.getElementById('end');
var image = document.getElementsByTagName('img');
model_input.onkeyup = function(e){
image[0].src = start.value + model_input.value + end.value;
}
</script>
~EDITED 9:00AM 5/29/12~
The Values entered in the textfield gets deleted if you hit enter
I need a way to grab a product's description stored in a H1 tag using the respective URL (The URL is the model number of what is entered in the textfield but uses a slightly different url structure that is different than the one used to grab images , see below ... http://mywebsite.com/ProductDetails.aspx?productid=TEXTFIELD)
***I Should make note that the URL used to get the H1 data will be a "cross domain" & not necessarily on the some domain. I read that jquery may not make requests on cross domains
You could use Jquery to do this easily.
Grab a copy of Jquery from http://www.jquery.com or use the CDN version by pasting this into your head section:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
Here's a simplified version:
If the start and end parts of your URL are not going to change you could simplify your form:
​<form>
<label>Model Num</label>
<input type="text" name="model" id="model" />
<input type="button" value="Update Image" id="update" />
</form>
<img src="" />
​
Then With the following Jquery code, you can detect a click on the update button, grab the code from the text box and change the image src attribute to
http://mysite.com/products/typed_code_here
Just paste the jquery code (and the script tags) into your head section
<script>
​$(document).on('click','#update',function(){
$('img').attr('src','http://mysite.com/product/'+$('#model').val()+'.jpg');
});​​​​​​
</script>
If you want to do this without Jquery and if your html has to remain as above, you could use the following along with your original html (watch out for spelling mistakes in your code):
<script>
var model_input = document.getElementById('model');
var start = document.getElementById('start');
var end = document.getElementById('end');
var image = document.getElementsByTagName('img');
model_input.onkeyup = function(e){
image[0].src = start.value + model_input.value + end.value;
}
</script>
The onkeyup event could be changed to blur, change etc depending on how you want to update the image. I'd suggest a button such that the user can update the image when they believe the code is valid.
Update​
The following github project has made progress on the front of cross domain html requests with jQuery. https://github.com/padolsey/jQuery-Plugins/tree/master/cross-domain-ajax/
Basically you'd just need to grab the product page via ajax (jQuery.ajax()) and then in the ajax callback you'd have to scan the returned HTML for the h1 element. Ultimately cross domain ajax is a design pattern and there are best practices associated with it. Grabbing the whole HTML page for the sake of an h1 element is not very effective. Consider revising your approach and be sure to check any copyright laws/terms and conditions if the site you're referencing is not your own.
If your using jquery, you could do this:
$(function () {
$('#model').change(function () {
$('img[name="productimage"]').attr('src', $('#start').val() + $('#model').val() + $('#end').val());
});
});
In your html take a hidden div. suppose
<div id="loadSource"></div>
$('#model').blur(function () {
var modelVal = $.trim(this.value),
startVal = $.trim($('#start').val()),
endVal = $.trim($('#end').val());
if( modelVal && startVal && endVal) {
var imgUrl = startVal + modelVal + endVal,
siteUrl = startVal + modelVal;
$('img[name="productimage"]')
.attr('src', );
// process to get h1 tag
$('#loadSource').load(''+ siteUrl +' h1', function() {
console.log( $('#loadSource h1').text() );
});
}
});

Categories