I'm trying to learn JavaScript by writing a Google Chrome extension for Reddit so I wrote something to display both link and comment karma in the little tab up top.
a = document.getElementById("header-bottom-right");
a.firstChild.firstChild.nextElementSibling.innerText = "100000"
Obviously it is not the full thing (just finding the correct nodes to edit), but is their a better way to grab the karma text?
Reddit uses jQuery library (an ancient version, but still). So instead of using plain js you could use: $('#header-bottom-right child_tag').html('10000') (you can also use custom html there)
With plain js could be something like this:
var hbr = document.getElementById('header-bottom-right');
var links = hbr.getElementsByTagName('a'); // replace this with what tag you want to change
links[0].innerHTML = 'your cool text';
May not be the best way, but you may be able to use innerHTML instead.
document.getElementById('header-bottom-right').firstChild.firstChild.nextElementSibling.innerHTML
Related
I'm trying to use JavaScript to include a footer on several webpages, so if I want to change the footer, I only have to change it in one place. PHP is not available on this server and neither are server side inserts (SSI), but Perl, Python, and Tcl are available. I have been trying with document.getElementsByTagName('footer').innerHTML = "text"; but it doesn't produce text. I copied this code from dev.mozilla, and it tells me how many tags I have:
var footer = document.getElementsByTagName('footer');
var num = footer.length;
console.log('There is ' + num + ' footer in this document');
So, I don't know what's wrong with the innerHTML script. I also tried with paragraph tags and got the same results in both cases.
I reccoment using textContent instead. Se why here.
To see how it works, paste the following into your browser console while you're on StackOverflow and hit enter.
document.querySelector('.site-footer').textContent = 'Custom footer content.'
note: use querySelector with a class instead of getElementByTagName
Cheers! 🍻
Before asking this question, I had searched for Python includes without any luck, so I stopped there, but after asking this question, I thought that I should search for Perl/Ruby includes. Today, I found out that I can use the Perl use function, so I could study that and try to implement it although I am completely new to Perl. Ruby also appears capable, perhaps even more. I have no experience with Ruby either, but maybe I should start there.
I just figured out that getElementsByTagName() results in an array, so I have to refer to the footer's index with [0]:
var footerTags = document.getElementsByTagName('footer');
footerTags[0].innerHTML = "test";
I'm writing my first firefox add-on.
It was completed, but mozilla rejected it with this answer:
1) Your add-on creates DOM nodes from HTML strings containing potentially unsanitized data, by assigning to innerHTML or through similar means. Aside from being inefficient, this is a major security risk. For more information, see https://developer.mozilla.org/en/XUL_School/DOM_Building_and_HTML_Insertion. Here are some examples where you do this: (cut...)
I wrote:
var myDiv = content.document.getElementById("myContent");
myDiv.innerHTML = "some html code";
now I'm not a JS programmer and I don't understand how to go on.
I tested some code like this:
var NewNode = content.document.createElement("span");
NewNode.appendChild(content.document.createTextNode("Hello World!"));
//content.document.body.appendChild(NewNode);//ok, works
content.document.getElementById("myContent").appendChild(NewNode);//doesn't work
but it doesn't work until I append it to .body
Samples working on other pages seems not working here. Moreover I don't understand if it fixes the problem that mozilla indicated.
Could you please help me with the code that should replace the two lines I wrote?
If you need the full code, here it is: http://www.maipiusenza.com/LDV/down/ldvgenerator.xpi
Thanks!
Nadia
Just did a quick js fiddle, I was wondering why you have used content.document so I amended it to document and it worked.
http://jsfiddle.net/eDW82/
var NewNode = document.createElement("span");
NewNode.appendChild(document.createTextNode("Hello World"));
document.getElementById("myContent").appendChild(NewNode);
I had a similar problem with unsanitized HTML and as I used it extensively I opted to use jQuery which will pass mozillas rules. It makes life a lot easier to be able to create your nodes that way.
$("<div>", {id:"example"}).text("Hello World")
It just reads so much nicer.
OK then, I did some digging and I think I managed to find your problem:
Whenever you want to inject any kind of html to your extension, The browser considers it as a security hole, that's why you have this problem. you have 2 different solution;
first: you can create an iframe and use it to show your html (in javascript whenever we want to show a file we have 2 option, first pass a file path on the server, or use data: to show your data directly):
var htmlStr = "<span>Hello World!</span>";
var frm = content.document.createElement("iframe");
content.document.getElementById("myContent").appendChild(frm);
frm.src = "data:text/html;charset=utf-8," + encodeURIComponent(htmlStr);
second: this solution would help you out, if you don't want to use an iframe to show your html.
var htmlStr = "<span>Hello World!</span>";
var frm = document.createElement("iframe");
frm.style.display="none";
document.body.appendChild(frm);
var win = frm.contentWindow;
var frmrange = win.document.createRange();
// make the parent of the first div in the document becomes the context node
frmrange.selectNode(win.document.firstChild);
var frg = frmrange.createContextualFragment(htmlStr);
content.document.getElementById("myContent").appendChild(frg);
Old Guess: the problem in your code is different document objects, try this:
var NewNode = content.document.createElement("span");
NewNode.appendChild(content.document.createTextNode("Hello World!"));
content.document.getElementById("myContent").appendChild(NewNode);
this was my first clue to point out.
I'm trying to use the jQuery SVG plugin to animate some stuff — scaling and whatnot. I'm totally new to SVG.
var params = {};
params['svgTransform'] = ['scale(1)', 'scale(1.5)'];
$('#TX', svg.root()).animate(params);
This is copied almost verbatim from the developer of the plugin.
Yet when it runs, I'm getting this:
4TypeError: 'undefined' is not a function (evaluating 'f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration)')
Any ideas?
I think you should check for existence of an element with ID="TX" in your SVG document.
Anyway, I must say that sometimes I found very difficult to remember where to code specific behaviour: there are so many choices, among XML (plain SVG), plain JavaScript+DOM (but what DOM?), jQuery specific, jQuery+SVG.... And all of these with their details... It's daunting! I hope it will be rewarding in the end.
BTW I found that Chrome give a good IDE to workout problems (I'm on Linux now...). Hit Ctrl+Shift+I to enter the debugger and see whatever error...
maybe it doesn't support array inside animate arg object. can you try :
var params = {};
params['svgTransform'] = 'scale(1.5)';
$('#TX', svg.root()).animate(params);
I currently have a bunch of lines that look like:
txt = "Can't print the value for <span class='keyword'>"+arguments[1]+"</span> before it's set";
I'm then doing
$('#mydiv').append($('<div/>').html(txt));
This looks terrible and I need to escape any html inside arguments[1]
The only alternative I can think of is to make sure all the text is inside its own element:
var spans = [];
spans[0] = $('<span/>').text("Can't print the value for ");
spans[1] = $('<span/>').text(arguments[1]).className('keyword');
spans[2] = $('<span/>').text(" before it's set");
$('#mydiv').append($('<div/>').append(spans[0],spans[1],spans[2]));
This is quite a lot for just a simple line of text. Is there anything else I can do?
edit: This isn't something that should be handled by a templating engine. It's html generated by a javascript logging function.
If It's a consistent format, I'd add it as a normal string and then do a search for the keyword part.
$('<div/>')
.appendTo('#mydiv')
.html("Can't print the value for <span class='keyword'></span> before it's set")
.find('.keyword').text(arguments[1]);
If you will be continuing to create lots of HTML using JS, I would suggest working with a templating library. I am a recent convert, it took me a long time to understand the point. But seeing many successful sites (twitter,github,etc.) and the great John Resig promote and/or make heavy use of templating, i'm glad I stuck with trying to understand. Now I get it. It's for separation of concerns, keeping logic out of the view.
I'm using this very bare bones templating library: http://blueimp.github.com/JavaScript-Templates/ though the templating provided by underscore.js and mustache.js are more popular.
The advantage of the library i'm using is its really small, <1kb and is basically like writing php/asp code if you are familiar with those.
you can write HTML inside <script> tags without having to escape:
using your variable, txt, the syntax looks like this:
<script>
var data={txt : "Can't print the value for <span class='keyword'>"+arguments[1]+"</span> before it's set"};
<div>{%=o.txt%}</div>
</script>
I was just reading the Times online and I wanted to copy a bit of text from the article and IM it to a friend, but I noticed when I did so, it automatically appended the link back to the article in what I had copied.
This is not a feature of my IM client, so I assume this happened because of some javascript on Times website.
How would I accomplish this if I wanted to implement it on my site? Basically, I would have to hijack the copy operation and append the URL of the article to the end of the copied content, right? Thoughts?
Here's the article I was reading, for reference: http://www.time.com/time/health/article/0,8599,1914857,00.html
It's a breeze with jQuery (which your referenced site is using):
$("body").bind('copy', function(e) {
// The user is copying something
});
You can use the jQuery Search & Share Plugin which does this exact thing whenever somebody copies more than 40 chars from your site: http://www.latentmotion.com/search-and-share/
The site that you referenced is apparently using a service called Tynt Insight to accomplish this though.
They are using the free service Tynt. If you want to accomplish the same thing, just use the same service.
What browser are you using (and what version)?
In some newer browsers, the user is either asked if a website can access the clipboard, or its simply not allowed. In other browsers (IE 6, for example), it is allowed, and websites can easily read from and write to your copy clipboard.
Here is the code (IE only)
clipboardData.setData("Text", "I just put this in the clipboard using JavaScript");
The "Copy & Paste Hijacker" jQuery plugin does exactly what you want and seems better suited for your purposes than Tynt or Search & Share: http://plugins.jquery.com/project/copypaste
You can easily format the copied content, specify max or min characters, and easily include the title of the page or the URL in the copied content exactly where you want.
I recently noticed this on another website and wrote a blog post on how it works. The jQuery example doesn't seem to actually modify what the user copies and pastes, it just adds a new context menu.
In short:
var content = document.getElementById("content");
content.addEventListener("copy", oncopy);
function oncopy() {
var newEl = document.createElement("p");
document.body.appendChild(newEl);
newEl.innerHTML = "In your copy, messing with your text!";
var selection = document.getSelection();
var range = selection.getRangeAt(0);
selection.selectAllChildren(newEl);
setTimeout(function() {
newEl.parentNode.removeChild(newEl);
selection.removeAllRanges();
selection.addRange(range);
}, 0)
}
The setTimeout at the end is important as it doesn't seem to work if the last part is executed immediately.
This example replaces your selected text at the last minute with my chosen string. You can also grab the existing selection and append whatever you like to the end.