data-autoscroll-block "start" position of turbo_frame option is misaligned - ruby-on-rails

I would like to use the data-autoscroll-block attribute described in Turbo Reference to set the scroll position to TOP when screen transitions by turbo_frame, but it is not completely at the top position.
Since the navbar is sticky, I'm guessing that the height (specifically, 64px) will be shifted.
<%# Applicable index view %>
<%= turbo_frame_tag "entries", autoscroll: true, data: { autoscroll_block: "start" } do %>
contents
<% end %>
<%# navbar view %>
<header class="sticky top-0 z-10 bg-white w-full h-16....">
contents
</header>
Any advice on how to fix this would be appreciated.

You can try offsetting it with css. For some reason the snippet scrolls the actual page as well, just "Run code snippet" and go "Full page".
// fake the turbo frame navigation, ignore this part
document.querySelector("turbo-frame a").onclick = event => {
event.preventDefault();
var frame = event.target.closest("turbo-frame");
var data = frame.dataset;
frame.scrollIntoView({
behavior: data.autoscrollBehavior,
block: data.autoscrollBlock
});
}
.scroller {
scroll-snap-type: y;
scroll-padding-block-start: 64px;
}
header {
position: sticky;
top: 0px;
height: 64px;
border: 1px solid;
}
.spacer {height: 50px;}
.spacer-xl {height: 1600px;}
<html class="scroller">
<body>
<div class="spacer"></div>
<header>
HEADER. Why you scroll the actual page?! <br> Sorry, Stackoverflow.
</header>
<div class="spacer"></div>
<turbo-frame autoscroll="true" data-autoscroll-block="start" data-autoscroll-behavior="smooth">
inside the frame click me
</turbo-frame>
<div class="spacer-xl"></div>
</body>
</html>

Related

dragging an element to the first position

<div class='parent'>
<div class='children'>1234</div>
<div class='children'>5678</div>
<div class='children'>9101</div>
<div class='children'>I WANT TO BE FIRST</div>
</div>
js
$('.parent').sortable({
axis: "y",
containment: "parent"
});
There is a problem dragging an element to the first position if containment is set to parent. I need this settings but I also need to move some elements to the top. But it seams that there is no space enough to do it. Sometimes it is possible but mainly - it's not.
I tried with adding top/bottom padding/margin to the parent - without success.
Any workaround?
Here is jsfiddle
you can try adding a 'hidden' element above, like so:
<div class='parent'>
<div class='children hidden'></div>
<div class='children'>1234</div>
<div class='children'>5678</div>
<div class='children'>9101</div>
<div class='children'>I WANT TO BE FIRST</div>
</div>
with this for css:
.hidden {
visibility: hidden;
height: 0;
}
It won't release if dragged above the invisible element though.
here's a jsfiddle
Can you add a containing div and set the containment to it? e.g.:
<div id="outer">
<div class='parent'>
<div class='children'>1234</div>
<div class='children'>5678</div>
<div class='children'>9101</div>
<div class='children'>I WANT TO BE FIRST</div>
</div>
</div>
along with:
$('.parent').sortable({
axis: "y",
containment: "#outer"
});
and
#outer {
padding-top: 1px;
}
That seemed to work with the fiddle.

iOS7 Safari: tapping on fixed positioned header bar with higher z-index triggers event handler of the element underneathe it

My web page has a fixed positioned header bar. As you scroll, the content will go under the header bar, using z-index. Clicking on the blocks in the content area will toggle its color. Click anywhere in header should not trigger the event handler of the block.
But this does not work on iOS7 Safari. Tapping on header made blocks change color. As I searched the internet, it seems to be iOS7 bug. Tried window.scrollTo(0,0), and extra 20px thing, did not help.
Interestingly I noticed the same problem on Yahoo Finance and Yahoo Sport web app on iOS7 mobile Safari, where they have fixed header too.
Anyone know a good fix?
Here is the code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" >
<style>
header {
position: fixed;
top: 0;
left: 0;
z-index: 2;
background: grey;
width: 100%;
height: 50px;
}
.content {
z-index: 1;
margin-top: 60px;
}
.block {
background: red;
height: 150px;
margin: 4%;
}
.block.green {
background: green;
}
</style>
</head>
<body>
<header>
Fixed positiond header.
</header>
<div class="content">
<p>On iOS Safari, scroll the blocks below the header, tap the header on the top edge to let the address bar appear. Then tap anywhere in the header, you will see block toggling colors.
</p>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
<!-- Include jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script>
$(document).ready(function() {
$(".block").on("click", function() {
$(this).toggleClass("green");
});
});
</script>
</body>
</html>
This does appear to be a bug, or at least a quirk in the way Safari on iPad is handling this. For a workaround, it seems that if you add and onclick event handler to your header it resolves the issue:
<header onclick="">
You can also add one with jQuery if you prefer that method.

