Google apps script and jquery mobile loader giving two spinners - google-apps-script

Let me preface this by saying I want a spinner...
I don't necessarily care whether it loads when the page first starts up, or later. The problem I'm experiencing also doesn't seem to care, as I've tried it both ways.
Right this moment, I don't declare it at the top of the page. Because I have a lot of visualization stuff going on, I start that up and immediately pass some info to the spinner (which also starts it up):
google.load('visualization', '1', {packages:['controls'], callback: initializeTables});
function initializeTables() {
provideInfo("loading proficiencies (Step 1/12)");
//etc... }
function provideInfo(text) {
$.mobile.loading( "show", {
text: text,
textVisible: true
});
}
So that starts... fine... ish...
The problem is that there's actually two spinners started when that starts - one in front, one behind. Because the one in front is slightly offset from the one behind, I can see both.
If I later call:
$.mobile.loading( "hide" );
It only hides the front one, not the back one.
I've found I can hide both by saying:
$(".ui-loader").hide();
Which is great. But, I'd like to not see two in the first place. I've tried to puzzle out the jquery mobile documentation page, to no avail (it also mentions a "global method docs" but I haven't been able to find that link):
//This does not work:
$( ".ui-loader" ).loader( "option", "text", "Loading Page..." );
//Nor does this:
$( "#notify_div" ).loader( "show" );
$( "#notify_div" ).loader( "option", "text", "Loading Page..." );
Anyone know how to get it all into one spinner, or why it's loading two?

Sadly, the current JQM documentation is for the 1.5 version which hasn't be released yet. You need to look directly at the source code of the 1.4.5 version.
There is a JQM default which is showing the spinner when a page is loading. You can override this behavior at JQM initialization.
<script type="application/javascript" src="js/jquery-2.2.4.js"></script>
<script>
$(document).on("mobileinit", function () {
$.mobile.changePage.defaults.showLoadMsg = false;
});
</script>
<script type="application/javascript" src="js/jquery.mobile-1.4.5.js"></script>
If You look at line 5847 of the JQM uncompressed source code, You will find all the configurable settings for that.
Moreover, just for the sake of completeness, there is another setting where You can tell JQM to not show the spinner for already cached pages. Just look at line 5122 of the JQM uncompressed source code:
// This delay allows loads that pull from browser cache to
// occur without showing the loading message.
loadMsgDelay: 50
Hope this help.

Related

Tampermonkey clicking a button by class

So i have a school issue where i need to access a site but this site requires me to go through around 4 portals to get there and am hoping to just write a quick script to do this for me. Problem comes where the site is very sloppy and are written with names being the same on certian buttons so I would like to click the buttons based on class
the classes are readit2, readit23, readit239, and readit2394
$(function(){
document.getElementByClassName(readit2).click();
});
the above code i thought would click it as soon as it loads the first page but does not. any help would be great
// ==UserScript==
// #name dumb spider web
// #namespace ===============
// #version 0.1
// #description gets me through this dumb stuff
// #match ===============
// #copyright 2012+, You
// #require http://code.jquery.com/jquery-latest.js
// ==/UserScript==
edit ^ added the header stuff
more edits:
it works through the console now but through tamper monkey OR grease monkey I can not get it to actually preform the action.
$(function(){
document.getElementsByClassName("readit2")[0].click();
});
Works through console but does not run when script is started.
I started looking at all the wrong things, your original code:
$(function(){
document.getElementByClassName(readit2).click();
});
The issue with this is that the call should be getElementsByClassName (plural "Elements"), since class is usually a shared property. That also returns an array, so if you are positive that there is only 1 ever:
$(function(){
document.getElementsByClassName("readit2")[0].click();
});
If not, I'd suggest getting the text and verifying that it contains something that you expect.
Edit: Added quotes.
The problem is that you are trying to access some nodes that still don't exist. Add this to your script:
// #run-at document-end
Then you make sure that all nodes are loaded and printed.
Another bypass would be this:
$(document).ready(
//your script
);

Safari 6.0.2 not calling onaudioprocess

I've earlier successfully used the JavaScriptAudioNode in the Web Audio API to synthesize and mix audio both in Chrome and Safari 6.0. However, the latest version of Safari no longer appears to work, because it does not call onaudioprocess to fill the source buffers.
This is a simplified example which plays only silence and appends text to the document body on each call to onaudioprocess:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("a").click(function() {
var context = new webkitAudioContext();
var mixerNode=context.createJavaScriptNode(2048, 0, 2);
mixerNode.onaudioprocess=function(ape) {
var buffer=ape.outputBuffer;
for(var s=0;s<buffer.length;s++)
{
buffer.getChannelData(0)[s]=0;
buffer.getChannelData(1)[s]=0;
}
$("body").append("buffering<br/>");
};
$("body").html("");
mixerNode.connect(context.destination);
return false;
});
});
</script>
</head>
<body>
start
</body>
</html>
The above example works in Chrome as expected, but not in desktop Safari. The iOS version of Safari does not work either, but it never did work for me in the first place.
Calling context.createJavaScriptNode does return a proper object of type JavaScriptAudioNode and connecting it to the destination node does not throw any exceptions. context.activeSourceCount remains at zero, but this is also the case in Chrome as it apparently only counts active nodes of type AudioBufferSourceNode. context.currentTime also increments as expected.
Am I doing something wrong here or is this an actual bug or a missing feature in Safari? The Apple documentation has no mention of JavaScriptAudioNode (nor the new name, ScriptProcessorNode) but it did work before on the first release of Safari 6. The iOS Safari requirement for user input doesn't seem to help, as the example above should take care of that.
The simple example can be found here and a more complex one is my Protracker module player which exhibits the same behaviour.
There are a couple bugs in Safari's implementation of the Web Audio API that you'll need to look out for. The first is in the createJavaScriptNode constructor... it seems to have problems with the "input channels" param being set to 0. Try changing it to this:
createJavaScriptNode(2048, 1, 2)
The second issue has to do with garbage collection (I think); once your mixerNode variable is out of scope, Safari seems to stop firing the onaudioprocess callback. One solution is to introduce mixerNode at the top-level scope (i.e. declaring var mixerNode; at the top of your script) and then store your JavaScriptNode in that top-level variable. If you plan on dynamically creating multiple mixerNodes, you can achieve the same effect by storing references to them in a top-level array variable.
If you make these two changes (input channel param set to 1, maintaining a reference to the mixerNode) then your script should work in Safari as expected.

