(Rails) Need some javascript assistance - ruby-on-rails

I currently have an application that calls creates and displays charts from various objects' data using JS. However, I'm having some severe issues. Can someone please explain why the following code works just fine when statically inserted into a page, but when used via rjs "page.replace_html my_div_id" it removes EVERYTHING ELSE on the page:
<script language="JavaScript" type="text/javascript">
<!--
if (AC_FL_RunContent == 0 || DetectFlashVer == 0) {
alert("This page requires AC_RunActiveContent.js.");
} else {
var hasRightVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);
if(hasRightVersion) {
AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,45,0',
'width', '800',
'height', '500',
'scale', 'noscale',
'salign', 'TL',
'bgcolor', '#777788',
'wmode', 'opaque',
'movie', 'charts',
'src', 'charts',
'FlashVars', 'library_path=xmlswfitems/charts_library&xml_source=xmlcharts/M1 Building One',
'id', 'my_chart',
'name', 'M1 Building One',
'menu', 'true',
'allowFullScreen', 'true',
'allowScriptAccess','sameDomain',
'quality', 'high',
'align', 'middle',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'play', 'true',
'devicefont', 'false'
);
} else {
var alternateContent = 'This content requires the Adobe Flash Player. '
+ '<u><a href=http://www.macromedia.com/go/getflash/>Get Flash</a></u>.';
document.write(alternateContent);
}
}
// -->
</script>
...also, it completely fails with IE. My only leads are from Safari ("unmatched embed tag"), Firefox (browser pretends chart never loads even though it has), IE (non-specific prototype.js error). FYI, I'm using XML/SWF Charts. I'm writing this code from scratch as I have needs not met by the existing/outdated SWFCharts library so please don't suggest solutions involving that particular library.
Best.

Use a standard library like SWFObject to embed your flash. It takes care of all the crossbrowser quirks for you and let's you do both static and dynamic publishing with regular html to fall back on if the user does not have flash.

AC_FL_RunContent uses document.write to generate the <object>/<embed> tags, which, if called after the page is completely loaded, replaces the entire contents of the page.
You will probably need to use SWFObject; as far as I know, it doesn't use document.write so it should work anytime.

Related

I can't get ckeditor to allow anything but basic attributes and can't turn off/ configure the advanced content editor (rails)