Show banner and menu navigation bar on all pages

I am new to Rails. I am using Aptana Studio 3 to write a small application.
In the Views folder, I added a new .html.erb page and added a jQuery navigation menu bar. This page also has a banner. I want to keep this as a base page (like Master Page in .NET) for all the other pages.
I want all the other pages to automatically show the banner and menu bar on top.
How to do this? I am using Rails 3.2.
Edited
Code of application.html.erb:
<!DOCTYPE html>
<html>
<head>
<title></title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
<script type="text/javascript" src="..\Libraries\jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('li.headlink').hover(
function() { $('ul', this).css('display', 'block'); },
function() { $('ul', this).css('display', 'none'); });
});
</script>
<style type="text/css" rel="stylesheet">
/* General */
#cssdropdown, #cssdropdown ul { list-style: none; }
#cssdropdown, #cssdropdown * { padding: 0; margin: 0; }
/* Head links */
#cssdropdown li.headlink { width: 220px; float: left; margin-left: -1px; border: 1px black solid; background-color: #e9e9e9; text-align: center; }
#cssdropdown li.headlink a { display: block; padding: 15px; }
/* Child lists and links */
#cssdropdown li.headlink ul { display: none; border-top: 1px black solid; text-align: left; }
#cssdropdown li.headlink:hover ul { display: block; }
#cssdropdown li.headlink ul li a { padding: 5px; height: 17px; }
#cssdropdown li.headlink ul li a:hover { background-color: LightBlue; color:Black }
/* Pretty styling */
body { font-family: verdana, arial, sans-serif; font-size: 0.8em;}
#cssdropdown a { color: white; } #cssdropdown ul li a:hover { text-decoration: none; }
#cssdropdown li.headlink { background-color: Blue;}
#cssdropdown li.headlink ul { background-position: bottom; padding-bottom: 10px; }
</style>
</head>
<body>
<%= yield %>
<div id="divMain">
<div id="divHeader">
<img src="..\Images\W.png">
</div>
<div id="divMenu">
<ul id="cssdropdown">
<li class="headlink">
Task
<ul>
<li>Add New</li>
</ul>
</li>
<li class="headlink">
Reports
<ul>
<li>Report</li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content"><%= content_for?(:content) ? yield(:content) : yield %></div>
</body>
</html>
Code of Content.html.erb
<% content_for :stylesheets do %>
<div id="divLogin">
</div>
<% end %>
<% content_for :MainContent do %>
<div id="divMain">
</div>
<% end %>
<%= render :partial => "layouts\application.html.erb" %>
Rails uses layouts as master templates. As default will you have one master layout template called application, which you can find in app/views/layouts/application.html.erb. If you look at this file will you see something like:
# app/views/layouts/application.html.erb
<html>
<head>
...
</head>
<body>
...
<div id="content">
# Your page content will be inserted here:
<%= yield %>
</div>
...
</body>
</html>
As default will this be rendered for all pages, and the content of each page (fx your new.html.erb) would be rendered in the yield block.
This means that application.html.erb is the right place to but generel layout stuff, like menus and banners that should appear on all pages.
If you want to have something that varies a bit for each page (fx different banners) can you add a special <%= yield(:banner) if content_for?(:banner) %> in your application.html.erb file. You will then be able to add a block in each of your pages for a banner like this:
# app/views/some_resource/some_page.html.erb
<% content_for(:banner) do %>
# insert page specifik banner here
<% end %>
# normal content for page
...
I hope this answers your question?
You can also read more about layouts (fx how to use more then one layout) on http://guides.rubyonrails.org/layouts_and_rendering.html
Edit: correct way to implement content.html.erb
The content of content.html.erb should be:
# What is this? This has nothing to do with stylesheets?
<% content_for :stylesheets do %>
<div id="divLogin">
</div>
<% end %>
<div id="divMain">
</div>
So no content_for :MainContent block and don't render the ´application.html.erb´ layout template (it's not even a partial, so you can't do this).
You can use nested layouts as described here.
Watch from 5:18,
from what I've read I think thats kind of what you may be looking for.
Hope it helps.
Railscast #328
Also here is a link to Twitter's bootstrap navbar which you may want to look into. It will show a banner and navigation bar on all pages and is fairly easy to set up.
http://twitter.github.io/bootstrap/components.html#navbar
One of the best sources for this topic is the beginning of the book The Rails View. Here is the link: The Rails View
This really helps with the content_for helper method, which will become your friend instantly once you know how to use it.

Using Masonry in Rails - boxes not moving on window resize