Catch video HTML5 play/stop event

How can I listen to the events play/stop/pause of a HTML5 video?
I tried with the following code:
$("video").on('play',function(){
//my code here
});
but it does not work.
Alternatively I would be fine also intercept the click that stop and start the video (in fact I would prefer), but even this code not works:
$('video').on('click', function(event) {
//my code here
});
I think because often above the video element is placed a div with associated events start and stop, but I do not know how to select via jQuery or Javascript:
P.S. This code should work on pages that are composed dynamically / not generated by me, so I can not refer the elements indicating their ID or a specific class.
UPDATE
I did not realize that the page on which I was testing had a video inside an iframe.
The syntax is best suited to my needs:
doc.querySelector("video").addEventListener('play', function(e) {
//my code here
}, true);
See here:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events
So... :
$("video")[0].onplay = function () {
// Do play stuff here
};
Hope that helps!
Your first attempt should work. But you need to make sure that jQuery is actually finding video elements. You say that the page is generated dynamically, so perhaps it's possible that your code is running before the video elements are added. This would also be the case if your script is higher up in the document than the video elements (e.g., in the <head>).
Try placing the following code immediately before the code you have there and check the output:
console.log($("video"));
If the output is an empty array, then you aren't finding any video elements. Try placing your script at the very end of the page or inside a DOMContentLoaded event. Or, if another script is generating the video elements, make sure your script runs after that one.
A few other notes on your question:
There is no stop event. Here's a list of media events.
I don't think the click event is what you want. That will fire no matter where on the video the user clicks: play button, volume control, etc.
The video being placed inside a div shouldn't have any effect on these events. I'm not sure why you'd have start and end events on a div, so maybe I'm not following.
Give this a try!
//Direct
<video id="videoThis" src="blahhh.mp4" onended="yourFunction()"></videoThis>
-or-
//JavaScript (HTML5)
document.querySelector("#videoThis").addEventListener("ended",yourFunction,false);
-or-
//jQuery
$("#videoThis").bind("ended",yourFunction);

