From 67ed4565d4c92d87f26d0961aeba335cb1322d63 Mon Sep 17 00:00:00 2001 From: Tyrel Souza Date: Tue, 22 Apr 2014 15:22:36 -0400 Subject: [PATCH] styling, tagging --- Gemfile | 1 + Gemfile.lock | 3 + app/assets/javascripts/application.js | 1 + app/assets/stylesheets/application.css.scss | 2 + app/assets/stylesheets/campaign.css.scss | 25 +- app/views/campaigns/_form.html.erb | 35 +- app/views/campaigns/_videolisting.html.erb | 5 +- app/views/campaigns/show.html.erb | 168 ++++---- app/views/layouts/application.html.erb | 6 +- .../bootstrap-tagsinput-angular.js | 80 ++++ .../assets/javascripts/bootstrap-tagsinput.js | 405 ++++++++++++++++++ .../javascripts/bootstrap-tagsinput.min.js | 8 + .../bootstrap-tagsinput.min.js.map | 1 + .../stylesheets/bootstrap-tagsinput.css | 44 ++ .../stylesheets/bootstrap-tagsinput.less | 48 +++ 15 files changed, 734 insertions(+), 98 deletions(-) create mode 100755 vendor/assets/javascripts/bootstrap-tagsinput-angular.js create mode 100755 vendor/assets/javascripts/bootstrap-tagsinput.js create mode 100755 vendor/assets/javascripts/bootstrap-tagsinput.min.js create mode 100755 vendor/assets/javascripts/bootstrap-tagsinput.min.js.map create mode 100755 vendor/assets/stylesheets/bootstrap-tagsinput.css create mode 100755 vendor/assets/stylesheets/bootstrap-tagsinput.less diff --git a/Gemfile b/Gemfile index d72a696..dff67e7 100644 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,7 @@ gem 'unicorn' gem 'bootstrap-sass', '<3.1' gem 'devise' gem 'jbuilder' +gem 'bootstrap-tagsinput-rails' group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 3345f75..9189a31 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -50,6 +50,8 @@ GEM debug_inspector (>= 0.0.1) bootstrap-sass (3.0.3.0) sass (~> 3.2) + bootstrap-tagsinput-rails (0.3.2.0) + railties (>= 3.1) builder (3.2.2) capybara (2.1.0) mime-types (>= 1.16) @@ -229,6 +231,7 @@ DEPENDENCIES better_errors binding_of_caller bootstrap-sass (< 3.1) + bootstrap-tagsinput-rails capybara-webkit (>= 1.0.0) coffee-rails database_cleaner diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 1ca0e3b..c9ad444 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -12,4 +12,5 @@ // //= require jquery //= require jquery_ujs +//= require bootstrap-tagsinput //= require_tree . diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index f173737..fa905fd 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -3,5 +3,7 @@ /////////////////////////////////////////////////////////////////////////////// @import 'bootstrap'; +@import 'bootstrap-tagsinput.css'; @import 'campaign'; + /////////////////////////////////////////////////////////////////////////////// diff --git a/app/assets/stylesheets/campaign.css.scss b/app/assets/stylesheets/campaign.css.scss index 6180d84..0c66454 100644 --- a/app/assets/stylesheets/campaign.css.scss +++ b/app/assets/stylesheets/campaign.css.scss @@ -56,4 +56,27 @@ select { span { padding-left: 2em; } -} \ No newline at end of file + span.list-item { + display:block; + } +} +span.tag.label.label-info { + display: block; + margin-bottom:1px; + + .tag-item { + width:90%; + white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* css-3 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + word-break: break-all; + white-space: normal; + } +} + +div.bootstrap-tagsinput { +width:100%; +} + diff --git a/app/views/campaigns/_form.html.erb b/app/views/campaigns/_form.html.erb index 09c3c2f..38de123 100644 --- a/app/views/campaigns/_form.html.erb +++ b/app/views/campaigns/_form.html.erb @@ -24,22 +24,29 @@
-
-
+
<%= frm.input :advertisername, label: 'Advertiser Name', hint: "The name of the company." %> + <%= frm.input :listingcode, + label: 'Listing Code', + hint: "This should be the same as Intake Form's Form Hash." %> <%= frm.input :clientid, label: 'Client ID', hint: 'An identifier provided by BetterVideo.' %> - <%= frm.input :listingcode, - label: 'Listing Code', - hint: "This should be the same as Intake Form's Form Hash." %> + <%= frm.input :description, + label: 'Description', + as: 'text', + hint: "Used for script research." %> + <%= frm.input :productsandservices, + label: 'Products & Services', + hint: "Used in script and video research." %> + <%= frm.input :websiteurl, label: 'Website URL', hint: "Used for script research and may be used in the video if they are including websites in the video graphics." %> - <%= frm.input :vpa, + <%= frm.input :vpa, label: 'Client Service Rep', hint: "This is the full name of the client services representative, as entered in the BetteVideo system associated with this order. This feature is designed for sales reps that are well known to the system. This feature is typically used for automated communication." %> @@ -79,16 +86,11 @@ label: 'Company Colors', hint: "Comma Separated.", placeholder: "ex: red, white, blue" %> - <%= frm.input :description, - label: 'Description', - as: 'text', - hint: "Used for script research." %> + <%= frm.input :facebookurl, label: 'Facebook URL', hint: "Used for script and photo research." %> - <%= frm.input :productsandservices, - label: 'Products & Services', - hint: "Used in script and video research." %> + <%= frm.input :targetaudience, label: 'Target Audience', hint: "Used in script and video research." %> @@ -97,7 +99,7 @@ hint: "Toll-free phone number of business. Used in video creation." %>
-
+
<%= frm.simple_fields_for(:videolistings, html: {class: 'form-horizontal'}) do |vidlist| %>
@@ -130,15 +132,14 @@ label: 'Notes', hint: "Notes and/or instructions sent in this field are used by the editors to aid in production of the video." %> <%= vidlist.input :asseturls, - as: 'text', label: 'Asset Urls', placeholder: "ex: http://www.company.com/logo.png, http://www.company.com/background.png", - hint: "A comma separated list of URLs of any assets." %> + hint: "A list of all file assets.", + input_html: {data: {role: "tagsinput" }}%>
<% end %>
-
diff --git a/app/views/campaigns/_videolisting.html.erb b/app/views/campaigns/_videolisting.html.erb index 0389fe8..38361c9 100644 --- a/app/views/campaigns/_videolisting.html.erb +++ b/app/views/campaigns/_videolisting.html.erb @@ -33,6 +33,9 @@ asseturls - <%= videolisting.asseturls %> + + <% videolisting.asseturls_array.each do |asset| %> + <%= asset[:asseturl] %> + <% end %> \ No newline at end of file diff --git a/app/views/campaigns/show.html.erb b/app/views/campaigns/show.html.erb index 8ab800b..a1b2843 100644 --- a/app/views/campaigns/show.html.erb +++ b/app/views/campaigns/show.html.erb @@ -2,99 +2,115 @@ <%= link_to 'Back', campaigns_path %> -
-

