-
-
Save BrianTheCoder/149947 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Place your application-specific JavaScript functions and classes here | |
// This file is automatically included by javascript_include_tag :defaults | |
$(function() { | |
MIN_ANSWERS = 2 | |
MAX_ANSWERS = 10 | |
MIN_ANSWERS_MSG = "Minimum of two(2) answers required." | |
MAX_ANSWERS_MSG = "Maximum of ten(10) answers only." | |
TOP_ANSWER_MSG = "Can't go up answer is on the top list." | |
BOTTOM_ANSWER_MSG = "Can't go down answer is on the bottom list." | |
// this will be the elements to be inserted | |
repeat_elements = '\n<li class="poll_answers">' | |
repeat_elements += '\n<a style="display: none" href="#" class="move_answer"><img alt="Move" src="/images/move.png" /></a>' | |
repeat_elements += '\n<input id="poll_answers_answer_{ph}" name="poll_answers[answer_{ph}]" size="30" type="text" value="New Answer"/>' | |
repeat_elements += '\n<input id="answers_id_answer_{ph}" name="answers_id[answer_{ph}]" value=0 type="hidden">' | |
repeat_elements += '\n<a href="#" class="insert_answer"><img alt="Insert_ans" src="/images/insert_ans.gif" /></a>' | |
repeat_elements += '\n<a href="#" class="remove_answer"><img alt="Remove_ans" src="/images/remove_ans.gif" /></a>' | |
repeat_elements += '\n</li>' | |
//$("#poll_answer_list").sortable() | |
// bind events | |
$('#poll_answer_list a.insert_answer').bind('click', insert_answer) | |
$('#poll_answer_list a.remove_answer').bind('click', remove_answer) | |
/* | |
$('#poll_answer_list a.up_answer').bind('click', move_up_answer) | |
$('#poll_answer_list a.down_answer').bind('click', move_down_answer) | |
*/ | |
$("#poll_answer_list li.poll_answers").bind("mouseover", field_mouseover) | |
$("#poll_answer_list li.poll_answers").bind("mouseout", field_mouseout) | |
$("#poll_answer_list a.move_answer").bind("mouseover", drag_handle_mouseover) | |
$("#poll_answer_list a.mov ie_answer").bind("mouseout", drag_handle_mouseout) | |
$('a.add_new_answer').bind('click', add_new_answer) | |
$('table.poll_list tbody tr').bind('mouseover', show_crud_controller) | |
$('table.poll_list tbody tr').bind('mouseout', hide_crud_controller) | |
// inserting new fiel | |
function insert_answer() { | |
if(!checkFieldsCount("insert")) return | |
input_id = $(this).prev("input").attr("id") | |
order = getOrder(input_id) | |
next_order = order + 1 | |
repeat_elements = repeat_elements.replace(/{ph}/g, next_order) | |
$(this).parents("li").after(repeat_elements) | |
$(this).parents("li").next().fadeIn(1000, function() { | |
new_field_id = "#poll_answers_answer_" + next_order | |
reOrderFields() | |
$(new_field_id).next().next().bind('click', insert_answer) | |
$(new_field_id).next().next().next().bind('click', remove_answer) | |
$(new_field_id).parents("li").bind('mouseover', field_mouseover) | |
$(new_field_id).parents("li").bind('mouseout', field_mouseout) | |
$(new_field_id).prev().bind('mouseover', drag_handle_mouseover) | |
$(new_field_id).prev().bind('mouseout', drag_handle_mouseout) | |
}) | |
} | |
// removing fields | |
function remove_answer() { | |
if(!checkFieldsCount("remove")) return | |
$(this).parents("li").fadeOut(1000, function() { | |
$(this).remove() | |
reOrderFields() | |
}) | |
} | |
// returns the order of the field | |
function getOrder(input) { | |
input_a = input.split("_") | |
return parseInt(input_a[input_a.length - 1]) | |
} | |
// reset field orders | |
function reOrderFields() { | |
temp = null | |
$("#poll_answer_list").children().each(function() { | |
var input_id = $(this).find("input").attr("id") | |
var order = getOrder(input_id) | |
if(!temp) { | |
if(order != 1) { | |
order = 1 | |
new_id = "poll_answers_answer_" + order | |
new_name = "poll_answers[answer_" + order + "]" | |
$(this).find("input").attr({ | |
id : new_id, | |
name: new_name | |
}) | |
} | |
temp = order | |
} | |
else { | |
var expected = temp + 1 | |
if(expected != order) { | |
new_id = "poll_answers_answer_" + expected | |
new_name = "poll_answers[answer_" + expected + "]" | |
$(this).find("input").attr({ | |
id : new_id, | |
name: new_name | |
}) | |
} | |
temp = expected | |
} | |
}) | |
} | |
// displays a message if violates the allowable minimum and maximum number of answers | |
function checkFieldsCount(action) { | |
if(action == "insert" && $("#poll_answer_list").children().size() == MAX_ANSWERS ) { | |
alert(MAX_ANSWERS_MSG) | |
return false | |
} | |
else if(action == "remove" && $("#poll_answer_list").children().size() == MIN_ANSWERS ) { | |
alert(MIN_ANSWERS_MSG) | |
return false | |
} | |
else return true | |
} | |
/* | |
// moving answer up | |
function move_up_answer() { | |
if($(this).parents("li").find("input").attr("id") == "poll_answers_answer_1") { | |
alert(TOP_ANSWER_MSG) | |
return false | |
} | |
$(this).parents("li").clone(true).insertBefore($(this).parents("li").prev()) | |
$(this).parents("li").remove() | |
reOrderFields() | |
} | |
// moving answer down | |
function move_down_answer() { | |
last_field_id = $("#poll_answer_list li:last-child").find("input").attr("id") | |
if($(this).parents("li").find("input").attr("id") == last_field_id) { | |
alert(BOTTOM_ANSWER_MSG) | |
return false | |
} | |
$(this).parents("li").clone(true).insertAfter($(this).parents("li").next()) | |
$(this).parents("li").remove() | |
reOrderFields() | |
} | |
*/ | |
// add new answer | |
function add_new_answer() { | |
// we just need to trigger the click on insert answer of the last field on the list | |
$("#poll_answer_list li:last-child").find("a.insert_answer").trigger("click") | |
} | |
// field mouseover handler | |
function field_mouseover(e) { | |
$(this).children("a:first-child").show() | |
} | |
// field mouseout handler | |
function field_mouseout() { | |
$(this).children("a:first-child").hide() | |
} | |
// move answer drag handle mouseover handler | |
function drag_handle_mouseover() { | |
$("#poll_answer_list").sortable({ | |
update: reOrderFields() | |
}) | |
} | |
// move answer drag handle mouseout handler | |
function drag_handle_mouseout() { | |
$("#poll_answer_list").sortable("disable") | |
} | |
// crud controller mouseover handler | |
function show_crud_controller() { | |
$(this).children(':first-child').next().find("ul").show() | |
} | |
// crud controller mouseout handler | |
function hide_crud_controller() { | |
$(this).children(':first-child').next().find("ul").hide() | |
} | |
}) | |
/*** let us take this out for awhile | |
*** I think I misunderstood the specs | |
function update_filter(element, value) { | |
$('div#result_filter').show() | |
switch(parseInt(value)) { | |
case 0: | |
$('div#result_filter').hide() | |
break; | |
case 1: | |
$('div.filters').hide() | |
$('div#filter_age').show() | |
break; | |
case 2: | |
$('div.filters').hide() | |
$('div#filter_gender').show() | |
break; | |
case 3: | |
$('div.filters').hide() | |
$('div#filter_country').show() | |
break; | |
} | |
} | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(function() { | |
var resource = "/tweet/search?f=" | |
var thread = "/tweet/thread?id=" | |
var filter = {} | |
// fn: sends ajax request for pulling off a thread/conversation | |
// once response is recieved we toggle the Show/Hide Conversation | |
function twitter_thread_ajax(url) { | |
$.ajax({ | |
url: url, | |
type: "Get", | |
success: function(html){ | |
if($("a#sc_" + id[1]).text() == "Show Conversation") { | |
$("div#thread_" + id[1]).html(html).slideDown("slow") | |
$("a#sc_" + id[1]).text("Hide Conversation") | |
} | |
else { | |
$("div#thread_" + id[1]).slideUp("slow") | |
$("a#sc_" + id[1]).text("Show Conversation") | |
} | |
} | |
}) | |
} | |
// fn: sends ajax request every time word is selected | |
// once response is recieved we mock it to the view | |
// and make necessary bindings of events | |
function twitter_ajax(url) { | |
$.ajax({ | |
url: url, | |
type: "Get", | |
success: function(html) { | |
// mock the html response to the view | |
$("#twitter_feed").html(html) | |
// makes all the links on tweet feeds popup | |
$("ul#tweets a:not([name='show_conversation'])").click(function() { | |
window.open($(this).attr('href')) | |
return false | |
}) | |
// binds click event to <a name="show_conversation"> | |
// then sends an ajax request | |
$('a[name="show_conversation"]').click(function() { | |
id = $(this).attr("id").split("_") | |
url = thread + id[1] | |
twitter_thread_ajax(url) | |
}) | |
// binds onchange event to language select | |
// then send an ajax request to filter the tweets | |
// according to language | |
$("select#lang_select").change(function() { | |
lang = $(this).val() | |
url = resource + process_filters(lang) | |
twitter_ajax(url) | |
}) | |
} | |
}) | |
} | |
// fn: processes the filters for search as well as the language | |
// returns the concatenated filters | |
function process_filters(language) { | |
var params = "" | |
lang = language || "all" | |
for(key in filter) { params += filter[key] + "+" } | |
return params + "&lang=" + lang | |
} | |
// toggles the class(gray background) | |
$('a[name="tweet_filter"]').toggle(function() { | |
$(this).addClass('tweet_filter_selected') | |
value = $(this).text() | |
key = "'" + value + "'" | |
filter[key] = value | |
},function() { | |
$(this).removeClass('tweet_filter_selected') | |
value = $(this).text() | |
key = "'" + value + "'" | |
delete(filter[key]) | |
}) | |
// binds onclick event to <a name="tweet_filter"> | |
$('a[name="tweet_filter"]').click(function() { | |
lang = $("select#lang_select").val() | |
url = resource + process_filters(lang) | |
twitter_ajax(url) | |
}) | |
$("#ajax-loader").bind("ajaxSend", function(){ | |
$(this).show(); | |
}).bind("ajaxComplete", function(){ | |
$(this).hide(); | |
}) | |
}) // end ready function |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Veebox | |
module API | |
module Voteable | |
def self.included(base) # :nodoc: | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
def is_voteable | |
Object.const_set(:VoteableApiError, Class.new(StandardError)) unless defined?(VoteableApiError) | |
has_many :votes | |
extend Veebox::API::Voteable::SingletonMethods | |
include Veebox::API::Voteable::InstanceMethods | |
end | |
end | |
module InstanceMethods | |
end | |
module SingletonMethods | |
end | |
end | |
module Voter | |
def self.included(base) # :nodoc: | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
def is_voter | |
Object.const_set(:VoteableApiError, Class.new(StandardError)) unless defined?(VoteableApiError) | |
has_many :votes | |
cattr_accessor :current_answer_voted | |
extend Veebox::API::Voter::SingletonMethods | |
include Veebox::API::Voter::InstanceMethods | |
end | |
end | |
module InstanceMethods | |
def cast_a_vote | |
raise VoteableApiError, "Please provide #current_poll in order to cast your vote." unless self.current_poll | |
raise VoteableApiError, "Please provide #current_answer_voted in order to cast your vote." unless self.current_answer_voted | |
raise VoteableApiError, "Poll answer does not belong to this Poll." unless answer_belongs_to_this_poll? | |
raise VoteableApiError, "User already voted this poll." if self.has_voted_this_poll? | |
raise VoteableApiError, "User already voted this answer." if self.has_voted_this_answer? | |
country = self.country if self.respond_to?(:country) | |
vote = self.votes.new :poll_answer_id => current_answer_voted, | |
:country => country | |
vote.save! | |
end | |
def has_voted_this_answer?(poll_answer_id=nil) | |
pa = poll_answer_id || current_answer_voted | |
self.votes.map(&:poll_answer_id).include?(pa) | |
end | |
def answer_belongs_to_this_poll?(poll_answer_id=nil, poll_id=nil) | |
pa = (poll_answer_id || current_answer_voted).to_i | |
p = (poll_id || current_poll).to_i | |
raise VoteableApiError, "Poll does not exist." unless poll = Poll.find_by_id(p) | |
poll.poll_answers.map(&:id).include?(pa) | |
end | |
end | |
module SingletonMethods | |
end | |
end | |
end | |
end | |
ActiveRecord::Base.send :include, Veebox::API::Voteable | |
ActiveRecord::Base.send :include, Veebox::API::Voter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Veebox | |
module API | |
module PollSystem | |
def self.included(base) # :nodoc: | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
def with_polls | |
Object.const_set(:PollApiError, Class.new(StandardError)) unless defined?(PollApiError) | |
has_many :polls | |
cattr_accessor :poll, :answers, :current_poll, :answers_id | |
cattr_accessor :ip_address | |
extend Veebox::API::PollSystem::SingletonMethods | |
include Veebox::API::PollSystem::InstanceMethods | |
end | |
end # ClassMethods | |
module InstanceMethods | |
# Transactionally saved users poll along with the poll answers | |
# Expects poll attributes and array of poll answer attributes | |
# Example format would be: | |
# params ={"poll"=>{"title"=>"My Poll"}, "poll_answers"=>{"answer_1"=>"My answer 1", "answer_2"=>"Any answer"} | |
def save_poll | |
raise PollApiError, "Expects #poll, please pass params[:poll]" unless self.poll | |
raise PollApiError, "Expects #answers, please pass params[:answers]" unless self.answers | |
begin | |
p, p_answers = nil, nil | |
transaction do | |
p = self.polls.new self.poll | |
p.save! | |
self.answers.collect do |k,v| | |
order = k.split("_")[1] | |
pa = {:answer => v, :order => order} | |
p_answers = p.poll_answers.new pa | |
p_answers.save! | |
end | |
# reset poll | |
self.poll = nil | |
self.answers = nil | |
# return the current poll saved | |
self.polls.last | |
end | |
rescue Exception => e | |
return p | |
end | |
end | |
def poll_with_votes | |
# TODO current user's polls that has a votes | |
# TODO implement only if needed | |
end | |
# These are the polls where the current_user has cast a vote | |
def voted_polls | |
sql = <<-EOS | |
SELECT * from polls p | |
WHERE p.id = ANY(SELECT poll_id from poll_answers pa | |
WHERE pa.id = ANY(SELECT poll_answer_id from votes v | |
WHERE v.user_id = #{self.id})) | |
EOS | |
Poll.find_by_sql(sql) | |
end | |
def has_voted_this_poll?(poll_id=nil) | |
poll = poll_id || current_poll | |
voted_polls.map(&:id).include?(poll) | |
end | |
def owner_of_this_poll?(poll_id=nil) | |
poll = poll_id || current_poll | |
return self == poll.user if poll.is_a?(Poll) | |
return self == Poll.find_by_id(poll).user if poll.is_a?(Fixnum) | |
end | |
def update_poll | |
raise PollApiError, "Expects #poll, please pass params[:poll]" unless self.poll | |
raise PollApiError, "Expects #answers, please pass params[:answers]" unless self.answers | |
raise PollApiError, "Expects #current_poll, please pass params[:id]" unless self.current_poll | |
raise PollApiError, "Expects #answers_id, please pass params[:answers_id]" unless self.answers_id | |
begin | |
p, p_answers = nil, nil | |
transaction do | |
now = Time.now | |
p = self.polls.find_by_id self.current_poll | |
p.update_attributes(:title => self.poll[:title], :updated_at => now) | |
self.answers.collect do |k,v| | |
order = k.split("_")[1] | |
p_answers = p.poll_answers.find_by_id self.answers_id[k] | |
if p_answers | |
p_answers.update_attributes(:answer => v, :order => order, :updated_at => now) | |
else | |
pa = {:answer => v, :order => order} | |
p_answers = p.poll_answers.new pa | |
p_answers.save! | |
self.answers_id.delete(k) # we need to remove the new item that bears id of 0 | |
self.answers_id.update(k=>p_answers.id) # and insert the new answer saved | |
end | |
end | |
# this is to delete answer in the record, that has been removed | |
# TODO : how to deal deleted answers that has votes | |
cond = "poll_id = #{p.id} AND id NOT IN (#{self.answers_id.values.join(',')})" | |
PollAnswer.delete_all(cond) | |
# reset poll | |
self.poll = nil | |
self.answers = nil | |
# return the current poll saved | |
return p | |
end | |
rescue Exception => e | |
return p | |
end | |
end | |
end # InstanceMethods | |
module SingletonMethods | |
# This will fill an anonymous user for non logged voters | |
# We used UUID to ensure uniqueness | |
def fill_anonymous(options={}) | |
raise PollApiError, "Expects .ip_address, please pass request.remote_ip" unless ip_address || options[:fb_uid] | |
#raise PollApiError, "geoiplookup Not found, please install geoiplookup for your system" unless system "geoiplookup 127.0.0.1" | |
if options[:fb_uid] # facebook user | |
uid = options[:fb_uid].to_s | |
if user = self.find_by_login(uid) | |
return user | |
end | |
login = uid | |
email = uid + "@facebook-user.com" | |
password = uid | |
password_confirm = password | |
else | |
uuid = (UUID.new).generate | |
login = uuid | |
email = uuid + "@anonymous-voter.com" | |
password = uuid | |
password_confirm = password | |
end | |
# we will try to detect what country our anonymous voter from | |
if system "geoiploo 127.0.0.1" # if geoiplookup is present | |
country = `geoiplookup #{ip_address}`.split(",")[-1].strip | |
else # set country to unknown | |
country = "N/A" | |
end | |
# we add anonymous user but we never activate it | |
user = User.new(:login => login, :email => email, :password => password, | |
:password_confirmation => password_confirm) | |
# then we tag them anonymous users | |
# and return the current user | |
if user.save! | |
# we do these here, because i do not have any idea | |
# why it will not work above on User.new | |
user.anonymous = !options[:fb_uid] | |
user.country = options[:country] || country | |
user.first_name = options[:first_name] || '' | |
user.last_name = options[:last_name] || '' | |
end | |
return user if user.save! | |
end | |
end # SingleTonMethods | |
end | |
end | |
end | |
ActiveRecord::Base.send :include, Veebox::API::PollSystem |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment