Bookmarklet to change the arbitrary value of a JSON config - javascript

I'm working on changing the UX of a proprietary, heavily obfuscated and tamper-proof web application, so I can't nip this in the bud at server level; I'm limited to the sandbox of my browser and bookmarklets.
A page loads up main code (<script preload>) and user config (<script defer>) in two separate queries. I would like for a setting in the user config to have a different value than what the server sends.
Doing it for myself, I could tamper with the config before it even arrives in the browser, but I have to make this work reliably for other users as well, without having them to install a whole bunch of stuff like Greasemonkey, Fiddler, whatever.
I've tried two equally inefficient approaches:
When the page starts loading, execute this and hope I win the race:
{
var loadedConf = document.getElementById("user").innerHTML;
if(typeof loadedConf === "undefined")
{
setTimeout(raceReplace, 5);
rantime += 5;
}
else
{
document.getElementById("user").innerHTML = loadedConf.replace(/arbitraryConfigField":false/,
'arbitraryConfigField":"arbitraryConfigValue"');
console.log("Raced to a finish in " + rantime + "ms")
}
}
raceReplace()
Because it's a race, it's wholly contingent upon how fast a user clicks the bookmarklet. With practice, I can do it almost 50% of the time! Heh.
Extend JSON.parse to make it return an object as it normally would, the way God and Douglas Crockford intended, except an arbitrary key/value:
JSON.parse = (text, fn) => {
const result = parse(text, fn)
if (result && result.arbitraryConfigField) {
result.arbiraryConfigField = 'arbitraryConfigValue'
}
return result
}
A better approach, but also prone to racing and could hinder regular JSON.parse performance.
(I'm wondering if performance-wise it wouldn't be better to just do a text.replace without any checking.)
Is there yet a third way to wait for the page to load, hook into it and on a subsequent reload (which, yes, necessarily re-renders everything) have the necessary value without the hassle and uncertainty of a race?
It would be grear to have this without the heavy artillery of designing a Chrome extension or hooking with Greasemonkey.

Related

Preload multiple (798) audio files in Chrome

I making a game and I want to load 798 sound files, but there is a problem only in Chrome, Firefox fine. Sample code: https://jsfiddle.net/76zb42ag/, see the console (press F12).
Sometimes script loads only 100, 500, 700 files, sometimes is fine. If i reduce the number of files to ex. 300 is ok (always). How can I solve this problem? I need a callback or any ideas? The game will be offline (node webkit).
Javascript code :
var total = 0;
// sample file to download: http://www.sample-videos.com/audio/mp3/crowd-cheering.mp3
// sounds.length = 798 files
var sounds = [
(...limit character, see https://jsfiddle.net/76zb42ag/...)
];
for (var i in sounds) {
load(sounds[i]);
}
function load(file) {
var snd = new Audio();
snd.addEventListener('canplaythrough', loadedAudio, false);
snd.src = file;
}
function loadedAudio() {
total++;
console.log(total);
if (total == sounds.length){
console.log("COMPLETE");
}
}
This isn't really a code problem. It's a general architecture problem.
Depending not only on the number, but also the size of the samples, it's going to be unlikely you can get them all loaded at once. Even if you can, it'll run very poorly because of the high memory use and likely crash the tab after a certain amount of time.
Since it's offline, I would say you could even get away with not pre-loading them at all, since the read speed is going to be nearly instantaneous.
If you find that isn't suitable, or you may need like 5 at once and it might be too slow, I'd say you'll need to architect your game in a way that you can determine which sounds you'll need for a certain game state, and just load those (and remove references to ones you don't need so they can be garbage collected).
This is exactly what all games do when they show you a loading screen, and for the same reasons.
If you want to avoid "loading screens", you can get clever by working out a way to know what is coming up and load it just ahead of time.

JavaScript: Like-Counter with Memory

Complete - Edited Once
I am looking to create a Like Counter with persistent Memory!
Right now, my project is stored on a USB-Drive and I'm not thinking of uploading my semi-finished site to the Internet just yet. I'm carrying it around, plugging and working.
A feature of the site, is a Heart Counter and Like Counter, respective with their symbolic icons.
I have a little sideline JavaScript file that has a dozen functions to handle the click-events and such - such as the Number Count of the counters.
But, as the values of the counters are auto-assigned to Temporary Memory - if you were to reload the page - the counter number would reset to it's default, Zero. A huge headache...
Reading from .txt
I thought of using the experimental ReadFile() object to handle the problem - but I soon found that it needed a user-put file to operate (from my examinations).
Here's my attempt:
if (heartCount || likeCount >= 1) {
var reader = new FileReader();
var readerResults = reader.readAsText(heartsAndLikes.txt);
//return readerResults
alert(readerResults);
}
When loaded, the page runs through standard operations, except for the above.
This, in my opinion, would have been the ideal solution...
Reading from Cookies
Cookies now don't seem like an option as it resides on a per-computer basis.
They are stored on the computer's SSD, not in the JavaScript File... sad...
HTML5 Web Storage
Using the new Web Storage will be of big help, probably. But again, it is on a per-computer basis, no matter how beautiful the system is...
localStorage.heartCount = 0 //Originally...
function heartButtonClicked() {
if (localStorage.heartCount) {
localStorage.heartCount = Number(localStorage.heartCount) + 1
}
document.getElementById('heartCountDisplay').innerHTML = localStorage.heartCount
} //Function is tied to the heartCountButton directly via the 'onclick' method
However, I am questioning whether web storage can be carried over on a USB-Drive...
Summarised ideas
Currently, I am looking to Reading and Editing the files, as it's most ideal to my situation. But...
Which would you use? Would you introduce a new method of things?
Please, tell me about it! :)
if (typeof(Storage) !== "undefined") { //make sure local storage is available
if (!localStorage.heartCount) { //if heartCount is not set then set it to zero
localStorage.heartCount = 0;
}
} else {
alert('Local storage is not available');
}
function heartButtonClicked() {
if (localStorage.heartCount) { //if heartCount exists then increment it by one
localStorage.heartCount++;
}
//display the result
document.getElementById('heartCountDisplay').innerHTML = localStorage.heartCount
}
This will only work on a per computer basis and will not persist on your thumb drive. The only way I can think of to persist the data on your drive is to manually download a JSON or text file.

Click counter without javascript

I'm using this javascript for a click counter in my blogger blog:
function clickCounter() {
if(typeof(Storage) !== "undefined") {
if (sessionStorage.clickcount) {
sessionStorage.clickcount = Number(sessionStorage.clickcount)+1;
} else {
sessionStorage.clickcount = 1;
}
document.getElementById("result").innerHTML = "Correct! " + sessionStorage.clickcount + " Smart answers 'til now.";
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support this quiz...";
}
}
<button onclick="clickCounter()" type="button">Suspension</button>
Is there any way to create something similar through a non javascript method?
Can you help me triger an event (extra text message through popup or within the page) every 5, 10, 20, 100 clicks?
Thank you very much
HTML, and the Web in general, was designed to be stateless.
When you pull up a page, it should be like the first time -- and every time -- you pull up the page.
Since then, people have come up with a number of techniques to add state -- to save data, but they all involved one of two methods -- or sometimes both.
Method 1: Store state on the server.
This method uses HTML forms or cookies to slip information to the server when you load and reload a page.
Method 2: Store state in the client
While there are some older versions of Internet Explorer that can be coded in VBA, we are going to ignore that. The only "real" way to run any kind of code on the client, to store any data, is to use JavaScript.
Method 3: Use the client to talk to the server
Using Ajax, you can let your client talk to the server, but without doing a page reload. This still uses JavaScript.
So, to answer your question:
Without a server
Without JavaScript
No, you cannot save or store anything.
I have not tried this but...
What if you put multiple buttons positioned on top of each other. As each one is clicked, it can be made to vanish with something like
a:visited { display: none; }
The ones that need to display a message (5th, 10th, etc.) have different behavior attached.
See on click hide this (button link) pure css

Efficient scrolling of piped output in a browser window

I have a custom browser plugin (built with FireBreath) that will invoke a local process on a users machine and pipe stdout back to the browser, to do this i'm running the process through a popen() call and as I read data from the pipe I fire a JSAPI event and send it back to the browser.
In the browser I append the output to a div as pre-formatted text and tell the div to scroll to the bottom.
Code in the browser plugin:
FILE* in;
if(!(in = _popen(command_string, "r")))
{
return NULL;
}
while(fgets(buff, sizeof(buff), in)!=NULL)
{
send_output_to_browser(buff);
}
HTML & Javascript/jQuery:
<pre id="sync_status_window" style="overflow:scroll">
<span id="sync_output"></span>
</pre>
var onPluginTextReceived = function (text)
{
$('#sync_output').append(text);
var objDiv = document.getElementById('sync_status_window');
objDiv.scrollTop = objDiv.scrollHeight;
}
This method works for the browsers I need it to (this is a limited use internal tool), but it's frustratingly laggy. My process usually finishes about 30-60 seconds before the output window finishes scrolling. So, how do I make this more efficient? Is there a better way to pipe this text back to the browser?
There are two optimizations I see potential in:
keep a reference to your pre and span, you keep repeating the dom
tree search , which is quite costly
Chunk up the output - either on the C side (preferable) or on the JS
side.
For quick hack (without removing dependency on jquery, which should be done) could look like
//Higher or global scope
var pluginBuffer=[];
var pluginTimeout=false;
var sync_status_window=document.getElementById('sync_status_window');
function onPluginTextReceived(text)
{
pluginBuffer[pluginBuffer.length]=text;
if (!pluginTimeout) pluginTimeout=window.SetTimeout('onPluginTimer();',333);
}
function onPluginTimer()
{
var txt=pluginBuffer.join('');
pluginBuffer=[];
pluginTimeout=false;
$('#sync_output').append(text);
sync_status_window.scrollTop = sync_status_window.scrollHeight;
}
Adapt to your needs, I chose 333ms for 3 updates/second

What does your .conkerorrc look like?

Conkeror has changed the way I browse the web: it's basically Emacs + Firefox with javascript based configuration in .conkerrorc rather than elisp configuration in .emacs.
I've built up a huge library of .emacs customizations over the years by getting little bits and pieces from others. I'm just starting with Conkeror but the fact that it uses JS (far more widely known than Elisp) must mean that there's some amazing stuff out there.
Care to share your pieces? I'm particularly interested in stuff that interacts well with pages produced by Django (or other dynamic web pages).
For example, I'd love a Conkeror-based action recorder that let me browse a site and find bugs, and then immediately save & submit the sequence of actions as a bug report with a single keystroke. By including the JS actions required to replicate the error, it would be the ultimate testing harness -- even better than Selenium because it would be totally keyboard driven.
Here's mine:
// homepage = "http://www.google.com";
// set default webjump
read_url_handler_list = [read_url_make_default_webjump_handler("google")];
// possibly valid URL
function possibly_valid_url (str) {
return (/[\.\/:]/.test(str)) &&
!(/\S\s+\S/.test(str)) &&
!(/^\s*$/.test(str));
}
// page modes
require("page-modes/google-search-results.js"); // google search results
require("page-modes/wikipedia.js"); // wikipedia mode
// webjumps
define_webjump("gmail", "https://mail.google.com"); // gmail inbox
define_webjump("twitter", "http://twitter.com/#!/search/%s", $alternative = "https://twitter.com/"); // twitter
define_webjump("w3schools", "http://www.w3schools.com"); // w3schools site
define_webjump("w3search", "http://www.google.com/search?sitesearch=www.w3schools.com&as_q=%s"); // w3schools search
define_webjump("jquery", "http://docs.jquery.com/Special:Search?ns0=1&search=%s"); // jquery
define_webjump("archwiki", "https://wiki.archlinux.org/index.php?search=%s"); // arch wiki
define_webjump("stackoverflow", "http://stackoverflow.com/search?q=%s", $alternative = "http://stackoverflow.com/"); // stackoverflow
define_webjump("sor", "http://stackoverflow.com/search?q=[r]+%s", $alternative = "http://stackoverflow.com/questions/tagged/r"); // stackoverflow R section
define_webjump("stats", "http://stats.stackexchange.com/search?q=%s"); // stats
define_webjump("torrentz", "http://torrentz.eu/search?q=%s"); // torrentz
define_webjump("avaxsearch", "http://avaxsearch.com/avaxhome_search?q=%s&a=&c=&l=&sort_by=&commit=Search"); // avaxsearch
define_webjump("imdb", "http://www.imdb.com/find?s=all;q=%s"); // imdb
define_webjump("duckgo", "http://duckduckgo.com/?q=%s", $alternative = "http://duckduckgo.com"); // duckduckgo
define_webjump("blekko", "http://blekko.com/ws/%s", $alternative = "http://blekko.com/"); // blekko
define_webjump("youtube", "http://www.youtube.com/results?search_query=%s&aq=f", $alternative = "http://www.youtube.com"); // youtube
define_webjump("duckgossl", "https://duckduckgo.com/?q=%s"); // duckduckgo SSL
define_webjump("downforeveryoneorjustme", "http://www.downforeveryoneorjustme.com/%s"); // downforeveryoneorjustme
define_webjump("urbandictionary", "http://www.urbandictionary.com/define.php?term=%s"); // urban dictionary
define_webjump("rts", "http://rts.rs"); // RTS
define_webjump("facebook", "http://www.facebook.com"); // facebook homepage
// tab bar
require("new-tabs.js");
// clicks in new buffer
require("clicks-in-new-buffer.js");
// Set to either OPEN_NEW_BUFFER(_BACKGROUND)
clicks_in_new_buffer_target = OPEN_NEW_BUFFER_BACKGROUND; // Now buffers open in background.
// history webjump
define_browser_object_class(
"history-url", null,
function (I, prompt) {
check_buffer (I.buffer, content_buffer);
var result = yield I.buffer.window.minibuffer.read_url(
$prompt = prompt, $use_webjumps = false, $use_history = true, $use_bookmarks = false);
yield co_return (result);
});
interactive("find-url-from-history",
"Find a page from history in the current buffer",
"find-url",
$browser_object = browser_object_history_url);
interactive("find-url-from-history-new-buffer",
"Find a page from history in the current buffer",
"find-url-new-buffer",
$browser_object = browser_object_history_url);
define_key(content_buffer_normal_keymap, "h", "find-url-from-history-new-buffer");
define_key(content_buffer_normal_keymap, "H", "find-url-from-history");
// load session module
require("session.js");
session_auto_save_auto_load = true; // auto-load session
// don't open download buffer automatically
remove_hook("download_added_hook", open_download_buffer_automatically);
// don't show clock
remove_hook("mode_line_hook", mode_line_adder(clock_widget));
// add favicons
require("favicon");
add_hook("mode_line_hook", mode_line_adder(buffer_icon_widget), true);
read_buffer_show_icons = true;
// add content handlers
content_handlers.set("application/pdf", content_handler_save); // pdf
// torrent
// mp3
// ogg
function define_switch_buffer_key (key, buf_num) {
define_key(default_global_keymap, key,
function (I) {
switch_to_buffer(I.window,
I.window.buffers.get_buffer(buf_num));
});
}
for (let i = 0; i < 10; ++i) {
define_switch_buffer_key(String((i+1)%10), i);
}
function enable_scrollbars (buffer) {
buffer.top_frame.scrollbars.visible = true;
}
add_hook("create_buffer_late_hook", enable_scrollbars);
Since no one else seems interested in posting an actual reply, I will.
function my_title_format (window) {
return 'conkeror {'+get_current_profile()+'}'+window.buffers.current.description;
}
I find it helpful to have the profile name in the window title as I use multiple profiles. It doesn't help me so much now that I use StumpWM and don't look at the window list much, but it's very helpful in other window managers.
define_key(content_buffer_normal_keymap, "C-x C-c", "confirm-quit");
can_kill_last_buffer = false;
These two keep me from accidentally closing a conkeror window by closing the last buffer.
Well, I can't really help you here but I just wanted to say that although I'm an emacs guy, I dropped Conkeror for vimperator because IMHO the browsing experience is much better!
Conkeror is merely Firefox with Emacs keybindings. I don't think it is, and nor does it intend to be, a fully featured environment as Emacs is.
It facilitates your browsing experience by allowing you to use your well-worn Emacs muscle memory. And lets you keep your hands on the keyboard more, instead of jumping from keyboard to mouse all the time.
So I don't think it is really capable of doing some of the things you imagine.
Its development is also rather slow and is probably understaffed. You'll find, for example, that you can't use most common Firefox addons/extensions with it. Firebug, Greasemonkey, Gears, etc.
I do like it for some browsing tasks: it has special modes for reading Reddit, Google Reader, and others that make things a lot easier.
But I also agree with binOr that vimperator is much better, even if you're an emacs guy. Helps if you use VIM of course.

Categories

Resources