- <%= @campaign.advertisername %> -

-

<%= notice %>

+
+

+ <%= @campaign.advertisername %> +

+

<%= notice %>

+
-
-
-
-
+
- Clientid - <%= @campaign.clientid %> - - - - Listingcode + Listing Code <%= @campaign.listingcode %> - - Billingcode - <%= @campaign.billingcode %> + Client Id + <%= @campaign.clientid %> - - - Address1 - <%= @campaign.address %> - - - - City - <%= @campaign.city %> - - - - State - <%= @campaign.state %> - - - - Zip - <%= @campaign.zip %> - - - - Email Address - <%= @campaign.emailaddress %> - - - - Customer First Name - <%= @campaign.customerfirstname %> - - - - Customer Last Name - <%= @campaign.customerlastname %> - - - - Businessphone - <%= @campaign.businessphone %> - - - Description <%= @campaign.description %> - - Contactphone - <%= @campaign.contactphone %> + Products & Services + <%= @campaign.productsandservices %> - Websiteurl <%= @campaign.websiteurl %> - + + Client Services Rep + <%= @campaign.vpa %> + + + Billing Code + <%= @campaign.billingcode %> + + + Email Address + <%= @campaign.emailaddress %> + + + Business Phone + <%= number_to_phone @campaign.businessphone %> + + + Contact Phone + <%= number_to_phone @campaign.contactphone %> + + + Customer First Name + <%= @campaign.customerfirstname %> + + + Customer Last Name + <%= @campaign.customerlastname %> + + + Address + <%= @campaign.address %> + + + City + <%= @campaign.city %> + + + State + <%= @campaign.state %> + + + Zip + <%= @campaign.zip %> + + + Awards + <%= @campaign.awards %> + + + Background + <%= @campaign.background %> + + + Categories + <%= @campaign.categories %> + + + Company Colors + <%= @campaign.companycolors %> + + + Facebook URL + <%= @campaign.facebookurl %> + + + Target Audience + <%= @campaign.targetaudience %> + + + Tollfree Phone + <%= @campaign.tollfreephone %> +
-
+
    - <% @campaign.videolistings.each do |videolisting| %> - <%= render 'videolisting', videolisting: videolisting %> - <% end %> - - <% if @campaign.videolistings.empty? %> -
  • No Video Listings for this Campaign.
  • - <% end %> -
