Rails 3.1 loads scripts before the page is loaded. How to bind functions to page elements? - rails-3.1

Putting this code in
$('#hello').click ->
alert 'hello'
in posts.js.coffee in vanilla Rails 3.1 app does not work. The javascript is compiled and loaded before the page so the function isn't bound to its element. There are easy solutions, like manually loading the js on the page rather than using the asset pipeline, or using JQuery .live functions, but it seems like this code should work out of the box. Am I missing something??

I might be pointing out the obvious here, but have you (in jQuery) tried this:
$(function(){
//your code
$('#hello').click(function(){
alert("hello");
});
});
or
$(document).ready(function(){ [...] });
These (atleast under normal circumstances) should prevent any javascript inside from doing anything until the DOM has been loaded.
Hope this helps

Related

Polymer override script loaded by HTML import

Is it possible to access a (Polymer) web component's dependency (also a component) which the only thing it does is load a js script, and override that with another (newer version in my case) script?
Concrete problem: I'm using various Polymer elements (say paper-dialog for example) which use neon-animation whose different animations all import the web-animations HTML which loads the script I want to override.
In other words I would like to perform something like what the /deep/ combinator does for CSS to penetrate into this specific HTML 'component' and add a newer version of the web-animations-next-lite.min.js script.
As for the why: the idea is to use a Chrome extension to perform this since remote update is not an option (internet connectivity limitations). I need to do this since with Chrome v54 our app "broke" (since we use an older web-animations version) by fixing the WebAnimations API so these errors broke animations and with that functionality (popups not appearing).
I already tried injecting the newer version script in my main HTML body with Chrome extension's content script but didn't have any luck there..
Thanks in advance for any ideas!
I know its a bit of a hack, but can't you just put your own version of the web-animations script in bower_components. The problem with trying to alter the polymer element in place is that it will have already loaded the script before you can get at it.
Listen to the load event on you HTML Imports <link>, then add a <script> element with the right src attribute.
It's this last downloaded (and parsed) script that will be taken in account.
<script>
function loaded() {
//file.html loaded
document.write( '<script src="new-file.js"></script>' )
}
</script>
<link rel=import href="file.html" onload="loaded()">

Injecting inline svg with ajax and reloading browser issue

I'm using the following script to inject a svg in my html body:
Meteor.startup(function() {
$('body').prepend('<div id="svg"></div>');
$('#svg').load('images/svg/sprite/sprite.svg');
});
This works as intended but things go wrong when I manually reload the page in my browser. But only when there's a parameter in my route. When there's no paramater in my route I can refresh all I want without any problems.
Router.route('/test') // all OK!
Router.route('/test/:_id') // current template gets rendered multiple times and app finally crashes
I can't seem to wrap my head around this. Why is this happening? And how to fix this?
The load path needs to be absolute.
$('#svg').load('/images/svg/sprite/sprite.svg');

Using chrome.runtime.sendMessage in an imported javascript file

I'm currently using jQuery's $.getScript within my content script to import more Javascript files into my content script. This works very well for me to get all my Javascript files imported, but I am running into an issue where I can't use chrome.runtime.sendMessage inside the imported javascript files to communicate with my background scripts, presumably because the function isn't recognized within a script that's been processed by $.getScript (please do correct me if I'm wrong).
In content.js (injected directly via the manifest file), I have the following code:
$.getScript(chrome.extension.getURL('js/angular-1.2.26-min.js'), function(data) {
$.getScript(chrome.extension.getURL('app/app.js'), function(data) {
$.getScript(chrome.extension.getURL('app/overview/overview-controller.js'), function(data) {
$.getScript(chrome.extension.getURL('js/angular-bootstrap.js'), function(data) {
})
})
})
})
And inside app/app.js (or any of the injected files), I try putting a sendMessage call anywhere, but nothing gets sent. (I log the onMessage event listener in the background)
chrome.runtime.sendMessage({msg: 'test'}, function(response) { alert('done') })
Note: I have also tried importing the Javascript files by sending a message to the background script to use chrome.tabs.executeScrip instead, but I need to be able to inject the javascript files only at a specific time and in a specific frame, so that doesn't help. I've also tried using the 3rd party executeScriptInFrame library but that doesn't seem to be working either. I run into "Blocked script execution in '{{URL}}' because the document's frame is sandboxed and the 'allow-scripts' permission is not set"
My questions:
Is there an effective solution to using chrome.runtime.sendMessage inside a script that's been injected using $.getScript?
Is there a way to use executeScript inside a content script?
Is there an effective way to inject content scripts into a particular frame? Again, from above -- I tried a third party library but ran into an issue regarding the frame's sandboxing. But this is strange since I am able to successfully inject content scripts to that frame when using the manifest to do it directly.
Thanks!
Well, that's an interesting question.
Most methods rely <script> injection, which adds code to the wrong (page) context that has no access to Chrome APIs. I assume this is how $.getScript works. So, this will not work as intended.
Another method is using eval(). According to the documentation, eval() is allowed (but discouraged) in Content Scripts. So you can, in principle, load the script file in a XHR / jQuery AJAX request and then eval() its contents. This should work.
Lastly, you could modify your content scripts only to execute if some condition is met (say, a variable is set), and so injecting into all frames of a tab should be less of a problem. This could potentially be messy though. Note that a content script can find itself in the iframe hierarchy, which may be useful.

Select2 multi-value: How to refresh

I'm using ajax in Rails 4 to load this form. Using select2-rails gem, it renders properly when the document loads:
After I click update, it loads the view partial:
but when I click on edit, the styling doesn't show up, and only the default bootstrap styling shows up:
How do I get this last image to show the select2 styling from the first image? I think it has to do with how select2 styling is loaded when the document is first loaded, but would appreciate a solution. Here is my stylesheet below:
$(document).ready(function(){
$("#e9").select2();
})
Allen:
Hello again by the way...
I had a similar problem in rails 4 and it had to do with turbolinks.
link: http://guides.rubyonrails.org/working_with_javascript_in_rails.html#how-turbolinks-works
In your JS file change your document ready to the function name below, then add the two commands just below the function, which are also below. This may be your issue as well because your page initially loads correctly, however when turbolinks is working, it tries to load only previously loaded files to quicken the load process and may skip your document ready function. Let me know if this helps... (Jake - DBC).
var select2Gem = function(){
$("#e9").select2();
};
$(document).ready(select2Gem);
$(document).on('page:load', select2Gem);

chrome content script to access and modify window

I am writing a chrome extension that is a 'content script'
I want to inject a google map on to a webpage.
Problem:
It appears that i have no way to add functions on to the window object, thus i cannot define a callback function for googlemaps to call when it loads.
How do people usually go about mucking with the window?
--
someone on the interwebs suggested i do this:
You can do this easily with a JavaScript URL: window.location =
"javascript:obj.funcvar = function() {}; void(0);"
but when i did this i got an access denied error. it seems like a lot of search results about this problem are outdated.
Content scripts have a separate JavaScript execution ennvironment from the page they run on, so they cannot alter JS variables in the page itself. However, the content script shares the DOM with the page, so you can inject a <script> tag into the DOM which will be loaded and run in the actual page's execution environment.

Resources