Help support.
http://area51.stackexchange.com/proposals/38817/marijuana?referrer=tkBgR7lUv1hXGK1vDNNwZw2
Help diffuse the myths. Sign up on stackexchange then follow the proposal. If we get 60 followers, we get into the next phase of becoming a full-blown Q&A site. Click here for FAQ
My latest project - Hyperion
The Git/FTP/SSH/IceCAST/Rails/Samba Server
One of my clients’ site, Gnartifact.com, is undergoing a full overhaul currently and occupies a lot of my free time. I figure it deserves the occasional blog for updates.
Firstly,
Gnartifact is getting a brand new video archiving form. Before, the site grabbed a lot of data from the Vimeo and YouTube APIs from the Rails backend. In this version, all API calls are done client-side using jQuery. This increases performance and accuracy of archiving.
Select default thumbnails is now even easier as you can now upload your own thumbnails, and all past thumbnails are saved to be chosen from at any point. Customization is the name of the game for this version. Paperclip still powers image uploading.
With the addition of many more video attributes, the archive form is broken into tabs. This makes organization and user workflow much simpler, and makes it easy to enable or disable features on the fly.
Major changes is the upgrade to Rails 3.1 from Rails 2.3. Production server will run on Phusion Passenger instead of a Mongrel cluster. Hosting company will be switched to my own reseller account. RVM is implemented now right in development. A local Git server and Capistrano will be used for deployment. The complete custom administrative end has been replaced with the ActiveAdmin gem, which I really recommend you check out.
As always, NewRelic will be used for server monitoring.
More updates to come soon
http://www.gnartifact.com
http://code.google.com/apis/youtube/overview.html
http://vimeo.com/api
https://github.com/thoughtbot/paperclip
http://activeadmin.info/
I’m getting started with my first official jQuery plugin, and I’m just turning now looking for input. I want to know what I’m doing wrong or right so far and if everything is being developed in a manner that won’t cause issue down the road. With no further adieu:
$.fn.heftyBox = function(args) {
if ($(this).length) {
//Set up defaults
var a = $.extend({
type : "checkbox",
width : "auto",
height : ($(this).innerHeight() > 150) ? $(this).innerHeight() : 150
}, args);
//Gather original attributes, convert DOM, then reassgign attributes
var attributes = $(this)[0].attributes;
var optionsHTML = $(this).html();
$(this).after('<ul id="tmpul">' + optionsHTML + '</ul>');
$(this).remove();
var ul = $('#tmpul')[0];
for (var i = 0; i < attributes.length; i++) {
$(ul).attr(attributes[i].name, attributes[i].value);
}
//Convert options to checkbox or radios
var options = $(ul).children('option');
var name = $(ul).attr('name');
$(ul).removeAttr('name');
var f = 0;
$.each(options, function(key, option) {
var itemAttributes = $(this)[0].attributes;
var value = $(this).attr('value');
var label = $(this).text();
var selected = $(this).attr('selected') ? "checked" : ''
selected += $(this).attr('disabled') ? " disabled" : ''
var newLi;
$(this).replaceWith(newLi = $('<li ' + selected + '><input type="' + a.type + '" id="option_' + name + '_' + f + '" name="' + name + '" value="' + value + '" ' + selected + '/><label for="option_' + name + '_' + f + '">' + label + '</label></li>') )
for (var i = 0; i < itemAttributes.length; i++) {
$(newLi).children('input').attr(itemAttributes[i].name, itemAttributes[i].value);
}
f++;
})
//Add Filter Box
$(ul).before('<input id="' + name + '_filter" class="list_filter" />');
var list = $(ul).children('li');
var filter = $('#' + name + '_filter');
filterBox($(filter), list);
//Contain it all
$(filter).before('<div class="heftyBox" id="' + name + '_container"></div>');
var container = $('#' + name + '_container');
$(filter).appendTo($(container));
$(ul).appendTo($(container));
//Select all box for checkboxes
if (a.type == "checkbox") {
$(filter).after($('<a href="#">Select All</a>').bind('click', function() {
var checkboxes = $(this).next('ul').find('input:not([disabled])');
if ($(checkboxes).length > $(checkboxes + ':checked').length) {
$(checkboxes).attr('checked', 'checked').closest('li').attr('checked', 'checked');
} else {
$(checkboxes).removeAttr('checked', 'checked').closest('li').removeAttr('checked');
}
($(this).text() == "Select All") ? $(this).text("Select None") : $(this).text("Select All")
$(this).next('ul').trigger('change')
return false;
}))
}
//Write the Data to the DOM
$(ul).data({
heftyBox: a
})
//Apply DOM data
updateheftyBox($(ul));
//Handle Value Change
$(this).bind('change', function() {updateheftyBox($(this));})
}
//scroll to first selected DOM
if ($(ul).find('li[checked]:first').length) {
var itemTop = $(ul).find('li[checked]:first').offset().top || $(ul).offset().top;
var ulTop = $(ul).offset().top;
$(ul).scrollTop(itemTop - ulTop);
}
}
updateheftyBox = function(target) {
var a = $(target).data().heftyBox;
var container = $(target).parent('.heftyBox');
var filter = $(target).siblings('.list_filter');
var ul = $(target);
//Gather created data
a.value = [];
$(ul).find('input:checked').each(function() {
a.value.push($(this).val())
})
$(container).css({
width: a.width,
height: a.height,
"min-width": $(filter).outerWidth()
});
$(ul).css({
height: a.height - $(filter).outerHeight(),
"margin-top": $(filter).outerHeight()
})
$(ul).val(a.value);
}
filterBox = function(target, blocks) {
$(target).unbind('keyup change');
$(target).bind('keyup change', function() {
var inText = $(this).val().trim(); //remove trailing whitespace
$.each(blocks, function() {
var title = $(this).children('label').text(); //the title in the block
if (matchAll(title, inText)) {
$(this).show();
} else {
$(this).hide();
}
})
})
}
matchAll = function(string, args) { //string= string to match, args= search input
var die = 0; //return switch
var checks = args.split(' '); //break input into array
$.each(checks, function() {
var myReg = new RegExp(this, 'i'); //search term to regex
if (!string.match(myReg)) { //if it doesn't match, kill the function
die = 1;
}
})
if (die == 1) {
return false;
} else {
return true;
}
}
$('.heftyBox li:has(input:checkbox)').live('click', function() {
($(this).has(':checked').length) ? $(this).attr('checked', 'checked') : $(this).removeAttr('checked')
})
The concepts of thus plugin:
Source github/kmacey1249/heftybox
Implemented like so:
Initial HTML
<select name="test" id="test" multiple="multiple" bar="baz">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3" foo="bar">Three</option>
</select>
jQuery Call
$('#test').heftyBox(); //{type: "checkbox"/"radio", width: "auto", height: 150}
Result:
<div class="heftyBox" id="test_container" style="width: auto; height: 178px; min-width: 155px; ">
<input id="test_filter" class="list_filter" />
<a href="#">Select All</a>
<ul id="test" multiple="multiple" bar="baz" style="height: 155px; margin-top: 23px; ">
<li>
<input type="checkbox" id="option_test_0" name="test" value="1">
<label for="option_test_0">One</label>
</li>
<li>
<input type="checkbox" id="option_test_1" name="test" value="2">
<label for="option_test_1">Two</label>
</li>
<li>
<input type="checkbox" id="option_test_2" name="test" value="3" foo="bar">
<label for="option_test_2">Three</label>
</li>
</ul>
</div>
Source:
codereview.stackexchange.com
I have a nested form in which I would like the form fields to only appear once for uploading a new image, then display the existing images, without any sort of CRUD capability. In essence, on the edit page, just give the option to add images, but not delete or update.
The relationship is a video has many video_images, which use paperclip for has_attached_file :image I’m trying the following in my controller now:
# GET /videos/new
# GET /videos/new.json
def new
@video = current_user.videos.build
@newthumbnail = @video.video_images.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: @video }
end
end
And this in my view:
<%= f.fields_for @newthumbnail do |u| %>
<%= u.label :image, "Upload New Thumbnail" %> <br />
<%= u.file_field :image, :class => "image_uploader" %>
<% end %>
<p>
Or select a previous thumbnail
</p>
<div id="previous_thumbnails">
<!-- These will ultimately be dynamically generated as the existing image associations -->
<div class="previous_thumbnail" rel="1">
<img src="http://placehold.it/120x90" />
</div>
<div class="selected previous_thumbnail" rel="2">
<img src="http://placehold.it/120x90" />
</div>
<div class="previous_thumbnail" rel="3">
<img src="http://placehold.it/120x90" />
</div>
<div class="previous_thumbnail" rel="4">
<img src="http://placehold.it/120x90" />
</div>
</div>
But I end up with the following error:
unknown attribute: video_image
Which tells me that somewhere, there’s a mistranslation of singularity vs plurality. I can see why Rails would singularize it, as it is, in fact, a single entry. However, even overriding the name of the file field, and making name="video[video_image][image]" into name="video[video_images][image]", I get an error like so:
VideoImage(#39741260) expected, got Array(#9591480)
With params sent:
"video_images"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x000000054f1078 @original_filename="Bill OneManBand.jpg",
@content_type="image/jpeg",
@headers="Content-Disposition: form-data; name=\"video[video_images][image]\"; filename=\"Bill OneManBand.jpg\"\r\nContent-Type: image/jpeg\r\n",
@tempfile=#<File:/tmp/RackMultipart20120205-3582-1xp2duq>>},
So where am I going wrong? I feel like I may be taking the wrong approach to this…
Source: stackoverflow.com