+ <% @campaign.videolistings.each do |videolisting| %> + <%= render 'videolisting', videolisting: videolisting %> + <% end %> + <% if @campaign.videolistings.empty? %> +
  • No Video Listings for this Campaign.
  • + <% end %> +
    -
    -
    \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d365cf4..436d6ca 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,9 +9,9 @@
    - <%= render 'layouts/header' %> - <%= render 'flashes' -%> - <%= yield %> + <%= render 'flashes' -%> + <%= render 'layouts/header' %> + <%= yield %>
    <%= render 'javascript' %> diff --git a/vendor/assets/javascripts/bootstrap-tagsinput-angular.js b/vendor/assets/javascripts/bootstrap-tagsinput-angular.js new file mode 100755 index 0000000..a9758e9 --- /dev/null +++ b/vendor/assets/javascripts/bootstrap-tagsinput-angular.js @@ -0,0 +1,80 @@ +angular.module('bootstrap-tagsinput', []) +.directive('bootstrapTagsinput', [function() { + + function getItemProperty(scope, property) { + if (!property) + return undefined; + + if (angular.isFunction(scope.$parent[property])) + return scope.$parent[property]; + + return function(item) { + return item[property]; + }; + } + + return { + restrict: 'EA', + scope: { + model: '=ngModel' + }, + template: '', + replace: false, + link: function(scope, element, attrs) { + $(function() { + if (!angular.isArray(scope.model)) + scope.model = []; + + var select = $('select', element); + + select.tagsinput({ + typeahead : { + source : angular.isFunction(scope.$parent[attrs.typeaheadSource]) ? scope.$parent[attrs.typeaheadSource] : null + }, + itemValue: getItemProperty(scope, attrs.itemvalue), + itemText : getItemProperty(scope, attrs.itemtext), + tagClass : angular.isFunction(scope.$parent[attrs.tagclass]) ? scope.$parent[attrs.tagclass] : function(item) { return attrs.tagclass; } + }); + + for (var i = 0; i < scope.model.length; i++) { + select.tagsinput('add', scope.model[i]); + } + + select.on('itemAdded', function(event) { + if (scope.model.indexOf(event.item) === -1) + scope.model.push(event.item); + }); + + select.on('itemRemoved', function(event) { + var idx = scope.model.indexOf(event.item); + if (idx !== -1) + scope.model.splice(idx, 1); + }); + + // create a shallow copy of model's current state, needed to determine + // diff when model changes + var prev = scope.model.slice(); + scope.$watch("model", function() { + var added = scope.model.filter(function(i) {return prev.indexOf(i) === -1;}), + removed = prev.filter(function(i) {return scope.model.indexOf(i) === -1;}), + i; + + prev = scope.model.slice(); + + // Remove tags no longer in binded model + for (i = 0; i < removed.length; i++) { + select.tagsinput('remove', removed[i]); + } + + // Refresh remaining tags + select.tagsinput('refresh'); + + // Add new items in model as tags + for (i = 0; i < added.length; i++) { + select.tagsinput('add', added[i]); + } + }, true); + }); + } + }; +}]); \ No newline at end of file diff --git a/vendor/assets/javascripts/bootstrap-tagsinput.js b/vendor/assets/javascripts/bootstrap-tagsinput.js new file mode 100755 index 0000000..06a071a --- /dev/null +++ b/vendor/assets/javascripts/bootstrap-tagsinput.js @@ -0,0 +1,405 @@ +(function ($) { + "use strict"; + + var defaultOptions = { + tagClass: function(item) { + return 'label label-info'; + }, + itemValue: function(item) { + return item ? item.toString() : item; + }, + itemText: function(item) { + return this.itemValue(item); + }, + freeInput : true + }; + + function TagsInput(element, options) { + this.itemsArray = []; + + this.$element = $(element); + this.$element.hide(); + + this.isSelect = (element.tagName === 'SELECT'); + this.multiple = (this.isSelect && element.hasAttribute('multiple')); + this.objectItems = options && options.itemValue; + + this.$container = $('
    '); + this.$input = $('').appendTo(this.$container); + + this.$element.after(this.$container); + + this.build(options); + } + + TagsInput.prototype = { + constructor: TagsInput, + + add: function(item, dontPushVal) { + var self = this; + + // Ignore falsey values, except false + if (item !== false && !item) + return; + + // Throw an error when trying to add an object while the itemValue option was not set + if (typeof item === "object" && !self.objectItems) + throw("Can't add objects when itemValue option is not set"); + + // Ignore strings only containg whitespace + if (item.toString().match(/^\s*$/)) + return; + + // If SELECT but not multiple, remove current tag + if (self.isSelect && !self.multiple && self.itemsArray.length > 0) + self.remove(self.itemsArray[0]); + + if (typeof item === "string" && this.$element[0].tagName === 'INPUT') { + var items = item.split(','); + if (items.length > 1) { + for (var i = 0; i < items.length; i++) { + this.add(items[i], true); + } + + if (!dontPushVal) + self.pushVal(); + return; + } + } + + // Ignore items allready added + var itemValue = self.options.itemValue(item), + itemText = self.options.itemText(item), + tagClass = self.options.tagClass(item); + + if ($.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0]) + return; + + // register item in internal array and map + self.itemsArray.push(item); + + // add a tag element + var $tag = $('' + htmlEncode(itemText) + ''); + $tag.data('item', item); + self.$input.before($tag); + + // add