Gatsby: set an image background through frontmatter, GraphQl and Styled-components - graphql

I know this problem sounds a bit complex but it's not.
I'll try my best to explain it in a simple way:
I'm making a list of blog posts for the homepage of my Gatsby website.
The list is made of "boxes", every box that links to a post has a background-image.
I pass this background-image to a styled-component, it gets the image from a prop value that I inserted in the main < div > element (you'll find the example bellow).
It works fine, till I try use an image from my local folder under src (instead of using an online link that I simply putted on frontmatter).
Here's what I did in the past, and worked:
I put the url of the image on the frontmatter of the markdown file:
---
slug: "/post/my-post"
[...]
imghero: "https:/path/to/image-online.jpg"
---
Then query it with graphql:
const LISTING_QUERY = graphql`
query BlogPostListing {
allMarkdownRemark(limit: 10, sort: {
order: DESC,
fields: [frontmatter___date]
}) {
edges {
node {
excerpt
frontmatter {
title
slug
date(formatString: "MMMM DD, YYYY")
imghero
}
}
}
}
}
`
After that I insert the {node.frontmatter.imghero} it on a prop on the main div:
const Listing = () => (
<StaticQuery
query={LISTING_QUERY}
render={({allMarkdownRemark}) => (
allMarkdownRemark.edges.map(({node}) => (
<Article img_background={node.frontmatter.imghero} key={node.frontmatter.slug}>
[... etc ...]
</Article>
))
)}
/>
)
export default Listing
And finally I call that img_background prop in the styled-component:
const Article = styled.article`
background-image: url(${props => props.img_background};);
[... etc ...]
`
This method works.
Now I want to get the image from my "images" folder and not from a random url.
I installed gatsby-remark-images
Set it on gatsby-config.js and put the path of some image on frontmatter.
Test everything with http://localhost:8000/___graphql (and worked)
Insert the additional query throught graphql:
[...]
frontmatter {
date(formatString: "DD MMMM, YYYY")
title
imghero
hero {
childImageSharp{
fluid(maxWidth: 630) {
...GatsbyImageSharpFluid
}
}
}
[...]
I modify the node on the component with the new path:
<Article img_background={node.frontmatter.hero.childImageSharp.fluid} [...]>
[...]
</Article>
Gatsby Develop compiles fine.
But then my homepage is completely white.
And the console of the browser says that node.frontmatter.hero is "null".
I don't know that else to do.
Thanks for the help.

I think a bit more info is necessary to resolve your issue, none of the thing you listed out looks wrong in itself. However so many folks got tripped off by image handling in gatsby that I'm writing a check list. It's meant to be generic, but I think no.5, 8, 9, 12 might help you locate the problem.
Using image with gatsby-transformer-remark + gatsby-transformer-sharp troubleshooting
Setup
Is there any error at all? Sometimes gatsby will still compile successfully despite something's wrong. Check the console for anything that's... red.
Did you restart gatsby i.e turn it on and off again? Try removing cache & public folder (.cache and public) if you suspect something's wrong with them.
Did you list your image folder, or any of its parent folders in gatsby-source-filesystem?
In your frontmatter, is the path to the image relative to the markdown file itself? i.e path starts with a dot ./relative/path/to/image.png
Does all markdown has a hero field in frontmatter? If a file doesn't have a hero field, it will be null.
If the image path in frontmatter is not relative or doesn't link to a file, it'll be treated as a regular string.
Query & Fragments
Does your query work? Test your query in http://localhost:8000/___graphql. Make sure the image field show up as a File node. Try something simple like
query {
allMarkdownRemark {
frontmatter {
title
hero {
id
name <-- just enough to know the file exists
}
}
}
}
If your hero shows up as a string, something's wrong, check the setup again.
Are you using fragments? Currently fragments can't be test in the graphiql tool, so you might need to find the definition of that fragment and test it manually. Here's a list of the default ones that come with gatsby-transformer-sharp and their definitions.
If you're using a custom fragment, make sure to define & export it somewhere.
Usage
If image doesn't show up in the browser, inspect & try to find what's shown up in place of your image.
Are you using gatsby-image? If so, make sure you're passing in something it can work with.
Make sure your image component receives what it should. If your component's expecting a path, don't pass in an object, like result of a fragment.
Some side note
gatsby-remark-images only handle relative links in markdown image & html <img>, so if your image is living in frontmatter, it won't do anything.

Related

Ckeditor plugin configuration not working

I have tried to add justify plugin to be able to align text right, left or centre. But after following the instructions in the documentation (http://apostrophecms.org/docs/tutorials/howtos/ckeditor.html), I wonder if the plugin should be located in a specific folder (mine is at public/modules/apostrophe-areas/js/ckeditorPlugins/justify/), as it disappears when the site is loaded, but if I include it in some other folder such as public/plugins/justify still doesn't work.
This is my code just in case: (located at lib/modules/apostrophe-areas/public/js/user.js)
apos.define('apostrophe-areas', {
construct: function(self, options) {
// Use the super pattern - don't forget to call the original method
var superEnableCkeditor = self.enableCkeditor;
self.enableCkeditor = function() {
superEnableCkeditor();
// Now do as we please
CKEDITOR.plugins.addExternal('justify', '/modules/apostrophe-areas/js/ckeditorPlugins/justify/', 'plugin.js');
};
}
});
Also, it would be nice to know how the plugin should be called at the Toolbar settings for editable widgets.
Thanks!
The URL you need is:
/modules/my-apostrophe-areas/js/ckeditorPlugins/justify/
The my- prefix is automatically prepended so that the public folders of both the original apostrophe-areas module and your project-level extension of it can have a distinct URL. Otherwise there would be no way for both to access their user.js, for instance.
I'll add this note to the HOWTO in question, which currently handwaves the issue by stubbing in a made-up URL.
As for how the plugin should be called, use the toolbar control name exported by that plugin — that part is a ckeditor question, not really an Apostrophe one. But looking at the source code of that plugin they are probably JustifyLeft, JustifyCenter, JustifyRight and JustifyBlock.
It turns out that it's not enough to simply call CKEDITOR.plugins.addExternal inside apostophe-areas. You also need to override self.beforeCkeditorInline of the apostrophe-rich-text-widgets-editor module and explicitly call self.config.extraPlugins = 'your_plugin_name';.
Here's what I ended up with:
In lib/modules/apostrophe-areas/public/js/user.js:
apos.define('apostrophe-areas', {
construct: function(self, options) {
// Use the super pattern - don't forget to call the original method
var superEnableCkeditor = self.enableCkeditor;
self.enableCkeditor = function() {
superEnableCkeditor();
// Now do as we please
CKEDITOR.plugins.addExternal('justify', '/modules/my-apostrophe-areas/js/ckeditorPlugins/justify/', 'plugin.js');
};
}
});
then in in lib/modules/apostrophe-rich-text-widgets/public/js/editor.js:
apos.define('apostrophe-rich-text-widgets-editor', {
construct: function(self, options) {
self.beforeCkeditorInline = function() {
self.config.extraPlugins = 'justify';
};
}
});
For some reason doing CKEDITOR.config.extraPlugins = 'justify' inside apostrophe-areas does not work, probably due to the way how CKEDITOR is initialized;
One more thing: this particular plug-in (justify, that is) does not seem to follow the button definition logic. It has button icons defined as images, whereas CKEditor 4.6 used in Apostrophe CMS 2.3 uses font-awesome to display icons. It means that the icons that ship with the justify module won't be displayed and you'll have to write your own css for each button individually.
There is another issue which you'll probably face when you finally enable the justify buttons. The built-in html sanitizer will be strip off the styles justify adds to align the content.
Apostrophe CMS seems to be using sanitize-html to sanitize the input, so changing CKEditor settings won't have any effect. To solve the issue, add the following to your app.js:
'apostrophe-rich-text-widgets': {
// The standard list copied from the module, plus sup and sub
sanitizeHtml: {
allowedAttributes: {
a: ['href', 'name', 'target'],
img: ['src'],
'*': ['style'] //this will make sure the style attribute is not stripped off
}
}
}
Thank you both for your help. After following both approaches of: locating the plugin at my-apostrophe-areas folder as well as editing editor.js on the apostrophe-rich-text widget (the sanitize.html file was already using that configuration), I got the plugin working. However, I was still having the issue with the icons.
I fixed that adding the Font Awesome icons that correspond to align-justify, align-right, align-left and align-center at the end of public/modules/apostrophe-areas/js/vendor/ckeditor/skins/apostrophe/editor.less

Fancybox 2 not showing when calling .open()

I'm trying to rig up a Knockout binding for Fancybox (although I don't think that's too much involved here). I'm calling Fancybox based on the code from the sample here: http://jsfiddle.net/STgGM/
$.fancybox.open([{
href: value.image(),
title: value.title()
}], {
padding: 0
});
The object passed in looks like:
{href: "http://example.com/imageurl", title: "Image Title"}
Stepping through the fancybox code, it bails out of trying to show the image around line 855 of the script:
if (!type) {
F.coming = null;
//If we can not determine content type then drop silently or display next/prev item if looping through gallery
if (F.current && F.router && F.router !== 'jumpto') {
F.current.index = index;
return F[ F.router ]( F.direction );
}
return false;
}
I'm not entirely sure what it's looking for at this point. F.current is null and F.router doesn't exist on the object.
So, in short, I'm trying to trigger Fancybox from a link click, without modifying my markup that much, or calling .fancybox() on a particular element. This appears to be possible, but it doesn't appear to be working for me.
After digging through the code more, I eventually found the solution. Fancybox was trying to figure out what sort of content I was telling it to display by inspecting the URL I was giving it. As my URL had no extension, since it was coming from an external service that uses and ID to access an image, and not a full file name, Fancybox had no clue what I was telling it to display, and gave up.
The solution, since I know what the content is, is this:
$.fancybox.open({
href: value.image(),
title: value.title(),
type: 'image'
},//other stuff (not relevant to this)
This makes FancyBox work as expected.

Angular.js - Filter in img src tag

We use Angular mainly for our search form, which is pretty complex. We use Solr as search framework and get our search results via AJAX/JSONP, which works perfectly.
There should be an image in every search result, but it can happen that there is none.
I use a filter to prevent nasty "X"s in the Internet Explorer when there is no img-URL in my search result.
angular.module('solr.filter', []).
filter('searchResultImg', function() {
return function(input) {
if (typeof(input) == "undefined") {
return "http://test.com/logo.png";
} else {
return input;
}
};
});
My linked image looks like this in the source code:
<img src="{{doc.image_url | searchResultImg}}"/>
Like I said, the infos are delivered correctly, the "problem" I have is that Firebug sends a GET request with the Angular src like:
http://test.com/foldername/%7B%7Bdoc.image_url%20|%20searchResultImg%7D%7D
The link is edited, so it won't work. Else customer freak out ;)
Does anyone have experience with this behaviour or knows a better way to set filters for src-tags?
Try replacing src with ng-src for more info see the documentation or this post.
<img ng-src="{{doc.image_url | searchResultImg}}"/>
Using Angular markup like {{hash}} in a src attribute doesn't work
right: The browser will fetch from the URL with the literal text
{{hash}} until Angular replaces the expression inside {{hash}}. The
ngSrc directive solves this problem.

Drupal Node Forms - Image field: How to directly upload an image after choosing a file (no need to click upload button)

I'm trying to change the default behavior of Drupal when adding an image through image field on a content type.
When you choose an image to assign to a node, it's not directly uploaded. You also need to click "upload" to display the preview of your image, and this is not really user friendly.
How can I change this (programmatically) to make Drupal start uploading directly the image after choosing the file.
Thank you for help
You can do it this way:
(function ($) {
Drupal.behaviors.autoUpload = {
attach: function(context, settings) {
$('.form-item input.form-submit[value=Upload]', context).hide();
$('.form-item input.form-file', context).change(function() {
$parent = $(this).closest('.form-item');
setTimeout(function() {
if(!$('.error', $parent).length) {
$('input.form-submit[value=Upload]', $parent).mousedown();
}
}, 100);
});
$('.form-item input.form-submit[value=Transférer]', context).hide();
$('.form-item input.form-file', context).change(function() {
$parent = $(this).closest('.form-item');
setTimeout(function() {
if(!$('.error', $parent).length) {
$('input.form-submit[value=Transférer]', $parent).mousedown();
}
}, 100);
});
}
};
})(jQuery);
This solution works with either english and french browsers. Unlike AutoUpload module, which only works on browsers configured in english. Note the [value=Upload] / [value=Upload] attribute
I found a similar post:
https://drupal.stackexchange.com/questions/31121/how-can-i-automatically-upload-images-on-file-selection-rather-than-pressing-the
It's exactly what I need..
You should be able to use http://drupal.org/project/imce for your needs.
I am not sure about the Image field but when I encountered this issue I decided letting users add images in body since it is a much easier option for durpal - When inserting images in text They will show immediately .
IMCE + filefield seems like a viable option for your direct needs,They do mention AJAX support.

How to set link font for TTStyledTextLabel

So, I'm fairly new to Three20, but so far the benefits have outweighed the pains in my ass that it's taken to get things working.
I'm using some TTStyledTextLabels, and I need to use a particular font for links. I've overridden TTDefaultStyleSheet and added a new style, like so:
- (TTStyle*)futuraStyle {
return [TTTextStyle styleWithFont:[UIFont fontWithName:#"Futura-CondensedMedium" size:20] color:kColorTextLink next:nil];
}
I can use tags to apply this style to normal text, but it doesn't seem to affect links.
I found that if I add the style class directly to the links, as in
link!
then the links do appear in the proper font. However, they are then no longer tappable! WTF?
Got it!
set the name in the link with a double dash and than the link style will be called with the UIConstrolState parameter, and all will work fine:
- (TTStyle*)futuraStyle:(UIControlState)state{
if(state==UIControlStateNormal){
return [TTTextStyle styleWithFont:[UIFont fontWithName:#"Futura-CondensedMedium" size:20] color:kColorTextLink next:nil];
}else{
return [TTTextStyle styleWithFont:[UIFont fontWithName:#"Futura-CondensedMedium" size:20] color:kColorTextLinkHiglighted next:nil];
}
}
and in your text:
link!

Resources