dynamically add div in rails - javascript

I want make <div class="row">.
if <div class="col-md-4"> is three or more,
I want make <div class="row">.
Because I use twitter bootstrap grid view.
My View is
<% #account_products.order(created_at: :desc).each do |product| %>
<div>
<div class="col-md-4">
<div = "icons-right">
<span class = "icons-right">
<%= link_to image_tag("like.png", size: "30"),
line_items_path(product_id: product),
:class => "cart_image", method: :post %>
<button class="btn btn-default btn-sm dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<!-- edit_product_path, product.id로 했으나 id값을 전달하지 않았다. -> 전달은 매개변수로 ! -->
<li role="presentation"><%= link_to "edit", edit_product_path(product.id) %></li>
<li role="presentation"><%= link_to "destory", product, method: :delete %></li>
</ul>
</span>
</div>
<div class="fixed-size-image">
<a href = "<%= product.image_url %>" target = "blank" >
<%= image_tag(product.item.url) if product.item? %>
</a>
</div>
<div class = "brand">
<%= product.brand %>
</div>
<div class = "description">
<%= product.title %>
</div>
<div class = "price">
<%= product.price %>
</div>
<!-- line_item_path -> line_items_path class="btn btn-primary btn-lg active -->
<!-- like.png -->
</div>
</div>
<% end %>

If I understand correctly, you're trying to output a <div class="row"> for every three columns, is that right?
There are two ways to do it:
<% #account_products.order(created_at: :desc).each_with_index do |product, i| %>
<% if i%3 == 0 %>
<div class="row">
<% end %>
... (The rest of your code)
<% if i%3 == 0 %>
</div>
<% end %>
<% end %>
Or:
<% #account_products.order(created_at: :desc).in_groups_of(3) do |product_group| %>
<div class="row">
<% product_group.compact.each do |product| %>
... (The rest of your code)
<% end %>
</div>
<% end %>
---edit---
As requested, jQuery solution:
var a = $('.col-md-4');
while(a.length) {
$(a.splice(0,3)).wrapAll("<div class='row' />")
}

Related

How do I sort by distance from user, based on user's location?

