Is there a way to get an image overlay over a selected radio button on Shopify (Liquid)? - shopify

A client wants me to make an image overlay over the selected radio button, so when Size Small, for example, is selected, instead of a highlighted button, and image will show up in its place. See image below. Let me know!! been trying to figure this out for like 5 days!! Thanks.
enter image description here

This looks like something that would just need a little bit of clever HTML/CSS structure.
For example:
.product-option{
position: relative;
display: inline-block;
}
.product-option__input{
display: none;
}
.product-option__label{
padding: 0.25em 1.5em;
display: inline-block;
cursor: pointer;
border: 1px solid black;
border-radius: 4px;
}
.product-option__input:checked ~ .product-option__label{
/* Some nice styles to highlight the selected option? */
background-image: url('/some-nice-background.png');
color: transparent; /* If you want to make the text go away for some reason? */
border-color: darkgreen;
/* Etc. */
}
.product-option__input:checked ~ .product-option__label:after{
/* Maybe we want something that we can position independently? */
position: absolute;
content: '';
border: 2px solid green;
border-radius: 50%;
width: 2.5em;
height: 2.5em;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
background: linear-gradient(-0.125turn, green, lightgreen);
}
<!--
In Liquid, this HTML would be generated with a forloop similar to the following:
{% for option in product.options_with_values %}
<div class="product-option-wrapper">
{% for value in option.values %}
{% assign unique_option_id = 'option_' | append: product.id | append: '-' | append: option.position | append: '-' | append: forloop.index %}
<div class="product-option>
<input class="product-option__input" id="{{ unique_option_id }}" name="{{ option.name }}" value="{{ value | escape }}" {% if value == option.selectd_value %}checked{% endif %} />
<label class="product-option__label" for="{{ unique_option_id }}">
<span class="product-option__text">{{ value }}</span>
</label>
</div>
{% endfor %}
</div>
{% endfor %}
-->
<div class="product-option">
<input class="product-option__input" id="option1-small" type="radio" name="option1" value="small"/>
<label class="product-option__label" for="option1-small">
<span class="product-option__text">Small</span>
</label>
</div>
<div class="product-option">
<input class="product-option__input" id="option1-med" type="radio" name="option1" value="med"/>
<label class="product-option__label" for="option1-med">
<span class="product-option__text">Med</span>
</label>
</div>
<div class="product-option">
<input class="product-option__input" id="option1-lg" type="radio" name="option1" value="lg"/>
<label class="product-option__label" for="option1-lg">
<span class="product-option__text">Large</span>
</label>
</div>
<!-- etc -->
This should hopefully be enough to get you started and let your imagination run wild with all the cool things you can do with just some simple HTML/CSS running together :)

Related

Shopify Template - Color Swatches using links not variants

I'm currently working on a Shopify project and I need to add color swatches on the product pages. I already did it in other projects using the product variants. But in this case the colors are different products. I found some examples on shopify:
Fashion Nova.
doyoueven.
In those examples when you click on a color you want, it changes the page. In the code it's a simple html link to the other products.
These brands are maybe using an app but I'm not sure.
Thanks.
I did that with an App for a swim suit company. Due to the way their navigation worked, it was clear they had a product per color. Not a color per variant. The App I provided them was for curated links. So they could connect all the same products with the different colors, and easily provide clickable links to each, making for a super easy way to manage inventory.
I did some test and I came up with an idea. I still need to work on it but I think maybe it could be a solution.
I am using tags to linked the products together. I need to test with more product how it's working but it could be a good start.
<div class="swatches">
<label>Colors</label>
<br />
<div class="related-colors">
{% for relatedProduct in collections.all.products %}
{% if product.tags contains relatedProduct.handle %}
{% for tag in relatedProduct.tags %}
{% if tag contains 'color-' %}
{% assign color = tag | replace: 'color-', '' %}
<a href="{{ relatedProduct.url }}">
<div class="color-swatches" style="background-color: {{color}}"></div>
</a>
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
</div>
</div>
<style>
.swatches{
width:100%;
padding-left:5px;
}
.color-swatches
{
margin-top:10px;
display: inline-block;
margin-right: 0px;
margin-bottom: 10px;
width: 30px;
height: 30px;
border: 1px solid #dedede;
border-radius: 30px;
}
</style>

Multi-line add-on for textarea

