Is there a way to uri encode a link in shopify:
http://www.tumblr.com/share?v=3&u={{ shop.url }}{{ article.url }}
Building out share buttons and tubmlr doesn't like that they are not encoded.
Not sure if it was recently added, but url_param_escape seems to do exactly what you want. This worked for me:
{{ shop.url | append: article.url | url_param_escape }}
My crude attempt is as follows:
{{ article.url | replace: ' ', '%20' | replace: '&', '%26' | replace: '?', '%3F' | replace: '!', '%21' | replace: ',', '%2C' | replace: "'", "%27" }}
and so on. I haven't mastered the art of writing liquid functions yet.
Unfortunately Shopify does not provide any filters to encode a URI. Your best bet is to use Javascript. For example add data-url="{{ shop.url }}{{ article.url }}" attribute to your HTML markup and give it a unique ID then script:
var x=document.getElementById("uniqueID");
if (x != null) {
var url='http://www.tumblr.com/share?v=3&u='+encodeURIComponent(x.getAttribute("data-url"));
x.setAttribute("href", url);
}
Call it in self invoking or at document ready if you like. Set href in HTML to whatever you wish for non-javascript browsers. You could consider using the Tumblr icon widget builder:
http://www.tumblr.com/buttons and their official JS because you never know when the link syntax may change
Bit late to the party here, but for anyone wondering, Shopify now has a filter for this built in.
{{ my_var | url_param_escape }}
So, in the case above, you could do:
{% capture my_escaped_url %}
{{ shop.url }}{{ article.url }}
{% endcapture %}
http://www.tumblr.com/share?v=3&u={{ my_escaped_url | url_param_escape }}
Hope this helps someone. You can read more here:
https://help.shopify.com/themes/liquid/filters/string-filters#url_param_escape
I ended up doing this using Tumblr's build a button widget and then modifying the JS slightly. Since I wanted to use the Tumblr icon from Font Awesome/Bootstrap, I simply deleted the style attributes that the JS assigns and then assigned the appropriate class to the anchor the JS creates. Instructions are as follows:
1. Get the code:
Choose a random button style (this won't matter because you'll end up deleting the code that specifies the background-image), set the post type to "photo", and select "Javascript" as the programming language (the last two option are found under the "Advanced" accordion). Once you've done that, Tumblr will spit out some code, which you can then modify.
2. Create a new snippet:
Create a new snippet in your theme's editor and then copy and paste in the scripts found in steps 1 and 3 of the button builder.
<script src="http://platform.tumblr.com/v1/share.js"></script>
<!-- Set these variables wherever convenient -->
<script type="text/javascript">
var tumblr_photo_source = "";
var tumblr_photo_caption = "";
var tumblr_photo_click_thru = "";
</script>
<!-- Put this code at the bottom of your page -->
<script type="text/javascript">
var tumblr_button = document.createElement("a");
tumblr_button.setAttribute("href", "http://www.tumblr.com/share/photo?source=" + encodeURIComponent(tumblr_photo_source) + "&caption=" + encodeURIComponent(tumblr_photo_caption) + "&clickthru=" + encodeURIComponent(tumblr_photo_click_thru));
tumblr_button.setAttribute("title", "Share on Tumblr");
tumblr_button.setAttribute("style", "display:inline-block; text-indent:-9999px; overflow:hidden; width:20px; height:20px; background:url('http://platform.tumblr.com/v1/share_4.png') top left no-repeat transparent;");
tumblr_button.innerHTML = "Share on Tumblr";
document.getElementById("tumblr_button_abc123").appendChild(tumblr_button);
</script>
3. Customize the JS:
First, set the variables. Then, you can specify your background image or icon for the anchor. Like I said above, I'm using the Tumblr icon from Font Awesome, so I just deleted all of the style attributes, the innerHTML, and assigned a class of "fa fa-tumblr".
If you want to use a background-image, you could simply replace the URL with your image's and tweak the height and width properties.
<script src="http://platform.tumblr.com/v1/share.js"></script>
<script type="text/javascript">
var tumblr_photo_source = "{{ product.featured_image | product_img_url: "master" }}";
var tumblr_photo_caption = "";
var tumblr_photo_click_thru = "{{ shop.url | append: product.url }}";
</script>
<script type="text/javascript">
var tumblr_button = document.createElement("a");
tumblr_button.setAttribute("class", "fa fa-tumblr");
tumblr_button.setAttribute("href", "http://www.tumblr.com/share/photo?source=" + encodeURIComponent(tumblr_photo_source) + "&caption=" + encodeURIComponent(tumblr_photo_caption) + "&clickthru=" + encodeURIComponent(tumblr_photo_click_thru));
tumblr_button.setAttribute("title", "Share on Tumblr");
document.getElementById("tumblr_button_abc123").appendChild(tumblr_button);
</script>
4. Include the button and snippet in your HTML:
Last, paste the code below wherever you want your button to show up.
<!-- Put this tag wherever you want your button to appear -->
<span id="tumblr_button_abc123"></span>
And add the snippet just before the </body> in your theme.liquid file.
<!-- Scripts for Tumblr Share Button -->
{% include 'your-tumblr-script-name' %}
Related
For example passing in a snippet
{% include 'icon-top', classes:'back-to-top__icon' %}
I can pass the class back-to-top__icon into icon-top snippet
<svg class="icon {{ classes }}" somesvg stuff here ></svg>
Doing the same with a section doesn't work - is there any way to do this in liquid?
Sections doesn't accept anything outside of the section file. You can look the section like a closed platform nothing comes inside or outside of the section.
The means that variables created outside/inside the section are not accessible inside/outside of it.
That said you can hack it slightly to achieve what you want.
For example:
The section file:
test.section.liquid
The section file code:
<div class="{{dummy_class}}"></div>
Then you call the section this way:
<div style="display: none;">
{% section 'test.section' %}
</div>
{% capture section_capture %}
{% section 'test.section' %}
{% endcapture %}
{{ section_capture | replace: '{{dummy_class}}', 'back-to-top__icon' }}
Clarification
You might be asking why are we calling the section two times?
When we call the section in a {% capture %} tag it's not shown in the admin panel that's why are showing it in a hidden div only to show it in the admin and we don't do anything else with it.
After that we capture the section in a variable section_capture, this will return the content of section and we can replace anything we want in there.
That's why we added this {{dummy_class}} dummy variable. It's wrapped in liquid but you can treat it as text and not liquid, so we can write it like so #dummy_class# as well.
After that we just target that string and replace it {{ section_capture | replace: '{{dummy_class}}', 'back-to-top__icon' }}
I am creating a blog site using the Wagtail CMS. I would like to display the Author avatar image whenever a new post is published. I am trying to render the image from this /admin/account/change_avatar/ location. I can see the image uploaded here is under the wagtailusers_userprofile -> col name: avatar table, but not sure how to render it in the template.
This image isn't a typical Wagtail Image (one that comes from wagtailimages.Image), this looks like a regular models.ImageField.
Here's what's in the UserProfile model for the avatar:
class UserProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='wagtail_userprofile'
)
avatar = models.ImageField(
verbose_name=_('profile picture'),
upload_to=upload_avatar_to,
blank=True,
)
Because this is a regular image field, you can get the url by appending .url in your template.
Here's some example template code:
{% if request.user.is_authenticated %}
{% if request.user.wagtail_userprofile.avatar %}
<img src="{{ request.user.wagtail_userprofile.avatar.url }}" alt="{{ request.user.get_full_name }}">
{% else %}
{# No image #}
{% endif %}
{% endif %}
The above code will check to see if the user is authenticated in the template. If you don't need it, ditch it.
THen there's the if statement to checks of the request.user.wagtail_userprofile.avatar exists. The wagtail_userprofile comes from the user field on the UserProfile model. It's using a related_name, so we use that in the template.
I also sprinkled in a {{ request.user.get_full_name }} for the alt tag, because the image alt should probably be the users name in this case, rather than the file name.
If you need the height or width, those are both available through the {{ request.user.wagtail_userprofile.avatar.height }} and {{ request.user.wagtail_userprofile.avatar.width }}.
I have an application that creates several "bokeh" plots. Those plots all belong to the same document, so that i can use linked panning / zooming. The plots are served by a "bokeh" server. All plots appear in one website but there is some html content between the plots. All of that is part of a django app. Using bokeh-0.12.1
#view.py
plots = []
plot1 = figure()
plot1.line([1,2,3],[5,4,2])
plot2 = figure()
plot3.line([1,2,3],[5,4,2])
script_tags = []
bokeh_document = curdoc()
session = push_session(bokeh_document)
script.tags.append(autoload_server(model=plot1, session_id=session.id))
script.tags.append(autoload_server(model=plot2, session_id=session.id))
Then in the template would look as follows:
template.html
<h1>These are the embedded server plots</h1>
{% for script in script_tags %}
<pre>{{ subgroup_plot.script }}</pre>
<h1>Here comes a plot</h1>
some Text
<div>
{{script | safe }}
</div>
{% endfor %}
But then the page gets rendered imporperly... The plots appear over each other and over the page content. The documentation does not mention how to embedd it in html. So how does it have to be done so that the css works correctly?
It looks like there are missing some CSS classes, namely bk-root and plotdiv. Try the following:
<h1>These are the embedded server plots</h1>
{% for script in script_tags %}
<pre>{{ subgroup_plot.script }}</pre>
<h1>Here comes a plot</h1>
some Text
<div class=“bk-root">
<div class=“plotdiv">
{{script | safe }}
</div>
</div>
{% endfor %}
Also refer to the CSS file to see the correct order/nesting of classes.
autoload_server had an issue in 0.12.1 that prevented the correct enclosing <div class="bk-root"> from appearing. This issue was fixed in 0.12.2, you can either upgrade, or put them in by hand as the other issue demonstrates.
I have a collection of components in my site, they are populated with contents that are being specified by variables in a .yml file.
site.components/button.html
---
title: Button
---
{% assign yml = 'sample' %}
{{ site.data.[yml].button }}
data/sample.yml
#variables
button: Click Me
When I open the url /button.html the variable works nicely:
#Page Output
<html>
Click Me
</html>
Q: Is there any way to overwrite the variable when the component is used in a page? eg:
---
title: A Sample Page
---
{% assign yml = 'content'%}
{{ site.components | where:"title" : "Button" }}
data/content.yml
#variables
button: Join Now
/sample-page.html
#Page Output
<html>
Join Now
</html>
Note the components are not includes.
Answer is NO.
When you do a {{ site.components | where:"title" : "Button" }} you get an array of Jekyll Documents that match the title. Those documents are already liquid parsed. You cannot instruct jekyll to parse them again.
The only way is to use includes and pass them variables.
_includes/button.html
{{ site.data.[include.text].button }}
_components/button.html
---
title: Button
---
{% include button.html text='sample' %}
sample-page.html
---
title: A Sample Page
---
{% include button.html text='content' %}
I have a requirement, where in I have 4 different drop down on shopify home page. The First drop-down, let's name it city-drop-down, will show list of city. Based on the city selected in city-drop-down, the second drop down, lets name it category-drop-down, will show list of categories available for particular city. Similarly the third drop down should show the value based on the 2nd drop down and 4th drop down should show the value based on 3rd drop down.
Basically, I need to store list of categories available for each city. Similarly I have to store values available for each categories. How can I store this value, so that the moment a value is selected on webpage, I can use a AJAX call to get the available data for next drop down.
Edited *****
Do let me know, if I am doing it totally wrong.
Included the scripts. Please note, initially I uploaded the files under "Files". However I moved it to Assets folder as it was easier to edit the file in Assets folder.
function readcityfile(){
var xmlhttp = new XMLHttpRequest();
var url = "/assets/city_type.txt";
alert("hi");
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
try{
var myArr = JSON.parse(xmlhttp.responseText);
alert(myArr);
//myFunction(myArr);
}
catch(err) {
alert(err.message);
}
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
function myFunction(arr) {
var i;
for(i = 0; i < arr.length; i++) {
alert(arr[i].city);
}
}
And the JSON file is -
[{"city": "Jamshedpur","types": "Sweets#Savories#Cake"},{"city": "Ranchi","types": "Sweets#Savories#Cake"}]
One simple way if the data size isn't too large would be to generate your data as a JSON file and simply store it as a file and then edit your theme to include the file's url. A file that is too large might be 100k. Smaller is better but if you don't have a back end to handle the AJAX calls the static file certainly provides a low cost proof of concept.
There are two ways to do this.Either as an asset or a file. Assets are part of your theme so even though you'll be altering your templates to manage this I'd tend to go with a file. (Assets are just files located under the theme but the are dealt with slightly differently)
go to your Shopify Admin control panel
Click Settings
Click Files
Click "Upload Files"
After upload you'll have a file. The next step uses the file's name not its URL.
Go to your theme editor:
Shopify Admin control panel
Online Store
Themes
click Customize Theme
drop-down Theme Options and select HTML/CSS
I'm guessing you are going to select the template product.liquid to edit.
do that and decide where you want to introduce your javascript file. If your script file was named cities_etc.js you'd import it as below:
{{ 'cities_etc.js' | file_url | script_tag}}
This method seems a bit slow if all that you are trying to do is create a tiered menu. Using Ajax requests will mean there are several round trips and it will be visually slow for the user waiting for the ajax request to complete.
You can create a linklist
I know you have already found your method but I would strongly urge you to give this a go. Here is an example of some liquid markup that will created a tiered menu. The parent linklists handle is main-menu then you need to create a linklist for each of the children where the handle matches the title in the main-menu. For example if you have an 'About Us' link in the main menu create a linklist also with the handle 'about-us'. Then just use some simple css or javascript to hide and show the menus on hover.
{% for link in linklists.main-menu.links %}
{% assign child_list_handle = link.title | handleize %}
{% if linklists[child_list_handle].links != blank %}
<li class="dropdown" aria-haspopup="true" data-id="{{ child_list_handle}}">
<a href="{{ link.url }}" class="nav-link {% if link.active %} active{% endif %}">
{{ link.title }}
</a>
<ul class="dropdown_menu hidden" id="{{ child_list_handle }}">
{% for childlink in linklists[child_list_handle].links %}
<li>
{{ childlink.title | escape }}
</li>
{% endfor %}
</ul>
</li>
{% else %}
<li>
{{ link.title }}
</li>
{% endif %}
{% endfor %}