I'm relatively new to JavaScript, so please bear with me.
I run an instance of the Blackboard Learn LMS. Feel sorry for me later. Blackboard displays different modules to end users to show different pieces of information. The Announcements module contains non-editable code that sends an Ajax request to display all system-wide and course-specific announcements for that particular user:
<div id="Announcements">
<div id="div_1_1"> </div>
<script type="text/javascript">
Event.observe(window, 'load', function () {
new Ajax.Request('/webapps/portal/execute/tabs/tabAction', {
method: 'post',
parameters: 'action=refreshAjaxModule&modId=_1_1&tabId=_2830_1&tab_tab_group_id=_155_1',
onSuccess: function (transport) {
try {
var res = transport.responseXML.getElementsByTagName('contents')[0].firstChild.nodeValue;
$('div_1_1').innerHTML = res.stripScripts();
page.globalEvalScripts(res, true);
} catch (e) {
$('div_1_1')
.innerHTML = 'Module information is temporarily unavailable. Please reload the page. <!--' + e.toString()
.escapeHTML()
.gsub('-', '-') + '-->';
}
},
onFailure: function (transport) {
$('div_1_1').innerHTML = 'Error loading module.';
}
});
});
</script>
</div>
The module brings up a lot of redundant information that I'd like to hide. Since there's no way to edit that particular code, I've been trying to figure out a way to do one of the following:
Modify the module's contents with additional scripting from another source on the page.
Copy the module's contents to a new, editable module, and display that one instead,
Both methods have proven impossible because the script in the Announcements module only runs once the page has loaded entirely, so there's no way to run a script afterward or wait until the process has completed.
Any ideas on how I might be able to modify the contents without editing its code directly?
I ended up using the DOMSubtreeModified event:
<script type="text/javascript">
$j = jQuery.noConflict();p
$j("#div_1_1").on("DOMSubtreeModified", function () {
var div = document.getElementById("div_1_1");
var inner = div.innerHTML;
inner = inner.substring(
inner.indexOf("<!-- Display course/org announcements -->")
);
div.innerHTML = inner;
});
</script>
Related
I'm trying to create a button that, upon clicking, "saves" the positions of multiple lists from a connected-sortable. I want the script to be able to retain the most recent position of each list item when the page is refreshed (i.e. If list 1 starts as A,B,C and I change it to B,A,C and refresh the page, it stays as B,A,C.).
I'm attempting to accomplish this by creating an array from an html document (published as a web app), save it using the getUserProperities function, and then return it the next time I open the web app.
I am able to log the positions without issue, but I'm having trouble figuring out where to run the getUserProperities function, or what other issue I may be dealing with.
In the console from the web app, I get this error Uncaught TypeError: Cannot read property 'getUserProperties' of undefined at saveList (userCodeAppPanel:4) at HTMLButtonElement.onclick (userCodeAppPanel:1).
Where should I be calling the getUserProperties function? From code.gs or index.html? I have been working off the example provided HERE.
The relevant portions of my code, from index.html are below.
<script>
$( function() {
$( "#myList, #flight1a, #flight1b, #flight2a, #flight2b, #flight3a, #flight3b, #sortable2" ).sortable({
connectWith: ".connectedSortable",
update: function(event, ui) {
var changedList = this.id;
var order = $(this).sortable('toArray');
var positions = order.join(';');
console.log({
id: changedList,
positions: positions
});
}
})
});
</script>
<script>
function saveList() {
google.script.run.PropertiesService.getUserProperties().setProperty('myProperty', JSON.stringify(positions));
var returnedObj = PropertiesService.getUserProperties("myProperty");
returnedObj = JSON.parse(returnedObj);
}
</script>
</head>
<body>
<button onclick="saveList()">Click me</button>
Properties Service can only be accessed through Google Apps Script, so it must be called in one of your *.gs files. To execute a server-side function, you need to use google.script.run (there's also a guide available).
For example, in your code.gs file add this function:
function savePositions(propertyName, value) {
PropertiesService.getUserProperties().setProperty(propertyName, value);
}
Then, in your index.html file modify saveList() to:
function saveList() {
google.script.run.savePositions("myProperty", JSON.stringify(positions));
}
google.script.run could be used to call a server side function not to call directly the Properties Service.
For further details see https://developers.google.com/apps-script/guides/html/reference/run
I'm new to JavaScript and trying to get this Tampermonkey script working. The scripts works just fine when it collects data from one page. However, I now want it to collect the data as before, but then move on to another page and continue the data collecting.
My code:
$(document).ready(function() {
$("#getData").click(function() {
// Part 1. Collect data and move on
window.location.href = goToURL;
// Part 2. Collect more data when the page has fully loaded
});
});
I have tired to put Part 2 of the code inside:
setTimeout(function() {
}, 5000);
and
window.onload = function(){
};
But I cannot get the code to work, it either executes before the page has loaded, or seemingly not at all. What am I missing?
When you change page with location.href, your JS is reloaded. So you need a way to store data between page changing. I suggest to use LocalStorage
Your code would look like:
function storeState(state){
localStorage.setItem('state', state);
}
function loadState(state){
return localStorage.getItem('state');
}
$(document).ready(function() {
var state = getState();
$("#getData").click(function() {
// Collect data and put it into state
storeState(/* your collected state*/)
window.location.href = goToURL;
});
});
Notice that you have to do some serialize/deserialize stuff because localStorage only save strings
Also as mentioned #charlietfl if you have different domains it will cause additional difficults
I have been looking around for the simplest way to refresh a particular div on my page, automatically, every x seconds.
So far I've got:
<script type="text/javascript">
window.onload = startInterval;
function startInterval()
{
setInterval("startTime();",1000);
}
function startTime()
{
document.getElementById('time').innerHTML = Date();
}
However the last part where the innerHTML is set to the date function is what I'd like replaced by the content of the "time" ID, and not an actual date print.
I know I could load an iframe, or externa html page, but I would like to simply call upon an existing div on the page instead of having to change the existing content. Is that possible?
Thanks!
Edit: What I mean is I have a a div that looks like this on the page:
Some stuff
I would like to have that div refreshed every x seconds, so yes, you may ignore the Date() part of my example, I simply found that code as is but when I tried to remove the .innerHTML part it just does nothing, I think lol!
Are you looking for something like this?
<script type="text/javascript">
window.onload = startInterval;
function startInterval() {
setInterval("startTime();",1000);
}
function startTime() {
var now = new Date();
document.getElementById('time').innerHTML = now.getHours() + ":" + now.getMinutes() + ":" +now.getSeconds();
}
</script>
NOTE: The OP is actually wanting to reload a script in an ad service already included on the page. The following does not help with this; however, due to the way the question was asked, I'm leaving this answer since I think it could help others looking for the following type of solution. Just be aware this does not demonstrate how to "rerun" already included (presumably global and non-function'd) code.
Say I have the following div I'd like to dynamically refresh:
<div id="refresh">Refreshes...</div>
jQuery offers the $.ajax group of functions that allow you to dynamically request a page and use the response as HTML. For instance:
$(document).ready(function(){
var $refresh = $('#refresh'),
loaded = 1,
data = {
html: $.toJSON({
text: 'some text',
object: {}
}),
delay: 3
};
var refresh = function(){
$.ajax({
url: "/echo/html/",
data: data,
type: "GET",
success: function(response) {
$refresh.html($refresh.html() + '<br/>#' + loaded);
loaded++;
setTimeout(refresh, 3000);
}
});
};
refresh();
});
http://jsfiddle.net/Ah3jS/
Note, I'm using jsFiddle's echo/html/ functionality here as well. The data variable is tuned to working with this for demonstration purposes. In reality, the data sent with the request is either GET or POST variables like you work with normally. Also, I don't use response in success, but that's because it doesn't return anything in jsFiddle's demo mode.
jQuery make's this stuff pretty easy. Really, I'd think about using it instead of most other approaches (requirements notwithstanding).
I am trying to copy some data from one processed web page into a new one that I want to export. The background is that I need to scrape parts of a page and need to build a new page with parts of the original page.
The problem seems that phantomJs includeJs() and evaluate() methods are sandboxed and I can't see a proper way to import DOM from one page to another.
I have some test code that looks like this, with page being the original and out the new page:
....
var title = page.evaluate(function() {
return title = document.getElementById('fooo').innerHTML;
});
console.log('page title:' + title);
//fs.write('c:/Temp/title.js', "var title = '" + title + "';", 'w');
var out = new WebPage;
out.viewportSize = page.viewportSize;
out.content = '<html><head></head><body><div id="wrapper"></div><p>done</p></body></html>';
out.includeJs('c:/Temp/title.js', function() {
var p = document.createElement('p');
p.appendChild(document.createTextNode(title));
document.getElementById('wrapper').appendChild(p);
});
...
The function in your last includeJs call here won't work - as you note, it's sandboxed, and that means that closures won't work, so title won't be defined. A method of passing variables to page.evaluate is noted as a feature request, but isn't available as of PhantomJS v.1.4.1.
The general way I get around this is by using the Function constructor, which allows you to create a function using a string:
var myVar = {some:"values", I:"want to pass into my page"},
test = new Function("window.myVar = " + JSON.stringify(myVar));
page.evaluate(test);
Now you can evaluate a function like the one you have, referencing myVar in the sandbox, and your data will be available in the client scope.
I want to display little messages to provide feedback to the user while he
is providing input or just interacting with the UI.
I need it for my firefox addon, so I have to develop it in plain javascript
and not jQuery.
I want the message to appear, but only one message can be visible at the same
time, so I need some kind of queue to manage incomming messages. After a certain time
e.g. 3 sec the message should fade away or just disappear.
For now I am able to add messages to the DOM. Any suggestions how to implement the queue
and how to push the messages forward according to the time?
Thanks!
Perheps you need the concept of FIFO (First In First Out)
Take a look at this simple example in plan java script language:
function Queue() {
var data = [];
this.isEmpty = function() {
return (data.length == 0);
};
this.enqueue = function(obj) {
data.push(obj);
};
this.dequeue = function() {
return data.shift();
};
this.peek = function() {
return data[0];
};
this.clear = function() {
data = [];
};
}
You can use jQuery in a firefox plugin:
Include a script tag in the xul file that points to the jQuery file, e.g.:
<script type="text/javascript" src="chrome://extensionname/content/jquery.js" />
In each js function that uses jQuery, insert this line:
$jQuizzle = jQuery.noConflict();
In each jQuery call, if you are trying to manipulate the document in the current browser window, you must supply the context as "window.content.document", like this:
$jQuizzle(".myClass", window.content.document).show();
Then you can use this jQuery plugin:
http://benalman.com/projects/jquery-message-queuing-plugin/
It's not clear what sort of message you want to display. The nsIAlertsService can display messages but I'm not sure how well it queues them. If you want something simpler then perhaps you could just show a custom <tooltip> element.