I'm using bootstrap 4 input-group and appending or pretending my inputs with add-ons as labels.
For the inputs its looking good. Now I need a multi-line add-on or label for text area.
I'm looking for best possible solution in Bootstrap or CSS.
Here is the code I'm trying.
<style>
.h-unset {
height: unset !important;
}
.multiline-label {
display: inline-block;
word-wrap: break-word;
word-break: break-word;
width: 100%;
}
</style>
<div class="input-group input-group-sm mb-3 row mx-0">
<div class="input-group-prepend col-md-3 px-0">
<label for="naastVastgoedbeleg-ging"
class="input-group-text w-100 rounded-0 multiline-label h-unset"
id="label-naastVastgoedbeleg-ging">
<strong>Werkzaamheden naast vastgoedbeleg-ging (bijv. loondienst of onderneming)</strong>
</label>
</div>
<textarea id="naastVastgoedbeleg-ging"
class="form-control rounded-0 col-md-9 h-unset"
aria-label="naastVastgoedbeleg-ging"
aria-describedby="label-naastVastgoedbeleg-ging">
</textarea>
</div>
Thankx for helping Happy Coding!
It worked by using this css
.multiline-label strong {
white-space: pre-wrap;
}

Safari flex-box

Trying to make responsive layout for my app with flexbox.
Flexbox working incorrect at safari.
When direction is row, all working right.
But for column layout broken. Having not idea why.
Already tried changing prefixes.(not autoprefix problem)
At chrome: gif
At safari: gif
sass:
$right-section-color: #98ee99
$left-section-color: fade_out(grey,0.8)
$font-color: fade_out(black,0.3)
.AllSection
width: 100%
color: $font-color
.Banner
#extend .BannerSection
.section
display: flex
justify-content: center
flex-direction: row
span
margin: auto
padding: 0
flex: 1
.imageWithText
flex: 1
margin: auto
display: flex
flex-direction: column
text-align: center
img
max-width: 10em
height: 100%
width: 100%
margin: auto
.text
flex: 1
margin: auto
#for $i from 1 through 5
#if($i % 2 == 0)
.section:nth-child(#{$i})
background-color: $left-section-color
#media #{$small-and-down}
flex-direction: column
#else
.section:nth-child(#{$i})
background-color: $right-section-color
#media #{$small-and-down}
flex-direction: column-reverse
jsx:
<Element name="AllSection" className="AllSection">
<div className="Banner">
<h3>Диспоузер Status це</h3>
</div>
<div className="section">
<div className="imageWithText">
<img src={ecoLogo} id='ecoLogo' alt="eco logo" />
<span>Екологічно</span>
</div>
<div className="text">
<span>Використання подрібнювача скорочує обсяг перевезеного на звалища сміття. Крім того, харчові
відходи є сировиною для виробництва біогазу. </span>
</div>
</div>
<div className="section">
<div className="text">
<span>Подрібнювачі миттєво усувають харчові відходи c кухні. Тепер не потрібно зберігати їх в сміттєвому відрі - джерелі неприємних запахів і бактерій.</span>
</div>
<div className="imageWithText">
<img src={wastedFood} alt="wasted food" />
<span>Гігієнічно</span>
</div>
</div>
<div className="section">
<div className="imageWithText">
<img src={kitchenPicture} alt="kitchen washer" />
<span>Практично</span>
</div>
<div className="text">
<span>Подрібнювач акуратно і легко встановлюється під раковину і не вимагає додаткових площ на
кухні. </span>
</div>
</div>
<div className="section">
<div className="text">
<span>Подрібнювач абсолютно безпечний для дітей і дорослих. Всередині немає ножів і шнеків.
Додаткову електробезпеку забезпечує пневмовимикач. </span>
</div>
<div className="imageWithText">
<img src={safetyIcon} alt="wasted food" />
<span>Безпечно</span>
</div>
</div>
</Element>
App created by react-create-app, so i have autoprefixer.
How can I fix this layout in safari?
UPDATE:
When setting width to 50% of element i want to layout, all working.
But how can i make it with flex: 1?

Iterating products in shopify product-loop.liquid

I have a problem with displaying a collection of products with a help of snippet product-loop.liquid in Shopify. The code is basically the following.
{% capture collection_handle %}{{ product-loop | handleize }}{% endcapture %}
{% capture url %}{% if collection_handle != "" %}/collections/{{ product-loop }}{{ product.url }}{% else %}{{ product.url }}{% endif %}{% endcapture %}
<div class="product span3 {% if template == 'collection' %}adaptive-grid{% endif %}">
</div>
{% unless template contains 'collection' %}
{% cycle 'clear-product-loop': '', '', '', '<div style="clear:both;"></div>' %}
{% endunless %}
The result is one row is 2 items or 3 items or 4 items (depending on screen resolution) and the next row is always 1 item and this pattern is repeating all the time. What is wrong?
EDIT: Some related CSS
.row { margin: 0 0 30px 0; }
.span1, .span2, .span3, .span4, .span5, .span6, .span7, .span8, .span9, .span10, .span11, .span12 { display: block; float: left; margin: 0 15px; }
.inner-left { margin-left: 0px !important; }
.inner-right { margin-right: 0px !important; }
.span1 { width: 53px; }
.span2 { width: 136px; }
.span3 { width: 219px; }
.span4 { width: 302px; }
.span3.adaptive-grid {width: 219px;}
.span3.adaptive-grid:nth-child(6n+7) {clear: none;}
.span3.adaptive-grid:nth-child(4n+5) {clear: both;}
Finally I resolved my problem by removing lines like
.span3.adaptive-grid:nth-child(6n+7) {clear: none;}
.span3.adaptive-grid:nth-child(4n+5) {clear: both;}
from Shopify styles file (Minimal theme). Now the grid of products is displayed ok for different resolutions without breaking the lines.

Vaadin with JQuery FileUpload

I would like to create FileUploader with Vaadin . But I need to get more features over normal Vaadin Upload.
beautiful and easy to manage (but optional)
fast and never failed while uploading
include progress bar
show preview
multi file upload support
upload file size and type restriction
drag and drop
client-side image resizable (it is main feature for me because all of my uploaded files were images)
There has an addon MultiFileUpload. Yes , it is perfect for most of my requirements but not for client-size image resizing. So I decided to use JQuery FileUpload because it is support for Client side Image Resizing.
I used vaadin Window for upload image. But I got a problem while creating my window , very hard to create each HTML elements respectively (may be I have less exp). So I used CustomLayout with HTML for easy to create and edit design of my image uploader window.
Below is my custom layout HTML file. (two scripts were templates for image preview)
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload">
<td width="100px" align="center">
<span class="preview"></span>
</td>
<td width="400px" align="center">
<p class="name">{%=file.name%}</p>
{% if (!o.files.error) { %}
<div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="bar" style="width:0%;"></div></div>
{% } %}
{% if (file.error) { %}
<div><span class="label label-important">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td width="100px" align="center">
{% if (!i) { %}
<button style="display: none;" class="start" type="button">
<span>Start</span>
</button>
<div class="v-button v-widget cancel" type = "button">
<span class="v-button-wrap" style="color: red;">
<span class="v-button-caption">Cancel</span>
</span>
</div>
{% } %}
<br>
{%=o.formatFileSize(file.size)%}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download">
<td width="100px" align="center">
<span class="preview">
{% if (file.path) { %}
<img src="../{%=file.path%}" width="100px">
{% } %}
</span>
</td>
<td width="400px" align="center">
<p class="name">
{%=file.name%}
</p>
{% if (file.error) { %}
<div><span class="label label-important">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td width="100px" align="center">
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
</tr>
{% } %}
</script>
<table cellpadding="5" style="width: 100%;">
<colgroup>
<col>
</colgroup>
<tbody>
<tr>
<td width="90px">
<div style="text-align: right; width: 120px;">UploadPhoto :</div>
</td>
<td>
<div id="pnlProgress" aria-valuenow="0" aria-valuemax="100" aria-valuemin="0" style="display: none;" class="progress progressall progress-success progress-striped active">
<div style="width: 0%;" class="allbar" id="pnlProgressBar"> </div>
</div>
</td>
</tr>
<tr>
<td colspan="3">
<div id="imageForm" style="width: 600px;">
<form id="fileupload">
<div style="margin-bottom: 10px; border: 1px solid #DDD; width: 600px; height: 300px; overflow: scroll">
<table cellspacing="0" cellpadding="5">
<tbody class="files"></tbody>
</table>
</div>
<div style="margin-bottom: 10px;" class="fileupload-buttonbar">
<div class="v-button v-widget btnPlus">
<span class="v-button-caption">Add Files</span>
<input type="file" multiple="" name="files[]">
</div>
<div class="v-button v-widget start" type = "submit">
<span class="v-button-wrap">
<span class="v-button-caption">StartUpload</span>
</span>
</div>
<div class="v-button v-widget cancel" type = "reset">
<span class="v-button-wrap">
<span class="v-button-caption">Cancel All</span>
</span>
</div>
</div>
<div style="border: 1px solid #999; width: 600px; height: 100px;" id="dropZone">
<div class="carPhotoDropMsg">
Draft & Drop Photos<br>(jpg, jpeg, png, gif only)
</div>
</div>
</form>
</div>
</td>
</tr>
</tbody>
Below is for ImageUpload window
public final class ImageUploadDialog extends CustomComponent {
private Window window;
public void show() {
UI.getCurrent().addWindow(window);
// 123 is seq for save in database or other use
Page.getCurrent().getJavaScript().execute("initImageuploader(123)");
}
public ImageUploadDialog() {
CustomLayout layout = new CustomLayout("imageUploadLayout");
window = new Window("Uploading Photos");
window.center();
window.setWidth("615px");
window.setModal(true);
window.setResizable(false);
window.setClosable(true);
window.setContent(layout);
}
}
And below is my upload.js file for initialize my image uploader
function initImageuploader(seq) {
$('#fileupload').fileupload({
url : 'photo/upload.html?s=' + seq,
sequentialUploads : true,
disableImageResize : false,
imageMaxWidth : 1024,
imageMaxHeight : 1024,
previewCrop : true,
dropZone : $("#dropZone"),
acceptFileTypes : /(\.|\/)(gif|jpe?g|png)$/i,
progress : function(e, data) {
if (data.context) {
var progress = data.loaded / data.total * 100;
progress = Math.floor(progress);
$('.progress').attr('aria-valuenow', progress);
$('.progress').css('display', 'block');
$('.bar').css('width', progress + '%');
}
},
progressall : function(e, data) {
var progress = data.loaded / data.total * 100;
progress = Math.floor(progress);
$('.progressall').attr('aria-valuenow', progress);
$('.progressall').css('display', 'block');
$('.allbar').css('width', progress + '%');
if (progress > 20) {
$('.allbar').text(progress + '% Completed');
}
},
stop: function (e) {
return;
}
});
}
And you need additional javascripts files for image uploader and I imported them at my UI class as below
#JavaScript({ "vaadin://themes/myproject/js/load-image.min.js",
"vaadin://themes/myproject/js/tmpl.min.js",
"vaadin://themes/myproject/js/jquery/jquery-1.10.1.min.js",
"vaadin://themes/myproject/js/jquery/vendor/jquery.ui.widget.js",
"vaadin://themes/myproject/js/jquery/jquery.iframe-transport.js",
"vaadin://themes/myproject/js/jquery/jquery.fileupload.js",
"vaadin://themes/myproject/js/jquery/jquery.fileupload-ui.js",
"vaadin://themes/myproject/js/jquery/jquery.fileupload-process.js",
"vaadin://themes/myproject/js/jquery/jquery.fileupload-image.js",
"vaadin://themes/myproject/js/jquery/jquery.fileupload-validate.js",
"vaadin://themes/myproject/js/canvas-to-blob.min.js",
"vaadin://themes/myproject/js/upload.js" })
#StyleSheet({ "vaadin://themes/myproject/css/jquery-ui-1.10.3.custom.min.css",
"vaadin://themes/myproject/css/imageUpload.css" })
public class EntryPoint extends UI {
..............
}
Please Notice for JS Files Order !
Below is my Custom CSS file for image upload window (imageUpload.css)
table.upld-status {
display: none;
}
.fileupload-buttonbar .btnPlus {
float: left;
position: relative;
overflow: hidden;
color: blue;
text-align: center;
margin-right : 10px;
}
.fileupload-buttonbar .btnPlus input {
margin: 0px;
position: absolute;
top: 0px;
right: 0px;
line-height: 30px;
font-size: 23px;
direction: ltr;
opacity: 0;
}
.carPhotoDropMsg {
color: #DDD;
font-size: 20pt;
height: 82%;
padding: 9px;
text-align: center;
}
.progress {
background-color: #F7F7F7;
background-image: linear-gradient(to bottom, #F5F5F5, #F9F9F9);
background-repeat: repeat-x;
border-radius: 4px 4px 4px 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset;
height: 17px;
overflow: hidden;
}
.progress-success.progress-striped .bar, .progress-success.progress-striped .allbar, .progress
striped .bar-success {
background-color: #62C462;
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.progress.active .bar, .progress.active .allbar {
animation: 2s linear 0s normal none infinite progress-bar-stripes;
}
.progress-success .bar, .progress-success .allbar, .progress .bar-success {
background-color: #5EB95E;
background-image: linear-gradient(to bottom, #62C462, #57A957);
background-repeat: repeat-x;
}
.progress-striped .bar, .progress-striped .allbar {
background-color: #149BDF;
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-size: 40px 40px;
}
.progress .bar, .progress .allbar {
-moz-box-sizing: border-box;
background-color: #0E90D2;
background-image: linear-gradient(to bottom, #149BDF, #0480BE);
background-repeat: repeat-x;
box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.15) inset;
color: #FFFFFF;
float: left;
font-size: 12px;
height: 100%;
text-align: center;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
transition: width 0.4s ease 0s;
width: 0;
}
I need server-side control for save image . You need two jars apache-common-io and apache-common-fileupload. Below is for maven repository of these two jars.
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
Finally , below is codes for server-side control .
#WebServlet(value = "/photo/upload.html")
public class UploadServletController extends HttpServlet {
protected final void doPost(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
PrintWriter out = response.getWriter();
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> fields = null;
try {
fields = upload.parseRequest(request);
}
catch (FileUploadException e) {
throw new RuntimeException("Error Parsing File Item " + e.getMessage(), e);
}
if (fields != null) {
String message = uploadPhoto(request, fields);
out.write(message);
}
}
public final synchronized String uploadPhoto(final HttpServletRequest request,
final List<FileItem> sessionFiles) {
List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>();
for (FileItem item : sessionFiles) {
if (!item.isFormField()) {
Long seq = Long.parseLong(request.getParameter("s"));
// get from vm arguments (eg:-DstaticDir=/Applications/springsource/workspace/myproject/src/main/webapp)
String staticDir = System.getProperty("staticDir");
Date today = new Date();
SimpleDateFormat fmtYMD = new SimpleDateFormat("/yyyyMMdd/HH");
SimpleDateFormat fmtHMS = new SimpleDateFormat("HHmmssS");
String saveDir = "data/photo" + fmtYMD.format(today);
String format = ".jpg";
try {
format = item.getName().substring(item.getName().lastIndexOf("."), item.getName().length())
.toLowerCase();
}
catch (Exception e) {
// nothing to do!
}
String fileName = seq + "_" + fmtHMS.format(today) + format;
Map<String, Object> res = new HashMap<String, Object>();
// Save image in specify location
String filePath = staticDir + "/" + saveDir;
saveFile(filePath, fileName, item);
res.put("seq", seq);
res.put("path", saveDir + "/" + fileName);
res.put("ext", format.substring(1));
res.put("name", item.getName());
res.put("size", item.getSize());
ret.add(res);
}
}
Map<String, Object> result = new HashMap<String, Object>();
result.put("files", ret);
JSONObject obj = new JSONObject(result);
return obj.toString();
}
public static String saveFile(final String filePath, final String fileName, final FileItem item) {
File file = new File(filePath);
if (!file.exists()) {
file.mkdirs();
}
File imageFile = new File(file, fileName);
try {
item.write(imageFile);
}
catch (Exception e) {
e.printStackTrace();
}
item.setFieldName(filePath + fileName);
return item.toString();
}
}
I know my codes may have risks and some weakpoints . Every suggestions were welcome . But I believe there has some useful for newbie (I am also a newbie). Sorry for too long and bad format.
The last thing is my problem ....
Why preview image (after upload not before upload) automatically include url instead of filepath ? I got image not found error
"NetworkError: 404 Not Found - http://localhost:8080/myproject/VAADIN/themes/myTheme/data/photo/20140723/23/123_235918346.jpg"
Actually this image path should be data/photo/20140723/23/111_235918346.jpg. I have no idea why prefix url http://localhost:8080/myproject/VAADIN/themes/myTheme/ was automatically include (may be due to my CustomLayout HTML file path) ? File paths were got from HTTP response (with JSON). I think it is due to VAADIN because it works on my GWT project or may be I am wrong. Any suggestions ? Thanks for reading my question.
I fixed it by repairing src value of preview template for after upload image as ...
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) {; %}
<tr class="template-download">
<td width="100px" align="center">
<span class="preview">
{% if (file.path) { %}
<img src="/myproject/{%=file.path%}" width="100px">
{% } %}
</span>
</td>
<td width="400px" align="center">
<p class="name">
{%=file.name%}
</p>
{% if (file.error) { %}
<div><span class="label label-important">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td width="100px" align="center">
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
</tr>
{% } %}
</script>
Now everythings were fine. If you didn't see image immidiately , please check your IDE (Eclipse or STS) setting as below
Preference > General > Workspace
and check checkboxes Refresh on access and Refresh using native hooks or polling.