I am running ckeditor 4.1.4 on a ruby on rails app. The advanced content editor seems to be stripping anything other than basic attributes.
For example, if I have a word doc with 'this is a test' where 'is a test' is bold, red and 28 point and looking at the contents of the clipboard with clipview shows
<body lang=EN-US style='tab-interval:.5in'>
<!--StartFragment-->
<p class=MsoNormal>This <b style='mso-bidi-font-weight:normal'><span
style='font-size:28.0pt;line-height:107%;color:red'>is a test</span></b><o:p></o:p></p>
<p class=MsoNormal><o:p> </o:p></p>
<!--EndFragment-->
</body>
</html>
It would appear that it is picking up the color,size and bold attributes.
However, when I paste that into a text area using ckeditor and look at the source in ckeditor, I see
<p>This <strong>is a test</strong></p>
The attributes other than strong have been removed.
My body tag on the form is
<div class="field">
<%= f.label :body %><br>
<%= f.cktext_area :body, :rows => 80, :cols => 120 %>
</div>
I have gone into C:\Ruby200\lib\ruby\gems\2.0.0\gems\ckeditor-4.1.4\app\assets\javascripts\ckeditor\config.js and added
config.allowedContent = true;
config.extraAllowedContent = '*(*);*{*}';
config.removeFormatAttributes = '';
CKEDITOR.editorConfig = function( config )
{
// Define changes to default configuration here. For example:
I tried adding the three config lines inside the block and that didn't work. I read a suggestion about adding them outside the config block so I tried that. I did restart the server but it still strips out the additional attributes.
This is an intranet application and, given our situation, I'm not worried about content filtering. I just want the users to be able to copy and paste with all attributes.
------ edit 1
I looked at the source of the page and see
//<![CDATA[
(function() { if (typeof CKEDITOR != 'undefined') { if (CKEDITOR.instances['document_body'] == undefined) { CKEDITOR.replace('document_body', {"allowedContent":true}); } } else { setTimeout(arguments.callee, 50); } })();
//]]>
</script>
I'm not sure if the allowedContent statement should be working.
There are many ways to configure CKEditor, but the most simple one is passing object as a second parameter to CKEDITOR.replace (just as it's shown in your last piece of code).
However allowedContent: true can be not enough to enable pasting anything, because there are also paste filters in CKE, enabled in default in Chrome and Safari. If you're using that browser, CKE will strip off all classes, styles and div and span elements. To disable that behaviour, you should also pass pasteFilter option set to null:
var editor = CKEDITOR.replace( 'editor', {
allowedContent: true,
pasteFilter: null
} );
If you don't want to mess with configuring CKE, you can also disable paste filter on the fly:
editor.on( 'instanceReady', function() {
editor.pasteFilter.disable();
} );
However disabling that filter can lead to producing very messy HTML, so be warned!
More info about paste filter is available in official documentation.
---edit:
Note that if you are pasting mainly from Word, there are also configuration options dedicated for that case: pasteFromWordRemoveFontStyles and pasteFromWordRemoveStyles.

Rendering dynamic scss-files with ajax, rails

As the title suggests, my main objective is to render a dynamic scss(.erb) file after an ajax call.
assets/javascripts/header.js
// onChange of a checkbox, a database boolean field should be toggled via AJAX
$( document ).ready(function() {
$('input[class=collection_cb]').change(function() {
// get the id of the item
var collection_id = $(this).parent().attr("data-collection-id");
// show a loading animation
$("#coll-loading").removeClass("vhidden");
// AJAX call
$.ajax({
type : 'PUT',
url : "/collections/" + collection_id + "/toggle",
success : function() {
// removal of loading animation, a bit delayed, as it would be too fast otherwise
setTimeout(function() {
$("#coll_loading").addClass("vhidden");
}, 300);
},
});
});
});
controller/collections_controller.rb
def toggle
# safety measure to check if the user changes his collection
if current_user.id == Collection.find(params[:id]).user_id
collection = Collection.find(params[:id])
# toggle the collection
collection.toggle! :auto_add_item
else
# redirect the user to error page, alert page
end
render :nothing => true
end
All worked very smooth when I solely toggled the database object.
Now I wanted to add some extra spices and change the CSS of my 50+ li's accordingly to the currently selected collections of the user.
My desired CSS looks like this, it checks li elements if they belong to the collections and give them a border color if so.
ul#list > li[data-collections~='8'][data-collections~='2']
{
border-color: #ff2900;
}
I added this to my controller to generate the []-conditions:
def toggle
# .
# .
# toggle function
# return the currently selected collection ids in the [data-collections]-format
#active_collections = ""
c_ids = current_user.collections.where(:auto_add_item => true).pluck('collections.id')
if c_ids.size != 0
c_ids.each { |id| #active_collections += "[data-collections~='#{id}']" }
end
# this is what gets retrieved
# #active_collections => [data-collections~='8'][data-collections~='2']
end
now I need a way to put those brackets in a scss file that gets generated dynamically.
I tried adding:
respond_to do |format|
format.css
end
to my controller, having the file views/collections/toggle.css.erb
ul#list<%= raw active_collections %> > li<%= raw active_collections %> {
border-color: #ff2900;
}
It didn't work, another way was rendering the css file from my controller, and then passing it to a view as described by Manuel Meurer
Did I mess up with the file names? Like using css instead of scss? Do you have any ideas how I should proceed?
Thanks for your help!
Why dynamic CSS? - reasoning
I know that this should normally happen by adding classes via JavaScript. My reasoning to why I need a dynamic css is that when the user decides to change the selected collections, he does this very concentrated. Something like 4 calls in 3 seconds, then a 5 minutes pause, then 5 calls in 4 seconds. The JavaScript would simply take too long to loop through the 50+ li's after every call.
UPDATE
As it turns out, JavaScript was very fast at handling my "long" list... Thanks y'all for pointing out the errors in my thinking!
In my opinion, the problem you've got isn't to do with CSS; it's to do with how your system works
CSS is loaded static (from the http request), which means when the page is rendered, it will not update if you change the CSS files on the server
JS is client side and is designed to interact with rendered HTML elements (through the DOM). This means that JS by its nature is dynamic, and is why we can use it with technologies like Ajax to change parts of the page
Here's where I think your problem comes in...
Your JS call is not reloading the page, which means the CSS stays static. There is currently no way to reload the CSS and have them render without refreshing (sending an HTTP request). This means that any updating you do with JS will have to include per-loaded CSS
As per the comments to your OP, you should really look at updating the classes of your list elements. If you use something like this it should work instantaneously:
$('li').addClass('new');
Hope this helps?
If I understood your feature correctly, actually all you need can be realized by JavaScript simply, no need for any hack.
Let me organize your feature at first
Given an user visiting the page
When he checks a checkbox
He will see a loading sign which implies this is an interaction with server
When the loading sign stopped
He will see the row(or 'li") he checked has a border which implies his action has been accepted by server
Then comes the solution. For readability I will simplify your loading sign code into named functions instead of real code.
$(document).ready(function() {
$('input[class=collection_cb]').change(function() {
// Use a variable to store parent of current scope for using later
var $parent = $(this).parent();
// get the id of the item
var collection_id = $parent.attr("data-collection-id");
show_loading_sign();
// AJAX call
$.ajax({
type : 'PUT',
url : "/collections/" + collection_id + "/toggle",
success : function() {
// This is the effect you need.
$parent.addClass('green_color_border');
},
error: function() {
$parent.addClass('red_color_border');
},
complete: function() {
close_loading_sign(); /*Close the sign no matter success or error*/
}
});
});
});
Let me know if my understanding of feature is correct and if this could solve the problem.
What if, when the user toggles a collection selection, you use jquery change one class on the ul and then define static styles based on that?
For example, your original markup might be:
ul#list.no_selection
li.collection8.collection2
li.collection1
And your css would have, statically:
ul.collection1 li.collection1,
ul.collection2 li.collection2,
...
ul.collection8 li.collection8 {
border-color: #ff2900;
}
So by default, there wouldn't be a border. But if the user selects collection 8, your jquery would do:
$('ul#list').addClass('collection8')
and voila, border around the li that's in collection8-- without looping over all the lis in javascript and without loading a stylesheet dynamically.
What do you think, would this work in your case?

Right way to attach a jQuery-UI dateselect to a Zend Framework 2 form element?

What would be the right way to attach a jQuery-UI dateselect to a Zend Framework 2 form element?
Would it be adding a appendScript so a javascript selector is added to the end of the layout that selects the class/id?
First of all, i strongly suggest to go with the time and to start using Zend\Form\Element\Date. All browsers who do not support the Date-Input will still render out a Input of type="text", so there is literally no loss in doing so.
The advantage you do get is that most modern browsers are able to render out there default Datepicker. Using the browsers defaults is preferred for users usability and comfort. Even IE10 does do a very good job of supporting the current neat stuff of CSS3 and HTML5. But of course you can't be sure and so you should always include a fallback for older browsers, too. For this, I strongly suggest that you run with Feature-Detection in favor of blindly overwriting the users defaults. The library that does the job the best probably is Modernizr. I will give you the JS for that at the end.
Another thing to note is that this kind of JavaScript belongs at the BOTTOM of your document. For this you have to print this right before closing your </body>-Tag
<?=$this->inlineScript();?>
Now print the script you want inside the right place like this inside your $action.phtml
<?php $this->inlineScript()->captureStart(); ?>
Modernizr.load({
test: Modernizr.inputtypes.date,
nope: [
'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js',
'jquery-ui.css'
],
complete: function () {
$('input[type=date]').datepicker({
dateFormat: 'yy-mm-dd'
});
}
});
<?php $this->inlineScript()->captureEnd(); ?>
What's happeing there is that the Modernizr-library will check for the browser support of the Date-Input of HTML5. If the browser is not able to render out a DateSelect, the appropriate JavaScript-Libraries will be loaded (jQuery, jQueryUI and CSS) and attached to the DOM and the jQueryUI.datepicker() will be called to your input-elements of type date.
In addition, all of this JS-Stuff will be captured and moved to the END of your DOM (where a script element will be added). Doing this you have the advantage that first the full DOM will be rendered and then the JS will be attached. Meaning your Form is usable sooner than in the example provided by Raj.
Based on the 2 answers, I did a bit more research and came up with my own approach...
Here is the top of my layout.phtml
$this->inlineScript()->offsetSetFile(10,$basePath . '/jquery/jquery-1.10.1.min.js');
$this->inlineScript()->offsetSetFile(12,$basePath . '/jquery-ui/ui/jquery-ui.min.js');
I have assigned all my javascripts with an ID so they are all loaded in the right order.
I then use this in my Form... by default it looks like any form element has the ID set to its name, this makes ite easy to style with input#name
$this->add(array(
'name' => 'start',
'type' => 'DateTime',
'options' => array(
'label' => 'Start Date',
'format' => 'Y-m-d H:i P',
),
));
Its then very easy to style with the following, here is my $action.phtml ...
echo $this->form($form);
# Decorations
$this->inlineScript()->offsetSetScript(99,"
$(function() {
$('input#start').datepicker({
dateFormat: 'yy-mm-dd',
showOtherMonths: true,
selectOtherMonths: true,
});
});
");
You can see here I have assigned it offset 99. This is what I use in all my templates.

Need help using jQueryUi in Plone

I'm new to Plone and jQueryUI, and have not been able to get any jQueryUI working on a Plone page.
I installed Plone 4 (4.1.4 41143) and jQueryUI 1.8.16 (http://plone.org/products/collective.js.jqueryui),
Under Zope Management Interface > portal_javascripts, collective.js.jqueryui.custom.min.js is present and enabled.
To try to implement the example from http://jqueryui.com/demos/button/, I placed in the body text of a Plone page:
<script type="text/javascript">
jQuery({function($) {
$( "input:submit, a, button", ".demo" ).button();
$( "a", ".demo" ).click(function() { return false; });
});
</script>
<DIV class=demo>
<BUTTON type=submit>A button element</BUTTON> <INPUT value="A submit button" type=submit> An anchor
</DIV><!-- End demo -->
but the resulting page does not show the expected result.
I've tried replacing "jQuery" in the code above with "$", "collective.js.jqueryui.custom.min", but nothing has worked yet.
I was able to get some jQueryUI working outside of Plone, but would be interested in knowing how to use it within Plone. Any help appreciated.
The content of your script tags is probably being deleted by Plone's HTML filtering.
You can change that in "Site Setup", "HTML Filtering". (The dialog there is confusing, you have to click two buttons. First remove from 'nasty tags', then 'save' at the bottom of page.)
Be aware though, that there are good security reasons for not allowing users to use script, embed and other tags. It can lead to all kind of trouble, for instance when they are also allowed in comments, or less experienced users copy/paste dangerous code.
If you're just practicing, and not putting your site on the big bad Internet, it can be fine, but if you start deploying a real site it is much better to put script stuff into page templates of your own file-based add-on product.
Your syntax within the script tag is incorrect. Try this:
jQuery(function($) {
$( "input:submit, a, button", ".demo" ).button();
$( "a", ".demo" ).click(function() { return false; });
})($);​
Yes, you may need to allow script tags as described above, but the example still did not work for me until I replaced the word jQuery with the $ sign, at least when using collective.js.jqueryui 1.8.16.9 on Plone 4.2.1.1.
<script>
$(function() {
$( "#progressbar1" ).progressbar();
$( "#slider" ).slider();
$( "input:submit, a, button", ".demo" ).button();
$( "a", ".demo" ).click(function() { return false; });
});
</script>
Putting ($) just before the semicolon on the line above also worked but I saw no difference.
The script worked on a file system page template even when script was included in the "nasty tags" list. Also, the script can be inserted into the document's head with the following in a page template:
<metal:slot fill-slot="javascript_head_slot">
<script>
$(function() {
$( "#slider" ).slider();
$( "#progressbar1" ).progressbar();
$( "input:submit, a, button", ".demo" ).button();
$( "a", ".demo" ).click(function() { return false; });
});
</script>
</metal:slot>
(I'd love to hear if there is a more appropriate prefix, but I don't really know javascript.)
I've just had a similar issue trying to get my scripts and jquery UI to work with a plone/zope setup. The solution was to register them in the javascript registry (/portal_javascripts).
The scripts themselves were added to /portal_skins/custom which is also where the homepage I was working on resides.
Script tags are filtered out from the source as already mentioned above, and the scripts from the registry automatically added instead.
Keep in mind also that order is important in the javascript registry.
Hope this is of some help to other users who come across this question,.

sIFR3 show text while loading

I am using sIFR3 on a website. I remember in sIFR2 you coul use this sIFR.bHideBrowserText = false; to show the text before sIFR kicks in.
How do you do this in sIFR3 and where do you put the code?
Thanks for your help.
C
The feature as it existed in sIFR 2 no longer exists in sIFR 3. You could achieve the same affect like this, though:
sIFR.autoInitialize = false;
sIFR.activate(movie);
sIFR.removeFlashClass();
sIFR.replace(movie, { selector: 'h1' });
window.onload = function(){
sIFR.setFlashClass();
sIFR.initialize();
};
Where, of course, movie is the appropriate variable that references the Flash movie. You might want to connect to the onload event through another JavaScript framework. You must wait until full page load, things like $(document).ready() (jQuery) will not work reliably cross-browser.

Resources