I am having problems with a javascript function. I want to replace an icon by changing the class.
On my page, I have the following element:
<i class="wait icon" alt="{webui_botstatenotavailable}" title="{webui_botstatenotavailable}" id="{botname}"></i>
The following javascript should change the class, but it does not work:
function incomingBotStatusList(http_request, statusOff, statusOn)
{
if (http_request.readyState == 4)
{
if (http_request.status == 200)
{
if (http_request.responseText.length < 7)
{
// Error
}
else
{
var botStatusList = JSON.parse(http_request.responseText);
for (var key in botStatusList)
{
if (botStatusList.hasOwnProperty(key))
{
var botStatusImage = document.getElementById(key);
if (botStatusImage != null)
{
if (botStatusList[key] == 0)
{
botStatusImage.class.innerHTML = "images/bullet_red.png";
botStatusImage.title = statusOff;
botStatusImage.alt = statusOff;
}
else if (botStatusList[key] == 1)
{
botStatusImage.class.innerHTML = "<i class=\"checkmark green icon\">";
botStatusImage.alt = statusOn;
botStatusImage.title = statusOn;
}
}
}
}
}
}
}
}
Did someone from you know how it will work?
Thanks for your help!
Best Regards
Pierre
I see a couple of problems with your code. First, the <i> element is used to apply italic formatting to text. It is not the HTML code for an icon or an image.
Secondly, you write botStatusImage.class.innerHTML, but the Element.class does not exist, and Element.className is a string. It does not have an innerHTML attribute. So, you could write botStatusImage.className = "new_class_name"; and this would be more correct.
You should then change the image source by calling botStatusImage.setAttribute('src', new_url), where you have set new_url to the new image location.
Check out the javascript reference for the Element class that is returned from document.getElementById: check this link
My recommendation, start simple, then make it complex.
First, try to get the icon to change without the AJAX request. Try writing a function like this:
function changeIcon( imageId, newUrl ){
var element = document.getElementById( imageId );
element.setAttribute( "src", newUrl );
}
Then test this function in the console by passing calling it with the URL's manually.
Once that works, don't change it! Next add the AJAX call, and when you have the Icon url from your server response, all you do is call the function that you already wrote and tested. That way you separate the AJAX code from the image update code and you can test them separately.
The key is smaller functions. Build the easy stuff first, and then call those easy functions from the harder functions. Once you know the easy function works well, it becomes much easier to find problems in the harder functions.
Related
I need to get :after and assign it to variable. It is possible?
querySelectorAll doesn't work.
alert(some_div_with_pseudo.querySelectorAll('::after')[0]) // undefined
The short answer is that you can’t. It’s not there yet.
JavaScript has access to the DOM, which is built when the page is loaded from HTML, and modified further when JavaScript manipulates it.
A pseudo element is generated by CSS, rather than HTML or JavaScript. It is there purely to give CSS something to hang on to, but it all happens without JavaScript having any idea.
This is how it should be. In the overall scheme of things, the pages starts off as HTML. JavaScript can be used to modify its behaviour and to manipulate the content on one hand, and CSS can be used to control the presentation of the result:
HTML [→ JavaScript] → CSS → Result
You’ll see that CSS, complete with pseudo elements, comes at the end, so JavaScript doesn’t get a look in.
See also:
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector#Usage_notes
https://www.w3.org/TR/selectors-api/#grammar
Edit
It seems that in modern JavaScript there is a workaround using window.getComputedStyle(element,pseudoElement):
var element = document.querySelector(' … ');
var styles = window.getComputedStyle(element,':after')
var content = styles['content'];
You can do this:
window.getComputedStyle(
document.querySelector('somedivId'), ':after'
);
Sample here: https://jsfiddle.net/cfwmqbvn/
I use an arrow pointing in the direction that the content and sidebar will toggle to/from via a CSS pseudo-element. The code below is effectively a write mode however it is entirely possible to read CSS pseudo-element content as well.
Since there is a bit involved I'll also post the prerequisites (source: JAB Creations web platform JavaScript documentation, if anything missing look it up there) so those who wish to try it out can fairly quickly do so.
CSS
#menu a[href*='sidebar']::after {content: '\2192' !important;}
JavaScript Use
css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2192"','important');
JavaScript Prerequisites
var sidebar = 20;
function id_(id)
{
return (document.getElementById(id)) ? document.getElementById(id) : false;
}
function css_rule_set(selector,property,value,important)
{
try
{
for (var i = 0; i<document.styleSheets.length; i++)
{
var ss = document.styleSheets[i];
var r = ss.cssRules ? ss.cssRules : ss.rules;
for (var j = 0; j<r.length; j++)
{
if (r[j].selectorText && r[j].selectorText==selector)
{
if (typeof important=='undefined') {r[j].style.setProperty(property,value);}
else {r[j].style.setProperty(property,value,'important');}
break;
}
}
}
}
catch(e) {if (e.name !== 'SecurityError') {console.log('Developer: '+e);}}
}
function sidebar_toggle()
{
if (id_('menu_mobile')) {id_('menu_mobile').checked = false;}
if (getComputedStyle(id_('side')).getPropertyValue('display') == 'none')
{
css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2192"','important');
if (is_mobile())
{
css_rule_set('main','display','none','important');
css_rule_set('#side','width','100%','important');
css_rule_set('#side','display','block','important');
}
else
{
css_rule_set('main','width',(100 - sidebar)+'%');
css_rule_set('#side','display','block');
}
}
else
{
css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2190"','important');
if (is_mobile())
{
css_rule_set('main','display','block','important');
css_rule_set('main','width','100%','important');
css_rule_set('#side','display','none','important');
}
else
{
css_rule_set('main','width','100%','important');
css_rule_set('#side','display','none');
}
}
There is a way in JavaScript to access value of pseudo elements without any library. To get the value, you need to use the 'getComputedStyle' function. The second parameter is optional.
let elem = window.getComputedStyle(parent, ':before');
alert(elem.getPropertyValue('background'))
This will do alert the value of pseudo element.
let elem = window.getComputedStyle(document.querySelector('#item'), ':after');
console.log(elem.getPropertyValue('content'))
I'm using the object tag to load an html snippet within an html page.
My code looks something along these lines:
<html><object data="/html_template"></object></html>
As expected after the page is loaded some elements are added between the object tags.
I want to get those elements but I can't seem to access them.
I've tried the following
$("object").html() $("object").children() $("object")[0].innerHTML
None of these seem to work. Is there another way to get those elements?
EDIT:
A more detailed example:
consider this
<html><object data="http://www.YouTube.com/v/GGT8ZCTBoBA?fs=1&hl=en_US"></object></html>
If I try to get the html within the object I get an empty string.
http://jsfiddle.net/wwrbJ/1/
As long as you place it on the same domain you can do the following:
HTML
<html>
<object id="t" data="/html_template" type="text/html">
</object>
</html>
JavaScript
var t=document.querySelector("#t");
var htmlDocument= t.contentDocument;
Since the question is slightly unclear about whether it is also about elements, not just about the whole innerHTML: you can show element values that you know or guess with:
console.log(htmlDocument.data);
The innerHTML will provide access to the html which is in between the <object> and </object>. What is asked is how to get the html that was loaded by the object and inside the window/frame that it is producing (it has nothing to do with the code between the open and close tags).
I'm also looking for an answer to this and I'm afraid there is none. If I find one, I'll come back and post it here, but I'm looking (and not alone) for a lot of time now.
No , it's not possible to get access to a cross-origin frame !
Try this:
// wait until object loads
$('object').load(function() {
// find the element needed
page = $('object').contents().find('div');
// alert to check
alert(page.html());
});
I know this is an old question, but here goes ...
I used this on a personal website and eventually implemented it in some work projects, but this is how I hook into an svg's dom. Note that you need to run this after the object tag has loaded (so you can trigger it with an onload function). It may require adaptation for non-svg elements.
function hooksvg(elementID) { //Hook in the contentDocument of the svg so we can fire its internal scripts
var svgdoc, svgwin, returnvalue = false;
var object = (typeof elementID === 'string' ? document.getElementById(elementID) : elementID);
if (object && object.contentDocument) {
svgdoc = object.contentDocument;
}
else {
if (typeof object.getSVGDocument == _f) {
try {
svgdoc = object.getSVGDocument();
} catch (exception) {
//console.log('Neither the HTMLObjectElement nor the GetSVGDocument interface are implemented');
}
}
}
if (svgdoc && svgdoc.defaultView) {
svgwin = svgdoc.defaultView;
}
else if (object.window) {
svgwin = object.window;
}
else {
if (typeof object.getWindow == _f) {
try {
svgwin = object.getWindow();//TODO look at fixing this
}
catch (exception) {
// console.log('The DocumentView interface is not supported\r\n Non-W3C methods of obtaining "window" also failed');
}
}
}
//console.log('svgdoc is ' + svgdoc + ' and svgwin is ' + svgwin);
if (typeof svgwin === _u || typeof svgwin === null) {
returnvalue = null;
} else {
returnvalue = svgwin;
}
return returnvalue;
};
If you wanted to grab the symbol elements from the dom for the svg, your onload function could look like this:
function loadedsvg(){
var svg = hooksvg('mysvgid');
var symbols = svg.document.getElementsByTagName('symbol');
}
You could use the following code to read object data once its loaded completely and is of the same domain:
HTML-
<html>
<div class="main">
<object data="/html_template">
</object>
</div>
</html>
Jquery-
$('.main object').load(function() {
var obj = $('.main object')[0].contentDocument.children;
console.log(obj);
});
Hope this helps!
Here goes a sample piece of code which works. Not sure what the problem is with your code.
<html>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var k = $("object")[0].innerHTML;
alert(k);
$("object")[0].innerHTML = "testing";
});
</script>
<object data="/html_template">hi</object>
</html>
UPDATED
I used this line of Javascript to change the value of a input filed inside an iFrame, taken from How to pick element inside iframe using document.getElementById:
document.getElementById('iframeID').contentWindow.document.getElementById('inputID').value = 'Your Value';
In your case, since you do not have a frame, and since you want to get and not set the value, log it for example with:
console.log(document.getElementById('object').value);
And if you guess or choose an element:
console.log(document.getElementById('object').data);
I have some javascript which looks at the body and finds words and if one is present, it outputs a div. This is useful for many things, however...
What I need to do is also look at the body and all the ALT tags for the page as well.
I found this: Use javascript to hide element based on ALT TAG only?
Which seems to change the ALT attribute, however I want to perform an action.
Here's my JS so far.
var bodytext = $('body').text();
if(bodytext.toLowerCase().indexOf('one' || 'two')==-1)
return;
var elem = $("<div>Text Here</div>");
Thank you.
P.S. I am a N00B/ relatively new at JS, I am doing this for a small project, so I am not sure where to start for this in terms of JS functions.
Updated Answer
Try this out, I commented the code to explain it a bit.
// build array of triggers
var triggers = ['trigger1','trigger2','trigger3'];
// wait for page to load
$(function() {
// show loading overlay
$('body').append('<div id="mypluginname-overlay" style="height:100%;width:100%;background-color:#FFF;"></div>');
// check page title
var $title = $('head title');
for(trigger of triggers) {
if($($title).innerHTML.toLowerCase().indexOf(trigger) >= 0) {
$($title).innerHTML = '*censored*';
}
}
// check all meta
$('meta').each(function() {
var $meta = $(this);
for(trigger of triggers) {
if($($meta).attr('name').toLowerCase().indexOf(trigger) >= 0) {
censorPage();
return; //stop script if entire page must be censored
} else if($($meta).attr('content').toLowerCase().indexOf(trigger) >= 0) {
censorPage();
return; //stop script if entire page must be censored
}
}
});
// check all img
$('img').each(function() {
var $img = $(this);
for(trigger of triggers) {
if($($img).attr('alt').toLowerCase().indexOf(trigger) >= 0) {
censor($img);
}
}
});
// check all video
$('video').each(function() {
var $video = $(this);
for(trigger of triggers) {
if($($video).attr('alt').toLowerCase().indexOf(trigger) >= 0) {
censor($video);
}
}
});
// if you want to be extra careful and check things like background image name,
// you'll have to run this code here - very inefficent
// but necessary if you want to check every single element's background image name:
for($element of $('body').children()) {
for(trigger of triggers) {
if($($element).css('background-image').toLowerCase().indexOf(trigger) >= 0) {
$($element).css('background-image','');
}
}
}
, function() { // Not sure if this is totally correct syntax, but use a callback function to determine when
// when the rest of the script has finished running
// hide overlay
$('#mypluginname-overlay').fadeOut(500);
}});
function censor($element) {
// just a basic example, you'll probably want to make this more complex to overlay it properly
$element.innerHTML = 'new content';
}
function censorPage() {
// just a basic example, you'll probably want to make this more complex to overlay it properly
$('body').innerHTML = 'new content';
}
---Original Answer---
I'm not sure exactly what you would like to do here, you should add more detail. However if you choose to use jQuery, it provides tons of useful methods including the method .attr(), which lets you get the value of any attribute of any element.
Example:
var alt = $('#my-selector').attr('alt');
if (alt == 'whatYouWant') {
alert('yay');
} else {
alert('nay');
}
You're using jQuery lib, you could select elements by attribute like:
$('[alt="one"]').each(function(el){
// do something
var x = $(el).arrt('alt');
});
If you use selector $('[alt]') you can get elements that have this attribute set, and then check the value of the element if you have a more complicated selection.
Than you have to change your return, as you could not put a div inside an ALT tag, it didn't work.
Here is about what is your expected output.
UPDATE
As you want to change all images and video in a page, the way to do this with jquery is through $.replaceWith():
$('img,video').replaceWith($('<div>Text Here</div>'));
If you need to filter the elements:
$('img,video').each(function(el){
if($(el).prop('tagName') == 'IMG' &&
$(el).attr('alt') == 'the text...') {
$(el).replaceWith($('<div>Text Here</div>'));
}
})
But I'm not an expert on Chrome Extensions, I just put this code here in jQuery, as you was using jQuery.
Of course it could be done, with much code with plain javascript and the DOM API.
My function is as follows:
function mySound() {
var eventTable = document.querySelector("#eventContent");
var eventCella=eventTable.getElementsByClassName("ago_eventlist_activity");
var eventCellb = eventTable.getElementsByClassName("missionFleet");
for (var i = 0; i < eventTable.rows.length-1; i++) {
var cella = eventCella[i];
var cellb = eventCellb[i];
if (cella.src == "Activity15.gif" && cellb.src == "60a018ae3104b4c7e5af8b2bde5aee.gif")
{theSound = probeSound; oaPlaySound();}
if (cella.img == "Activity15.gif" && cellb.img == "cd360bccfc35b10966323c56ca8aac.gif")
{theSound = attackSound; oaPlaySound();}
if (cella.img == "Activity15.gif" && cellb.img == "575dfbbe877f58d6c09120ffbcaabe.gif") {theSound = attackSoundRIP; oaPlaySound();}
} /* for i */
}
*I can't use ...byid cause it doesn't seem to have one?
I am including a link to the FireFox inspect element so you can see what I can see to try to make this work.
Image of InspectElement:
Any help would be helpful I am just trying to code this for a friend and I really don't know java at all.
Thanks
There is a difference between Java and javascript. I'm guessing you mean javascript since that is what the code appears to be.
There are a few issues with the code
cella.img does not target the image inside of the cell, you'll need to target the image first, or use find the image inside the cell.
var eventCella = eventTable.querySelector(".missionFleet img");
or
var imgb = eventCellb[i].querySelector("img");
Does the ago_eventlist_activity cell even contain an image? There doesn't seem to be one in the screenshot.
Checking the image src needs to include the complete url, unless you use an indexOf...
if (imgb.src.indexOf('60a018ae3104b4c7e5af8b2bde5aee.gif') > -1) {
// do something
}
I hope that helps. Please, the next time you ask a question, include the HTML instead of a screenshot. Or better yet, include a demo (jsFiddle) that shows the problem because it makes it easier for others to help. Not everyone will take the time or make an effort.
I have a simple JS script to swap out elements containing Flash and replace them with other formats for users who don't have Flash installed.
var hideclass="hidden"
var showclass="empty"
function flashFixMain(){
if (swfobject.hasFlashPlayerVersion("7.0.0")) {
document.getElementById('logoflash').className=showclass;
document.getElementById('logononflash').className=hideclass;
} else {
document.getElementById('logoflash').className=hideclass;
document.getElementById('logononflash').className=showclass;
}
}
And put simply, it doesn't work.
The if statement works fine - putting an alert in the appropriate place pops up fine.
I've checked the source of the appropriate page(s) online, and the element name pops up exactly as written (and only once!).
The class names work fine, as they are used as defaults on the page at the start.
So does anyone have any ideas what I might have missed?
change
document.getElementById('logoflash').class=showclass;
to
document.getElementById('logoflash').className = showclass;
it's className, not class
Instead of using .class you need to use the .className property; for instance:
document.getElementById('logoflash').className = showclass;
In modern browsers you can also use .classList to add a class rather than replace all existing classes:
document.getElementById('logoflash').classList.add(showclass);
As an aside, you could consider moving a few statements around like this:
var hasFlash = swfobject.hasFlashPlayerVersion("7.0.0"),
logoFlash = document.getElementById('logoflash'),
logoNonFlash = document.getElementById('logononflash');
logoFlash.className = hasFlash ? showclass : hideclass;
logoNonFlash.className = hasFlash ? hideclass : showclass;
I wrote up a quick test scenario and without seeing more of your environment, do not see anything that should keep this from working as expected.
The one thing I did notice while doing a write up w/o using jQuery (which I guess you are NOT using?) is that your 'addClass' is really a 'REPLACE' class value. You are simply setting it to a single class.
This makes me think, not having seen your environment, that some OTHER classes might be already assigned to your elements that are getting wiped out. This could be causing unexpected behaviour if some of your display is dependent on these other classes...
Without seeing more of your scenario, that is the only thing that seems like it might be an issue.
Anyway, here is my test setup. You might find something in this useful.
<div id="logoflash" class='something'>
Logoflash
</div>
<div id="logononflash" class='else' >
logononflash
</div>
<script>
var swfobject = {FlashPlayerVersion: '7.0.1', hasFlashPlayerVersion: function(v) {if(v == this.FlashPlayerVersion) return true; else return false;}, myName: 'fakeSWObject' };
console.log(swfobject)
var hideclass = "hidden"
var showclass = "empty"
var getById = function(sID) { return document.getElementById(sID); };
var addClass = function(sID, sClass) { getById(sID).className += ' ' + sClass };
function toggleEl(sID, bState){
console.log('begin toggleEl')
console.log('bState: ' + bState)
try {
if(bState == undefined) {
console.log('Toggling by element state');
getById(sID).style.display = getById(sID).style.display == 'none' ? 'block' : 'none';
} else {
console.log('Toggling by argument');
getById(sID).style.display = !!bState ? 'block' : 'none';
}
} catch (err) {
console.log(err);
}
}
function flashFixMain(){
if (swfobject.hasFlashPlayerVersion("7.0.0")) {
console.log('Is Flash 7.0.0');
toggleEl('logoflash', true);
toggleEl('logononflash', false);
addClass('logoflash', hideclass);
addClass('logononflash', showclass);
} else {
console.log('Is NOT Flash 7.0.0');
toggleEl('logoflash', true)
toggleEl('logononflash', false)
addClass('logoflash', showclass);
addClass('logononflash', hideclass);
}
}
$(function(){ // Yes, this is jQuery to fire after doc is ready
flashFixMain();
})
</script>
use Jquery:
$("#logoflash").addClass(hideclass);
or
$('#logoflash').toggleClass(hideclass, swfobject.hasFlashPlayerVersion("7.0.0"));