All-in-one location/hashchange history management library

First of all, I know there's libraries that provide polyfills for location.pushState/popState (History.js, Hash.js, jQuery hashchange), so please don't just link to those.
I need a more powerful library to achieve the following in a RIA:
User clicks a link
library is notified and loads context via Ajax (no complete reload!)
All <a> elements are leveraged with a click handler that
prevents page reloads in 2. (preventDefault) and
calls location.pushState instead / sets location.hash for older browsers
loaded content is inserted in page and replaces current content
Continue with 1.
Also, previously loaded content should be restored as the user navigates back.
As an example, klick through Google+ in Internet Explorer <10 and any other browser.
Is there anything that comes even close? I need support for IE8, FF10, Safari 5 and Chrome 18. Also, it should have a permissive license like MIT or Apache.
I believe Sammy.js ( http://sammyjs.org) (MIT-licenced) has the best focus on what you want to do, with its 2 main pillars being:
Routes
Events
I could quote from the docs but it's pretty straightforward:
setup clientside routes that relate to stuff to be done, e.g: update the view through ajax
link events to call routes, e.g: call the route above when I click an link. (You would have to make sure e.preventDefault is called in the defined event I believe, since this is an app decision really, so that can't be abstracted away by any library that you're going to use imho)
Some relevant docs
http://sammyjs.org/docs
http://sammyjs.org/docs/routes
http://sammyjs.org/docs/events
Example for a route: (from http://sammyjs.org/docs/tutorials/json_store_1)
this.get('#/', function(context) {
$.ajax({
url: 'data/items.json',
dataType: 'json',
success: function(items) {
$.each(items, function(i, item) {
context.log(item.title, '-', item.artist);
});
}
});
});
Or something like
this.get('#/', function(context) {
context.app.swap(''); ///the 'swap' here indicates a cleaning of the view
//before partials are loaded, effectively rerendering the entire screen. NOt doing the swap enables you to do infinite-scrolling / appending style, etc.
// ...
});
Of course other clientside MVC-frameworks could be an option too, which take away even more plumbing, but might be overkill in this situation.
a pretty good (and still fairly recent) comparison:
http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/
( I use Spine.js myself ) .
Lastly, I thought it might be useful to include an answer I've written a while ago that goes into detail to the whole best-practice (as I see it) in client-side refreshes, etc. Perhaps you find it useful:
Accessibility and all these JavaScript frameworks
I currently use PathJS in one of my applications.
It has been the best decision that i have made.
For your particular usecase take a look at HTML5 Example.
The piece of code that that makes the example work (from the source):
<script type="text/javascript">
// This example makes use of the jQuery library.
// You can use any methods as actions in PathJS. You can define them as I do below,
// assign them to variables, or use anonymous functions. The choice is yours.
function notFound(){
$("#output .content").html("404 Not Found");
$("#output .content").addClass("error");
}
function setPageBackground(){
$("#output .content").removeClass("error");
}
// Here we define our routes. You'll notice that I only define three routes, even
// though there are four links. Each route has an action assigned to it (via the
// `to` method, as well as an `enter` method. The `enter` method is called before
// the route is performed, which allows you to do any setup you need (changes classes,
// performing AJAX calls, adding animations, etc.
Path.map("/users").to(function(){
$("#output .content").html("Users");
}).enter(setPageBackground);
Path.map("/about").to(function(){
$("#output .content").html("About");
}).enter(setPageBackground);
Path.map("/contact").to(function(){
$("#output .content").html("Contact");
}).enter(setPageBackground);
// The `Path.rescue()` method takes a function as an argument, and will be called when
// a route is activated that you have not yet defined an action for. On this example
// page, you'll notice there is no defined route for the "Unicorns!?" link. Since no
// route is defined, it calls this method instead.
Path.rescue(notFound);
$(document).ready(function(){
// This line is used to start the HTML5 PathJS listener. This will modify the
// `window.onpopstate` method accordingly, check that HTML5 is supported, and
// fall back to hashtags if you tell it to. Calling it with no arguments will
// cause it to do nothing if HTML5 is not supported
Path.history.listen();
// If you would like it to gracefully fallback to Hashtags in the event that HTML5
// isn't supported, just pass `true` into the method.
// Path.history.listen(true);
$("a").click(function(event){
event.preventDefault();
// To make use of the HTML5 History API, you need to tell your click events to
// add to the history stack by calling the `Path.history.pushState` method. This
// method is analogous to the regular `window.history.pushState` method, but
// wraps calls to it around the PathJS dispatched. Conveniently, you'll still have
// access to any state data you assign to it as if you had manually set it via
// the standard methods.
Path.history.pushState({}, "", $(this).attr("href"));
});
});
</script>
PathJS has some of the most wanted features of a routing library:
Lightweight
Supports the HTML5 History API, the 'onhashchange' method, and graceful degredation
Supports root routes, rescue methods, paramaterized routes, optional route components (dynamic routes), and Aspect Oriented Programming
Well Tested (tests available in the ./tests directory)
Compatible with all major browsers (Tested on Firefox 3.6, Firefox 4.0, Firefox 5.0, Chrome 9, Opera 11, IE7, IE8, IE9)
Independant of all third party libraries, but plays nice with all of them
I found the last too points most attractive.
You can find them here
I hope you find this useful.
i'd like to suggest a combination of
crossroads.js as a router
http://millermedeiros.github.com/crossroads.js/
and hasher for handling browser history and hash urls (w/ plenty of fallback solutions):
https://github.com/millermedeiros/hasher/
(based on http://millermedeiros.github.com/js-signals/)
This will still require a few lines of code (to load ajax content etc.), but give you loads and loads of other possibilities when handling a route.
Here's an example using jQuery (none of the above libraries require jQuery, i'm just lazy...)
http://fiddle.jshell.net/Fe5Kz/2/show/light
HTML
<ul id="menu">
<li>
foo
</li>
<li>
bar/baz
</li>
</ul>
<div id="content"></div>
JS
//register routes
crossroads.addRoute('foo', function() {
$('#content').html('this could be ajax loaded content or whatever');
});
crossroads.addRoute('bar/{baz}', function(baz) {
//maybe do something with the parameter ...
//$('#content').load('ajax_url?baz='+baz, function(){
// $('#content').html('bar route called with parameter ' + baz);
//});
$('#content').html('bar route called with parameter ' + baz);
});
//setup hash handling
function parseHash(newHash, oldHash) {
crossroads.parse(newHash);
}
hasher.initialized.add(parseHash);
hasher.changed.add(parseHash);
hasher.init();
//add click listener to menu items
$('#menu li a').on('click', function(e) {
e.preventDefault();
$('#menu a').removeClass('active');
$(this).addClass('active');
hasher.setHash($(this).attr('href'));
});​
Have you looked at the BigShelf sample SPA (Single Page Application) from Microsoft? It sounds like it covers how to achieve most of what you're asking.
It makes use of History.js, a custom wrapper object to easily control navigation called NavHistory and Knockout.js for click handling.
Here's an extremely abbreviated workflow of how this works: first you'll need to initialize a NavHistory object which wraps history.js and registers a callback which executes when there is a push state or hash change:
var nav = new NavHistory({
params: { page: 1, filter: "all", ... etc ... },
onNavigate: function (navEntry) {
// Respond to the incoming sort/page/filter parameters
// by updating booksDataSource and re-querying the server
}
});
Next, you'll define one or more Knockout.js view models with commands that can be bound to links buttons, etc:
var ViewModel = function (nav) {
this.search = function () {
nav.navigate({ page: 2, filter: '', ... }); // JSON object matching the NavHistory params
};
}
Finally, in your markup, you'll use Knockout.js to bind your commands to various elements:
<a data-bind="click: search">...</a>
The linked resources are much more detailed in explaining how all of this works. Unfortunately, it's not a single framework like you're seeking, but you'd be surprised how easy it is to get this working.
One more thing, following the BigShelf example, the site I'm building is fully cross-browser compatible, IE6+, Firefox, Safari (mobile and desktop) and Chrome (mobile and desktop).
The AjaxTCR Library seems to cover all bases and contains robust methods that I haven't seen before. It's released under a BSD License (Open Source Initiative).
For example, here are five AjaxTCR.history(); methods:
init(onStateChangeCallback, initState);
addToHistory(id, data, title, url, options);
getAll();
getPosition();
enableBackGuard(message, immediate);
The above addToHistory(); has enough parameters to allow for deep hash-linking in websites.
More eye-candy of .com.cookie(), .storage(), and .template() provides more than enough methods to handle any session data requirements.
The well documented AjaxTCR API webpage has a plethora of information with downloadable doc's to boot!
Status Update:
That website also has an Examples Webpage Section including downloadable .zip files with ready to use Front End(Client) and Back End(Server) project files.
Notably are the following ready-to-use examples:
One-way Cookie
HttpOnly Cookies
History Stealing
History Explorer
There are quite a bit other examples that rounds out the process to use many of their API methods, making any small learning curve faster to complete.
Several suggestions
ExtJs, see their History Example, and here are the docs.
YUI Browser History Manager.
jQuery BBQ seem to provide a more advanced feature-set over jQuery.hashcode.
ReallySimpleHistory may also be of help, though it's quite old and possibly outdated.
Note: ExtJs History has been extended to optimize duplicate (redundant) calls to add().
PJAX is the process you're describing.
The more advanced pjax techniques will even start to preload the content, when the user hovers over the link.
This is a good pjax library.
https://github.com/MoOx/pjax
You mark the containers which need will be updated on the subsequent requests:
new Pjax({ selectors: ["title", ".my-Header", ".my-Content", ".my-Sidebar"] })
So in the above, only the title, the .my-header, .my-content, and .my-sidebar will be replaced with the content from the ajax call.
Somethings to look out for
Pay attention to how your JS loads and detects when the page is ready. The javascript will not reload on new pages. Also pay attention to when any analytics calls get called, for the same reason.

JQuery UI progress bar not showing up until page loads fully

I'm loading a dynamic application (which takes 20-30 seconds), and I'm trying to create a dynamic progress bar that shows the user how much of the task has been completed dynamically as the page loads.
I'm accomplishing this by setting buffer to false and having my script output a line of JavaScript as it progresses that calls a function to increment the scrollbar:
function progress(percent)
{
$(function() {
$("#progressbar").progressbar({value: Math.round((percent*100))});
});
}
This is called by s simple function call like progress(15) generated by my page and sent realtime to the browser. A simple bar I made with css worked perfectly, but now that I'm trying to use jQuery it seems my progress bar is being incremented correctly but it won;t show up on the page until the page is done loading or the "stop" button is pressed. Any ideas why this is?
you're using the shorthand equivalent of the 'document.ready' notation $(function(){}); which only fires after the dom is loaded
if your function wasn't wrapped with that you'd be all set
i.e.
function progress(percent)
{
$("#progressbar").progressbar({value: Math.round((percent*100))});
}
Are you wrapping it in the $(document).ready( callback? If so that's the issue. $(document).ready won't run until the DOM has been loaded.
It could also be that if the page is loading it hasn't run the JS yet, or the #progressbar wasn't found in the DOM. This could be because you're calling the function before the #progressbar div is written.
Correct:
<div id="progressbar"></div>
<script type="text/javascript">/* Function call */</script>
Incorrect:
<script type="text/javascript">/* Function call */</script>
<div id="progressbar"></div>
I recommend making the page template (headers, footers, etc, everything that doesn't require a lot of server side processing) and then putting in the progressbar attached to a $.load AJAX call.