Uploaded responsive background-images - ruby-on-rails

I have created a RoR based app/website where the client can upload their own background image to the cover page.
Everything works well with one image, but I would like the site to be responsive and allow my client the choice to upload 3 completely separate images that are displayed depending on the px width of the window.
Currently I have the following code (only showing relevant code), which works fine:
In covers_controller.rb:
class CoversController < ApplicationController
#
#covers = Cover.all
#cover = Cover.find_by(:published => 'yes')
#
end
In application.html.erb:
<body style="background-image: url(<%= #cover.image %>)">
I have however not succeeded in making the cover images responsive. I have tried the following...
Adding a css.erb file with the following code:
#media (max-width: 767px) {
.cover-bg {
background-image: url(<%= #cover.image %>)
}
}
#media (min-width: 768px) {
.cover-bg {
background-image: url(<%= #cover.m-image %>)
}
}
#media (min-width: 1200px) {
.cover-bg {
background-image: url(<%= #cover.lg-image %>)
}
}
For the css.erb above I added two new images to the Model called m-image and lg-image (using paperclip), and added the .cover-bg class to the body tag on application.html.erb, but got a blank page.
UPDATE: here is the model. I realize that I did not add the new images to the Model. However, when first testing the idea of using css.erb, I used images from three different Models for the different #media css, and encountered the same problem:
class Cover < ActiveRecord::Base
has_attached_file :image,
styles: { xlarge: "1600x1600>", large: "600x600>", medium: "300x300>", thumb: "100x100>" }
validates_attachment_content_type :image,
content_type: /\Aimage\/.*\z/
end
I hope there is a easy solution out there, but I have yet to find it. I also tried various application helper methods, but no luck thus far.

Your .css.erb file won't work because you're calling instance-dependent objects, when in likelihood, this file will be precompiled - making it static.
how do you propose that application.css will be able to read #cover?
--
The reason why it worked when you used <body style="..."> is because when you have an inline style in the view, Rails has access to all the data for the instance information etc.
To fix the problem, you need to reference your media queries in a place where you'll have access to all the instance data, namely the view.
After looking at some resources, it's my opinion that you're best putting it into the <head> of the layout of your app:
#app/views/layouts/application.html.erb
<head>
<%= if [[conditional for page]] %>
<style>
#media (max-width: 767px) {
.cover-bg {
background-image: url(<%= #cover.image.url %>)
}
}
#media (min-width: 768px) {
.cover-bg {
background-image: url(<%= #cover.image.url(:medium) %>)
}
}
#media (min-width: 1200px) {
.cover-bg {
background-image: url(<%= #cover.image.url(:large) %>)
}
}
</style>
<% end %>
</head>
<body class="cover-bg">
...
This should give you the ability to assign the custom background image size.
--
Another thing you'll want to look at is background-size: cover:
#app/assets/stylesheets/application.css
.cover-bg {
background-size: cover;
}
This would have to be accompanied by the inline "background-image" style, but if it was done correctly, would allow you to resize your screen and be impervious to the change of background size.
Update
Ruby on Rails applications are dynamic by nature -- they connect to a database etc.
Each time you send a request to a Rails application, there is a lot which happens on the server (you can read more about how it works with MVC):
In short, Rails basically acts like a drive-thru where you pull up, send your request/order, and then Rails comes back with the goods. The "goods" are rendered HTML code which your browser then outputs on the screen.
This rendered HTML - although will be interspersed with #instance_variables etc in the backend - will be static for the browser.
Your browser is nothing more than an engine to render HTML/CSS/JS. Rails "compiles" your data and sends back an HTML file so that Chrome / Firefox can output something useful on screen.
In other words, your <%= #instance_variable %> is ONLY available in the "backend" of the app (when your "order" is being processed). This means that if you're looking to make your application versatile, you have to make sure all backend data is available to the parts of the app which are returned to the browser each time.
As such, your CSS has a problem. By its nature, CSS is static. There is no reason to include it in the expensive process of repopulating with each request/order. Kind of like changing the design on the drive-thru bags each time. You do it once and then use them for several years (the bags are NOT personalized with professional print each time).
So they're kept static -- precompiled (minified) so that it can be downloaded once and then kept in the cache whilst the user browses.
If you need to make your CSS variable (IE it uses backend data), you can include it only if it's available before the files are precompiled. If you're trying to access instance variables, it has to be kept in the views/layout.

Related

How can I use a bundled font in a WebView with React Native on iOS?