I have a Rails 7 app in which users can search, sort, and filter to find parks and nature reserves. I'm using the Ransack gem.
I have calculated the distance of each park from the user based on the user's IP address using Javascript.
Now I want to add a link on the Parks Index page for users to sort by distance. (Currently I have sort by rating and sort by name.)
Not sure how to go about this... I suspect I'll have to store the distance in the database somehow (on the user table?), so I can apply a server-side sort. Is that the right approach?
How do I store the distance from user in an efficient way, when the distance is recalculated every time the user visits the site?
app/javascript/controllers/geolocation_controller.js
import { Controller } from '#hotwired/stimulus';
import { getDistance, convertDistance } from 'geolib';
export default class extends Controller {
static targets = ['park'];
connect() {
window.navigator.geolocation.getCurrentPosition((position) => {
this.setUserCoordinates(position.coords);
this.setDistanceText();
})
}
setUserCoordinates(coordinates) {
this.element.dataset.latitude = coordinates.latitude;
this.element.dataset.longitude = coordinates.longitude;
}
getUserCoordinates() {
return {
latitude: this.element.dataset.latitude,
longitude: this.element.dataset.longitude,
};
}
setDistanceText() {
this.parkTargets.forEach((parkTarget) => {
let distanceFrom = getDistance(
this.getUserCoordinates(),
{ latitude: parkTarget.dataset.latitude,
longitude: parkTarget.dataset.longitude },
);
parkTarget.querySelector('[data-distance-away]').innerHTML =
`${Math.round(convertDistance(distanceFrom, 'km'))} kilometers away`;
});
}
}
app/views/parks/_park_cards.erb
<% #parks.order('average_rating DESC NULLS LAST').each do |park| %>
<li
style="list-style-type: none;"
data-geolocation-target="park"
data-latitude="<%= park.latitude %>"
data-longitude="<%= park.longitude %>"
>
<div class="col">
<div class="card border-0 px-2 mb-4">
<% if park.default_image && park.default_image.content_type.in?(%w[image/gif image/jpeg image/png]) %>
...
<% else %>
...
<% end %>
<div class="card-header border-0 bg-white mx-0 px-0 d-flex justify-content-between align-items-center">
<strong><%= link_to park.name, park, class: "text-body" %></strong>
<div class="mx-0 px-0">
<% if park.average_rating? %>
<span>
...
</span>
<%= park.average_rating.round(2) %>
<% end %>
</div>
</div>
<div>
<div data-distance-away>
</div>
<div class="btn p-0 favorite-icon">
...
</div>
<div class="btn p-0">
...
</div>
<br>
<br>
</div>
</div>
</div>
</li>
<% end %>
app/views/parks/index.html.erb
<% provide(:title, 'Parks') %>
<div
data-controller="geolocation"
class="container-fluid"
data-latitude=""
data-longitude=""
>
<div class="col-sm-12">
<%- if current_user && current_user.admin? %>
<%= link_to "New park", new_park_path %>
<% end %>
</div>
<div class="container-fluid">
<div class="col-sm-12 d-flex justify-content-between align-items-center mx-0 px-1 mb-5">
<span class="d-flex align-items-center">
<strong>
<%= #parks.count %>
<%= 'park'.pluralize(#parks.count) %>
</strong>
<span class="ms-4">
<%= link_to "Clear all filters", parks_path, class: "btn link-dark" %>
</span>
</span>
<span class="mb-5">
</span>
<span class="d-flex align-items-center">
<%= sort_link(#q, :average_rating, "Sort by rating", default_order: :desc, class: "btn") %>
<% if I18n.locale.to_s.include?('he') %>
<%= sort_link(#q, :name_he, "Sort by name (Hebrew)", default_order: :asc, class: "btn") %>
<% else %>
<%= sort_link(#q, :name_en, "Sort by name", default_order: :asc, class: "btn") %>
<% end %>
<span class="d-flex justify-content-end ms-4">
<%= render 'filters_button' %>
</span>
</span>
</div>
</div>
<div class="col-sm-12 row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 mx-0 px-2">
<%= render 'park_cards', parks: #parks %>
</div>
<div class="col-sm-12 pagination">
<%= will_paginate(#users) %>
</div>
</div>
<%= render 'filters_modal' %>
app/controllers/parks_controller.rb
class ParksController < ApplicationController
before_action :set_park, only: %i[ show edit update destroy ]
before_action :admin_user, only: %i[ new edit create update destroy ]
# GET /parks or /parks.json
def index
#parks = #q.result(distinct: true).paginate(page:params[:page], :per_page => 48)
end
...
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_locale
before_action :set_search
def set_search
#q = Park.ransack(params[:q])
end
...

Render nested form in bootstrap tab

Working on Rails 5,
I am trying to render nested form (same model) in each dynamic tab,
but now the same fomr is rendering in the all the tabs,how to render different fieldset in different tabs
views/material_masters/new.html.erb
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-body">
<div class="tabbable-line">
<ul class="nav nav-tabs ">
<% #part_locations.each.with_index do |l, i| %>
<li <%= 'class="active"' if i == 0 %>>
<%= l.location_name %>
</li>
<% end %>
<li><button type="button" class="fa fa-plus btn btn-primary btn-xs" data-toggle="modal" data-target="#myModal"></button> </li>
</ul>
<div class="tab-content">
<% #part_locations.each.with_index do |l, i| %>
<div class="tab-pane <%= 'active' if i == 0 %>" id="<%= l.location_name %>">
<%= f.fields_for :material_locations do |builder| %>
<%= render 'material_location_fields', :f => builder %>
<% end %>
<%= link_to_add_association "Add", f, :material_locations, class: "btn btn-primary btn-xs" %>
</div>
<% end %>
</div>
</div>
</div>
</div>
</div>
views/material_masters/_material_location_fields.html.erb
<fieldset>
<div class= "nested-fields">
<div class="col-sm-3">
<%= f.label :material_location, "Material Location" %>
<%= f.text_field :mat_location,class:"form-control",required: true %>
</div>
<div class="col-sm-3">
<%= f.label :opening_stock %>
<%= f.text_field :opening_stock ,class:"form-control",onKeyPress:"return NumbersOnly(this, event,true)",required: true %>
</div>
<div class="col-sm-3">
<%= f.label :reorder_qty %>
<%= f.text_field :reorder_qty, class:"form-control",onKeyPress:"return NumbersOnly(this, event,true)",required:true %>
</div>
</div>
</fieldset>
model/material_master.rb
class MaterialMaster < ApplicationRecord
has_many :material_locations
accepts_nested_attributes_for :material_locations,allow_destroy: true
end
https://i.stack.imgur.com/b6Ssr.png
https://i.stack.imgur.com/69h3X.png
Hear i am trying to add location in bangalore tab i am addling mumbai location and in delhi tab i want to add one more material location but the same form is coming in the next tab
What is obviously on your code is that you have space here in a line:
<%= l.location_name %>
as you can note l .location_name can you remove the space?

Toggle set of images with btn-group

I don't want to display all of the images at once, because it just jumbles the page design. I would like to click a button in a bootstrap btn-group and the appropriate image shows up. Not a javascript/ jquery guy so I need a little help.
<div class="btn-group" role="group" aria-label="...">
<button type="button" class="btn btn-default">Front</button>
<button type="button" class="btn btn-default">Back</button>
<button type="button" class="btn btn-default">Left</button>
<button type="button" class="btn btn-default">Right</button>
</div>
<div class="front-product-img">
<% front = #product['colors'][0]['images'].find{|img| img['label'] == 'Front'} %>
<%= image_tag front['url'], class: 'img-responsive' if front.present? %>
</div>
<div class="back-product-img">
<% back = #product['colors'][0]['images'].find{|img| img['label'] == 'Back'} %>
<%= image_tag back['url'], class: 'img-responsive' if back.present? %>
</div>
<div class="left-product-img">
<% left = #product['colors'][0]['images'].find{|img| img['label'] == 'Left'} %>
<%= image_tag left['url'], class: 'img-responsive' if left.present? %>
</div>
<div class="right-product-img">
<% right = #product['colors'][0]['images'].find{|img| img['label'] == 'Right'} %>
<%= image_tag right['url'], class: 'img-responsive' if right.present? %>
</div>
$(".btn-group[role='group'] button[type=button]").click(function() {
$("."+$(this).text().toLowerCase()+"-product-img").toggle();
});
use the above piece of code for your requirement..

How to modify the value of an input in spree commerce cart

I have the following cart view that i addapted with bootstrap.
<div class="row line_item">
<div class="col-md-4 cart-item-image" data-hook="cart_item_image">
<% if variant.images.length == 0 %>
<%= link_to small_image(variant.product), variant.product %>
<% else %>
<%= link_to image_tag(variant.images.first.attachment.url(:product)), variant.product %>
<% end %>
</div>
<div class="col-md-4 cart-item-image" data-hook="cart_item_description">
<h4><%= link_to line_item.name, product_path(variant.product) %></h4>
<%= variant.options_text %>
<% if line_item.insufficient_stock? %>
<span class="out-of-stock">
<%= Spree.t(:out_of_stock) %> <br />
</span>
<% end %>
<span class="line-item-description" data-hook="line_item_description">
<%= line_item_description_text(line_item.description) %>
</span>
</div>
<div class="col-md-1 cart-item-price" data-hook="cart_item_price">
<%= line_item.single_money.to_html %>
</div>
<div class="col-md-1 cart-item-quantity" data-hook="cart_item_quantity" valign="center">
<%= item_form.number_field :quantity, min: 0, class: "form-control line_item_quantity", size: 5 %>
</div>
<div class="col-md-2">
<div class="cart-item-total" data-hook="cart_item_total">
<%= line_item.display_amount.to_html unless line_item.quantity.nil? %>
</div>
<div class="cart-item-delete" data-hook="cart_item_delete">
<%= link_to content_tag(:span, '', class: 'glyphicon glyphicon-minus-sign'), '#', class: 'delete', id: "delete_#{dom_id(line_item)}" %>
</div>
</div>
</div>
and the following coffeescript that goes along with it
Spree.ready ($) ->
if ($ 'form#update-cart').is('*')
($ 'form#update-cart a.delete').show().one 'click', ->
($ this).parents('.line-item').first().find('input.line_item_quantity').val 0
($ this).parents('form').first().submit()
false
($ 'form#update-cart').submit ->
($ 'form#update-cart #update-button').attr('disabled', true)
Now the delete button does not work with this cart html ( while it is working with the original view a following)
<div style="margin-top: 35px;">
<div class="row">
<tr class="line-item">
<td class="col-md-4 cart-item-image" data-hook="cart_item_image">
<% if variant.images.length == 0 %>
<%= link_to small_image(variant.product), variant.product %>
<% else %>
<%= link_to image_tag(variant.images.first.attachment.url(:small)), variant.product %>
<% end %>
</td>
<td class="col-md-4 cart-item-description" data-hook="cart_item_description">
<h4><%= link_to line_item.name, product_path(variant.product) %></h4>
<%= variant.options_text %>
<% if line_item.insufficient_stock? %>
<span class="out-of-stock">
<%= Spree.t(:out_of_stock) %> <br />
</span>
<% end %>
<span class="line-item-description" data-hook="line_item_description">
<%= line_item_description_text(line_item.description) %>
</span>
</td>
<td class="col-md-1 lead text-primary cart-item-price" data-hook="cart_item_price">
<%= line_item.single_money.to_html %>
</td>
<td class="col-md-1 cart-item-quantity" data-hook="cart_item_quantity" valign="center">
<%= item_form.number_field :quantity, min: 0, class: "form-control line_item_quantity", size: 5 %>
</td>
<td class="col-md-1 lead text-primary cart-item-total" data-hook="cart_item_total">
<%= line_item.display_amount.to_html unless line_item.quantity.nil? %>
</td>
<td class="col-md-1 cart-item-delete" data-hook="cart_item_delete">
<%= link_to content_tag(:span, '', class: 'glyphicon glyphicon-minus-sign'), '#', class: 'delete', id: "delete_#{dom_id(line_item)}" %>
</td>
</tr>
</div>
</div>
It seems to me that the coffeescript should work in both cases!
What am i missing after i modify the view ? It seems to me that the coffeescript should perform the search in both cases...
It doesn't look like you've done anything wrong when it comes to keeping the markup for the javascript the same. My guess would be that Spree.ready ($) -> isn't actually firing. That could be caused by you removing javascript files during your view customization by accident. You should try checking your web developer console to see if there are any javascript errors like Spree not being defined or something like that.

Ruby on Rails jQuery: Toggle not working

I am trying to create a button that shows/hides a div. It seems relatively easy, but whenever I click this button, it just does a refresh, and when I keep clicking it, it hides most of my page. Here is what I have so far. Also, I dont know if it matters but I am using foundation for most of the css
application.js
$(function() {
$(document).foundation();
});
$(document).ready(function() {
$('#message_button').click(function() {
$("#messages").toggle();
});
});
_userindex.html
<div class="row">
<div class="small-12 columns new-button">
<%= link_to 'New Job', new_job_path, class: 'button' %>
</div>
</div>
<div class="section-container auto" data-section>
<section>
<p class="title" data-section-title>Active Jobs</p>
<div class="content" data-section-content>
<% if #active.present? %>
<ul>
<% #active.each do |job| %>
<li class='panel'>
<div class="row">
<div class="small-12 columns">
<div class="row">
<div class="large-6 columns">
<span id="location"><strong>location</strong>: <%= job.location %></span>
</div>
<div class="large-6 columns">
<span id="status"><strong>status</strong>: <%= job.status %></span>
</div>
</div>
<div class='light panel bottom'>
<strong>job: <%= link_to job.name, job %></strong><br>
<%= job.description %>
</div>
</div>
</div>
<div class="row job-buttons">
<div class="small-6 columns">
MESSAGES BUTTON -->>> <%= link_to 'messages', '', class: 'button small secondary', id: "message_button" %>
</div>
<div class="small-6 columns">
<%= link_to 'cancel', job, method: :delete, data: {confirm: 'Are you sure?'}, class: 'button small alert' %>
</div>
</div>
<br />
I WANT TO HIDE THIS ENTIRE DIV ---->>>> <div id="messages">
<div class="row">
<div class="small-12 columns">
<div class="panel">
<%= form_for(#message) do |f| %>
<%= f.label :body, "Description" %>
<%= f.text_area :body %>
<%= f.hidden_field :job_id, value: job.id %>
<%= f.submit 'Create message', class: 'button small secondary' %>
<% end %>
</div>
</div>
</div>
<% jobs_messages = job.messages %>
<% if jobs_messages.present? %>
<ul>
<% jobs_messages.each do |m| %>
<% if m.user_id.present? %>
<% user = m.user %>
<% else %>
<% user = m.runner %>
<% end %>
<li class='panel'>
<div class='row'>
<div class='small-12 columns'>
<p> From: <%= user.login %> </p>
<p> Body: <%= m.body %>
</div>
</div>
</li>
<% end %>
</ul>
<% else %>
<div class="empty panel">
<p>no messages at the moment</p>
</div>
<% end %>
</div>
</li>
<% end %>
</ul>
<% else %>
<div class="empty panel">
<p>no active jobs at the moment</p>
</div>
<% end %>
</div>
</section>
<section>
<p class="title" data-section-title>Completed Jobs</p>
<div class="content" data-section-content>
<% if #completed.present? %>
<% else %>
<div class="empty panel">
<p>no completed jobs yet</p>
</div>
<% end %>
</div>
</section>
</div>
I am trying to an $().click action to the link_to button with id "message_button". Whenever this button/link is clicked, I want it to show/hide the "messages" div.
I am new to jQuery, rails, and foundation, so I left most of the code just in case anything was important. But I marked the message_button and the message div to help you better find it.
2 problems:
It looks to me as though you have a bad case of the "multiple IDs"!
You are not preventing the default behaviour of the link. (so when you click it, the page refreshes or navigates away)
Problem #2 is easy: call preventDefault() (usage example below).
Problem #1 is a little trickier...
You are creating <li> content within a loop, inside each of those <li> tags you have elements with the IDs #messages and #message_button. Multiple instances of an ID on the same page is not allowed. If you want, you can use classes instead of ids as you can have multiple instances of a class.
However, switching from IDs to Classes won't fix your problem, as if you use classes you'll just be toggling ALL messages when any message button is clicked.
Referring to this question here, you can easily get the index of the loop in your rails template:
<% #active.each do |job, index| %>
Your template/html code here
<% end %>
This exposes a new variable, index which you can use to decorate each of your messages and buttons with an index value to then specify which message you wish to show.
Note: I'm not sure if this is the best approach, but this should work. It's been a while since I've used Rails, so there might be errors. I've included the code below just to demonstrate the possible solution:
application.js:
$(function() {
$(document).foundation();
});
$(document).ready(function() {
//NOTE that I am selecting on a class here
$('.message_button').click(function(e) {
//You also need to prevent the default behaviour of
//the link. That is why the page keeps refreshing.
e.preventDefault();
//get the index value I appended to this elements ID
var msgButtonIndex = $(this).attr("id").replace("message_button_","");
//select and toggle the respective message
$("#messages_" + msgButtonIndex).toggle();
});
});
_userindex.html:
<div class="row">
<div class="small-12 columns new-button">
<%= link_to 'New Job', new_job_path, class: 'button' %>
</div>
</div>
<div class="section-container auto" data-section>
<section>
<p class="title" data-section-title>Active Jobs</p>
<div class="content" data-section-content>
<% if #active.present? %>
<ul>
<% #active.each do |job,index| %>
<li class='panel'>
<div class="row">
<div class="small-12 columns">
<div class="row">
<div class="large-6 columns">
<span id="location"><strong>location</strong>: <%= job.location %></span>
</div>
<div class="large-6 columns">
<span id="status"><strong>status</strong>: <%= job.status %></span>
</div>
</div>
<div class='light panel bottom'>
<strong>job: <%= link_to job.name, job %></strong><br>
<%= job.description %>
</div>
</div>
</div>
<div class="row job-buttons">
<div class="small-6 columns">
<%# Adding a "message_button" class and a decorated "message_button_{index}" ID! %>
<%= link_to 'messages', '', class: 'button small secondary message_button', id: "message_button_" + index.to_s %>
</div>
<div class="small-6 columns">
<%= link_to 'cancel', job, method: :delete, data: {confirm: 'Are you sure?'}, class: 'button small alert' %>
</div>
</div>
<br />
<%# decorating this ID too %>
<div id="messages_<%= index.to_s %>">
<div class="row">
<div class="small-12 columns">
<div class="panel">
<%= form_for(#message) do |f| %>
<%= f.label :body, "Description" %>
<%= f.text_area :body %>
<%= f.hidden_field :job_id, value: job.id %>
<%= f.submit 'Create message', class: 'button small secondary' %>
<% end %>
</div>
</div>
</div>
<% jobs_messages = job.messages %>
<% if jobs_messages.present? %>
<ul>
<% jobs_messages.each do |m| %>
<% if m.user_id.present? %>
<% user = m.user %>
<% else %>
<% user = m.runner %>
<% end %>
<li class='panel'>
<div class='row'>
<div class='small-12 columns'>
<p> From: <%= user.login %> </p>
<p> Body: <%= m.body %>
</div>
</div>
</li>
<% end %>
</ul>
<% else %>
<div class="empty panel">
<p>no messages at the moment</p>
</div>
<% end %>
</div>
</li>
<% end %>
</ul>
<% else %>
<div class="empty panel">
<p>no active jobs at the moment</p>
</div>
<% end %>
</div>
</section>
<section>
<p class="title" data-section-title>Completed Jobs</p>
<div class="content" data-section-content>
<% if #completed.present? %>
<% else %>
<div class="empty panel">
<p>no completed jobs yet</p>
</div>
<% end %>
</div>
</section>
</div>

Categories

Resources