I have tried this using both the files from the Masonry website, plus the masonry-rails gem, but am getting the same problem.
Basically, when I resize the browser window, the boxes aren't moving to fit the new page size. Instead, I'm just getting scroll bars appearing in the browser.
I know that the files are loading fine, and picking up the right selectors, because if I e.g. change the column width in the masonry() parameters, the boxes do appear in a different place when I load the page.
Also, I'm using Bootstrap if that's relevant, but I've named the selectors so they don't clash with the ones reserved for bootstrap - e.g. using #masonry-container instead of #container.
Any help would be much appreciated, thanks!!
application.js:
//= require masonry/jquery.masonry
message_board/show:
<div id="show-message-board">
<%= render :partial => "show_message_board", :locals => { :messages => current_user.messages }, :remote => true %>
</div>
<script>
$(function(){
$('#masonry-container').masonry({
// options
itemSelector : '.item',
columnWidth : 50,
isAnimated: true
});
});
</script>
_show_message_board.html.erb:
<div id="masonry-container" class="transitions-enabled infinite-scroll clearfix">
<% messages.each do |message| %>
<div class="item">
<p class="message_from"><%= message.user.first_name %> <%= message.user.last_name %>:</p>
<p class="message_content"><%= message.content %></p>
</div>
<% end %>
EDIT:
I've tried using the following as suggested elsewhere, and that still doesn't work!:
$(function(){
var $container = $('#masonry-container');
$container.imagesLoaded( function(){
$container.masonry({
itemSelector : '.item'
});
});
});
Here's what I did to get Masonry to work in my Rails project. Perhaps this will help you...
I downloaded the "jquery.masonry.min.js" file from the site and placed it in my app\assets\javascripts directory.
I added
//= require jquery.masonry.min to my application.js file
I created a separate css file for masonry (just to keep things neat) called "masonry.css.scss" under my app\assets\stylesheets directory. This is the CSS I have (I'm using "box" instead of your "item"):
.box {
margin: 5px;
padding: 5px;
background: #D8D5D2;
font-size: 11px;
line-height: 1.4em;
float: left;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
display: inline;
width: 260px;
}
.box img {
width: 100%;
}
Since I'm using the code in my "home\index.html.erb" file, I created a "home.js" file under my app\assets\javascripts" directory. This is the js code I have:
jQuery(document).ready(function () {
var $container = $('#UserShoppingRequestsContainer');
$container.imagesLoaded(function () {
$container.masonry({
itemSelector:'.box',
isAnimated:true,
animationOptions:{
duration:750,
easing:'linear',
queue:false
}
});
});
})
Finally, in my "home\index.html.erb" file, I have something like this:
<div id="UserShoppingRequestsContainer">
<% #shopping_requests.each do |shopping_request| %>
<div class="box col3" id="<%= shopping_request.id.to_s %>">
<%= link_to image_tag(shopping_request.request_picture.url(:medium)), user_shopping_request_path(shopping_request.user, shopping_request) %>
<p class="serif1_no_padding"><%= shopping_request.category.name %></p>
</div>
<% end %>
</div>
I think that's it.

customising the look of f.file.field in rails

<div id="photo_attachment_container">
<%= f.file_field :photo %>
</div>
Currently this just looks like a button, how can I add some css and customise the look (e.g dimensions background etc) of this button? Thanks
The HTML file field has been, and remains, one of the most least customizable of the HTML form controls. The other problem is that it is rendered so differently between browsers and OSes. The best way to style these controls is to render the file control as a transparent element on top of another button or set of elements that is styled the way you want. The file control does not need to be visible to be activated with a user click, but it does need to be on the top most layer (sending it click or focus events doesn't work in my tests).
Here's some example HTML:
<div id="test">
<div class="wrapper">
<input type="file" />
</div>
<button>Select a file</button>
</div>
The CSS renders the wrapper div and button as absolutely positioned elements. The button is visible and styled while the wrapper which contains the file field is transparent. I've set the wrapper field to reduce transparency when you hover over it to illustrate its positioning relative to the styled button underneath.
#test {
position: relative;
}
#test .wrapper {
opacity: 0;
cursor: pointer;
position: absolute;
top: 0;
z-index: 2;
}
#test .wrapper:hover {
opacity: 0.5;
}
#test button {
background-color: #ccc;
border: none;
color: #666;
padding: 3px 5px;
border-radius: 5px;
position: relative;
top: 0;
z-index: 1;
}
Example on JS fiddle.
http://jsfiddle.net/JgDuh/
EDIT:
To answer the question you asked in your comment, you would structure the above answer in your Rails view template like this:
<div id="photo_attachment_container">
<div class="wrapper">
<%= f.file_field :photo %>
</div>
</div>
This would render as (Note that I used user as the substitute for whatever model you passed in form_for):
<div id="photo_attachment_container">
<div class="wrapper">
<input type="file" id="user_photo" name="user[photo]" />
</div>
</div>

Resources