In my React Native app I have some information I have stored in a local bundled folder and that I display in a WebView. I want this to work consistently with the rest of the app, so I need to use the same fonts as I use through the rest of the app.
I have this working correctly in Android, but in iOS I can't make it show the fonts at all.
My Webview Screen looks like this:
export class InstructionView extends React.Component<InstructionScreenRouteProp> {
render(): JSX.Element {
let filePath = (Platform.OS === 'android') ? 'file:///android_asset/' : './html/';
filePath += this.props.route.params.file.file + '.html';
return (
<WebView
originWhitelist={['*']}
source={{ baseUrl:'',
uri: filePath }}
startInLoadingState = { true }
/>
);
}
}
My bundle is structured like this:
/html/instructions.html
/html/styles.css
/Resources/MyFont-Regular.ttf
And then the css file font declaration looks like this:
#font-face {
font-family: 'myFont';
src: local('MyFont-Regular'), url('MyFont-Regular.ttf'), format('truetype');
}
h1 {
font-family: 'myFont';
font-size: 2em;
background-color: #622a53;
color: #fffcdc;
padding: 0.5em;
}
I don't think the font would currently work on Android because I've been trying to figure out the iOS version of it, but I have had it working on Android previously by using the explicit path, much like the file path in the render function.
The html is loaded and rendered correctly, the other styles from the stylesheet are applied, it is only the font that is missing.
I have seen various suggestions around this in different places, but none of them satisfy me because they seem to rely on placing the font in the same folder as the html content or even encoding it in the stylesheet, which seems redundant when I already have it included in the app bundle elsewhere. I have tried a lot of different paths in the font-face url and none of them seemed to work, but because of the way React silently caches assets it can be hard to know if I actually saw all the things I tried.
What do I need to do to be able to use an existing font in a WebView on an iOS device?

Vuejs codes display curly braces at a glimpse when switching page, before a new page loaded

i understand v-cloak is used to display nothing when a new page is loaded.
in my rails app, when i try to switch page (i am using vue component in Rails View), there is a short glimpse of Vuejs codes displaying curly braces before another new page is load. i am entirely baffled and not sure if this is turbolink related as there is no error message found in browser console, or in the rails git logs.
this short glimpse of Vuejs displaying curly braces before another page is loaded, is really annoying, can anyone help on this?
v-cloak is used to do this.
official APIļ¼š
[v-cloak] {
display: none;
}
<div v-cloak>
{{ message }}
</div>
tips: written [v-cloak] in #import loaded css file can't work for this problem.
another way: around target tags.
Apart from using [v-cloak] which is a generic way of completely hiding an element until Vue inits, two more usable "tools" are v-text and v-html directives, coupled with computed properties delivering the strings the above directives expect from more complex logic.
Not only do they hide the content until init time, but they can also serve as selectors for the unparsed template elements, as they get removed from the element once Vue parses it. So you could apply backgrounds, width, min-heightto those elements, without the need to spiff your layout with preload classes and remove them on mounted().
An important note here is that transitions won't work on those elements, because Vue purposefully rebuilds the entire DOM of the template once it mounts. If it didn't, enter animations wouldn't work as expected. So there can be no transition from h2[v-text] to h2, because the element is completely replaced. But you can take that into account and start your enter transition from how the [v-text] element was styled.
It's probably not the solution you're looking for (it's more designer's work than programmer's, really) and it's definitely not a magical one liner: it has to be solved on a page by page basis.
But this is how pre-loaders are done (the technique is the same in any modern FE framework, it's just that sometimes you need to spiff your markup with preload classes and remove them on mounted, ngAfterViewInit or componentDidMount).
To be able to style this at your own pace, simply disable JavaScript (or don't init Vue, if you prefer) so you set every detail right. But don't overdo it.
Here's a basic example showing you don't need a whole lot of detail to get a decent effect. It's a matter of roughly matching element heights and coding in some striped CSS backgrounds, really (throw in a blur filter, if you want to get really fancy):
Vue.config.productionTip = false;
Vue.config.devtools = false;
setTimeout(() => {
new Vue({
el: '#app',
data: () => ({
Message: 'Message',
Description: `<p>I'm baby tousled echo park pabst polaroid synth marfa. Migas small batch paleo pop-up street art, chia sriracha cronut ramps succulents portland. YOLO normcore taiyaki organic. Green juice helvetica single-origin coffee polaroid swag selvage schlitz. Artisan la croix unicorn cardigan meh everyday carry wolf thundercats.
<p>Iceland hoodie vice, chicharrones gentrify dreamcatcher ethical jianbing blog truffaut pinterest VHS flannel selfies bushwick. Flannel activated charcoal bespoke master cleanse, chambray tumblr four loko helvetica chicharrones ugh aesthetic irony godard. Beard farm-to-table mumblecore wolf typewriter try-hard shoreditch church-key scenester tousled letterpress yuccie bitters. Selfies +1 man bun, jianbing hell of tote bag crucifix flexitarian. Cronut mumblecore knausgaard meditation authentic lumbersexual listicle pok pok coloring book pitchfork gentrify. +1 offal cronut, flexitarian glossier shoreditch biodiesel stumptown tumeric seitan polaroid.
<p>Narwhal williamsburg adaptogen, four dollar toast retro chillwave occupy kombucha YOLO marfa franzen kogi biodiesel street art next level. Viral blog taxidermy twee echo park roof party. Hammock street art tumeric selvage sartorial. Paleo hashtag activated charcoal, heirloom quinoa cred blog ethical.`
})
})
}, 1000)
#app h2[v-text] {
width: 200px;
background-color: #f8f8f8;
height: 1em;
}
#app div[v-html] {
min-height: 250px;
background-image: repeating-linear-gradient(
180deg,
#fff,
#fff 10px,
#f5f5f5 10px,
#f5f5f5 20px);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2 v-text="Message"></h2>
<div v-html="Description"></div>
</div>
When applying this technique, do not use images, as they require loading as well. Work with CSS only and make sure that CSS is available in <header> (or at least before the app element). Last, but not least, keep in mind your preload has to match your app at all screen widths.

LESS generated CSS not being applied - stumped! (VS 2013 LESS bundling)

I'm completely stumped - what am I missing?
I have a LESS file called Main.less - and VS 2013 automatically generates Main.min.css whenever I save it.
The CSS generated is fine - no errors. When I copy the generated CSS to my Style.css (to verify) it is applied correctly.
I bundle the Main.min.css generated from the LESS file via the usual bundleconfig along with other css files (mainly my bootstrap and site css).
When I run the site, I can see the styles in the referenced bundled source - but the style is not applied! What am I missing?
(here is the .LESS)
#color1: #FFA114;
#color2: #69b1fa;
#std_border: 2px;
.rounded {
border-radius: 10px;
}
.sel_1 {
.rounded;
border: #std_border solid #color1;
}
(here is the .css as it appears in the minified bundle on the browser)
.rounded{border-radius:10px}.sel_1{border-radius:10px;border:2px solid #ffa114}
I can only imagine something is wrong somewhere so that the browsers (latest Chrome and IE) don't even apply the styles. No idea what...
EDIT: UPDATE:
I also referred the generated min.css directly
<link href="/Content/Main.min.css" rel="stylesheet" />
and on browser-> view source -> click on the .css you see the following
.rounded{border-radius:10px}.sel_1{border-radius:10px;border:2px solid #ffa114}.sel_2{border-radius:10px;border:2px solid #ffa114;border-color:#69b1fa}.asel_1{border-radius:10px;border:2px solid #ffa114;border-style:dashed}.asel_2{border-radius:10px;border:2px solid #ffa114;border-color:#69b1fa;border-style:dashed}.map_sel{border:3px double #69b1fa}.line{border-bottom:2px #ffa114 solid;padding:10px}
And the styles are still not applied!

can caching information attached to image file names cause a 404 error?

I deployed a Rails app successfully, however, the images are not displaying. This is the 404 error that's showing in the console
GET http://mydomain.com/assets/myimage.png 404 (Not Found)
Inside my application directory on my server, there's three subdirectories
current releases shared
which is a setup created by the deployment script I borrowed from Ryan Bates.
I can see the images in the images directory of the assets folder in current
current/app/assets/images$ ls
glyphicons-halflings.png glyphicons-halflings-white.png qb.png
However, in the assets folder of the shared directory (which is I'm guessing where they're being put after everything's compiled for production), the same images have some (I'm assuming) cache information attached to them, such that the image I want isn't
myimage.png
but rather
myimage-0bb3f134943971c95b2abdfd30f932c7.png
I'm wondering if this is what's causing the 404 error, as (I'm assuming) the code's looking for myimage.png in the shared/assets directory.
Do you know how I can deal with this problem?
contents of /shared/assets
/shared/assets$ ls
application-39c95ed7b8d86b0698b6c443563e33c7.js fontawesome-webfont-c4adb9424c8b6a6b1b9b0d2627528c4c.woff
application-39c95ed7b8d86b0698b6c443563e33c7.js.gz fontawesome-webfont-f57557847fd1897100790d9df344ded8.ttf
application-7a6376d676fb88537b9f839687ccaad3.css glyphicons-halflings-4e5b89324f1ac987ddf6835ef51f5fe9.png
application-7a6376d676fb88537b9f839687ccaad3.css.gz glyphicons-halflings-white-2fa53df59ca25ee50f59f971c0c9175d.png
application-a184171300937caf263adbc5e8582ba4.css manifest-990c8a24196fee5e9c394078c326c763.json
application-a184171300937caf263adbc5e8582ba4.css.gz myimage-0bb3f134943971c95b2abdfd30f932c7.png
fontawesome-webfont-57b442a30fcae0d4334299c521a326a2.svg twitter
fontawesome-webfont-8140ac47a16c8f7074e59f2ebe0657eb.eot
code used to display images
For one image, I create a span like this
and then assign it a background image
.qb{
position: absolute;
width: 50px;
height: 50px;
background-image: url('/assets/qb.png');
left: 75px;
top: 300px;
}
For another image, I have a template like this with a class that automatically uses Twitter bootstrap to create a x to let uses click and remove a page element
<script id="blahblah_template" type="text/underscore">
<h2> The Story <i class='icon-remove'></i></h2>
It's triggering a 404 even though the image is on the server
Failed to load resource: the server responded with a status of 404 (Not Found)
http://mydomain.com/assets/glyphicons-halflings.png
you should use asset helpers provided by rails which would automagically create the right url to the image with caching build in. here is how:
.qb{
position: absolute;
width: 50px;
height: 50px;
background-image: url( <%= asset_path 'qb.png' %> );
left: 75px;
top: 300px;
}
the above will map qb.png to qb-0bb3f134943971c95b2abdfd30f932c7.png & also update the url once the caching fingerprint changes. just make sure that your stylesheet filename has .erb at the end, something like stylesheet.css.erb
see The Asset Pipeline guide for more information
[edit]
For Bootstrap integration with rails asset pipeline, kindly use gem like bootstrap-sass. it will fix your issues with images

Rails: WickedPDF: Page Breaks

In my Ruby (1.9.2) Rails (3.0.x) I would like to render a web page as PDF using wicked_pdf, and I would like to control where the page breaks are. My CSS code to control page breaks is as follows:
<style>
#media print
{
h1 {page-break-before:always}
}
</style>
However, when I render the page with wicked_pdf, it does not separate the document into two pages. Is there something else that I must do to get page breaks with wicked_pdf?
For some reason, the "#media print" didn't quite do it. I just went with
.page-break { display:block; clear:both; page-break-after:always; }
for the CSS rule, and then I stuck the following in my page for a page break:
<div class="page-break"></div>
That just worked.
Tried Jay's solution but could not get it to work (maybe a conflict with other css)
I got it to work with this:
<p style='page-break-after:always;'></p>
I had the same problem and I discovered something that might help. This was my page break CSS code:
.page-break {
display: block;
clear: both;
page-break-after: always;
}
This didn't work because of TWO reasons:
I. In one of the SASS imported file I had this line of code:
html, body
overflow-x: hidden !important
II. The other problem was bootstrap
#import "bootstrap"
It looks like because of the float: left in:
.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
float: left;
}
the page break is no longer working. So, just add this after you import bootstrap.
.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
float: initial !important;
}
None of these solutions worked for me. I did find a solution that worked for many people in the gem issues here - https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1524
you want to add CSS on the element that needs the page break. In my case, it was table rows, so I added:
tr {
page-break-inside: avoid;
}
Make sure that the stylesheet link tag includes media='print" or media='all' if you are using an external stylesheet:
<%= stylesheet_link_tag 'retailers_pdf',media: 'all' %>
or
<%= stylesheet_link_tag 'retailers_pdf',media: 'print' %>
otherwise wicked_pdf will not pick it up.
Also note that if you are in the middle of a table or div with a border, that the page-break attributes will not work. In this case, it's time to break out jQuery and start splitting things up. This answer: https://stackoverflow.com/a/13394466/2016616 has a good snippet for position measurement. I am working on clean and repeatable table-splitting code and will post it when I have finished it.
i had the same issue and what ended up working for me was to make sure that my element with
page-break: always;
was on the root of the document, seems when its nested inside of other elements, especially ones with height assigned, the declaration gets ignored.
hope this helps someone.

Resources