I've been playing around with the new media manager in WordPress and had some fun with it, but have reached the point where I'm banging my head against a wall.
I have a custom meta box that I'd like to store some images in (well it's a hidden input and I'm currently storing their ID's, but could equally be the image objects), then making an AJAX call to show some thumbnails, which I have subsequently made draggable so users can reorder (not necessarily relevant just some background).
My problem is that when I open the media manager, no images are selected, so if a user wants to edit the pictures in their gallery they need to select them all again.
What I'm trying to figure out, is how do I open the media manager with the current images passed through so they are pre-selected.
So, broadly, my code looks like this
jQuery('#myButton').click(function(e) {
e.preventDefault();
frame = wp.media({
title : 'My Gallery Title',
multiple : true,
library : { type : 'image'},
button : { text : 'Insert' },
});
frame.on('close',function() {
// get selections and save to hidden input plus other AJAX stuff etc.
}
frame.open();
});
My thought is that there must be either a parameter to pass into the frame (probably a JSON object of the images, or I need to create an event for
frame.on('open', function() {
// Set selected images
}
But I have tried both ways round and am not getting anywhere.
It would appear possible, as changing the 'Featured Image' takes you to the library with the current one selected - I've just been unable to understand the core code sufficiently yet and hope someone else has !
After studying the core for a bit, the answer here is really quite straightforward.
Listen for the open event of the wp.media object, grab the state, create attachment objects with your id's and add them to the selection.
frame.on('open',function() {
var selection = frame.state().get('selection');
var ids_value = jQuery('#my_field_id').val();
if(ids_value.length > 0) {
var ids = ids_value.split(',');
ids.forEach(function(id) {
attachment = wp.media.attachment(id);
attachment.fetch();
selection.add(attachment ? [attachment] : []);
});
}
});
This works when selecting multiple images as well as single and assumes that using the code above you have stored the values in a single text/hidden field with comma separation.
not a real answer, but somethings that I have noticed
using your code the frame.open( console.log('open') ) does trigger the console.log.
The other frame.on('open', function() { console.log('on->open')}) does not.
When looking at the post edit page. (Where a featured image is already set).
If you open the featured img window a few things happen that are interesting.
WP does 3 ajax calls, the 1st and 3rst contain the featured img id. the 2nd is the same as with your code.
when the popup is loaded the featured image is visible / loaded before the rest of the images. When those show up the featured image is put in the right order.
When looking in firebug at the dom tab I discovered that the var wp.media.model.settings.post.featuredImageId holds (wait for it) the featured image value.
Hopes this helps you in some way.
I think those guy manage to do it :
https://wordpress.stackexchange.com/questions/76125/change-the-default-view-of-media-library-in-3-5/76213#76213
But this doesn't work for me.
I ve got the jquery in the footer of my post/edit, post/new but that just don't work for me :(
Related
I'm trying to tweak the WordPress plugin https://github.com/algolia/algoliasearch-wordpress to suit our needs. What we want to be able to do is have a search result that will load the data up in the same page.
I have my WordPress posts and its data being indexed successfully. I have added a search box to the page, and autocomplete is being fired.
Out of the box, the WordPress plugin template wraps the result in an anchor tag and assigns it the URL of the found result. When clicked, this navigates you to that post. However, what I want to do is intercept that click and load the result in the same page without navigating away.
I have removed the href from the anchor. I have also edited the supplied autocomplete.php template where the call to autocomplete:selected occurs. In there I have removed the call to navigate away by removing window.location.href.
Now I have two main issues.
1 - When the user clicks the search result I would like the input to be populate with the title of the item they clicked on. I added this in the autocomplete:selected callback by adding $searchInput[0].value = suggestion.post_title. Which seems to change the value of the input correctly, but as soon as I click away from the input, it is re-set back to the original typed value. So if I type 'may' and click the result 'mayonnaise', the result data can be accessed but the input returns back to 'may'. My function looks this:
/* Instantiate autocomplete.js */
var autocomplete = algoliaAutocomplete($searchInput[0], config, sources)
.on('autocomplete:selected', function (e, suggestion) {
console.log(suggestion);
autocomplete.autocomplete.close();
});
2 - It seems that the autocomplete dropdown does not hide when the user clicks away. To resolve this i've had to use what I think is a bit of a nasty hack with jQuery. I was wondering if this is really required? My code just below the autocomplete:selected call looks like this:
jQuery('body').on("click", function(event){
if (!jQuery(event.target).closest($searchInput[0]).length) {
autocomplete.autocomplete.close();
}
});
Found some answers to my questions.
1 - In order to populate the input with the title of the selected search result I added a call to the setVal method of the autocomplete object. I'[m still not sure why this is required.
/* Instantiate autocomplete.js */
var autocomplete = algoliaAutocomplete($searchInput[0], config, sources)
.on('autocomplete:selected', function (e, suggestion) {
autocomplete.autocomplete.setVal(suggestion.post_title);
});
2 - It looks like the config of the autocomplete object uses the value of WP_DEBUG in order to set the debug value. The options available for the autocomplete component can be found here https://github.com/algolia/autocomplete.js#options. This lead me to find that when debug is set to true, the autocomplete box does not hide on selection. This is to allow for easier debugging and styling of the component.
I am following this example https://kadira.io/academy/meteor-routing-guide/content/rendering-blaze-templates
When I click on my links the whole page is being reloaded. Is there any way to load only the template part that is needed and not the whole page?
Edit: Also I noted another problem. Everything that is outside {{> Template.dynamic}} is being rendered twice.
Here is my project sample. https://github.com/hayk94/UbMvp/tree/routing
EDIT: Putting the contents in the mainLayout template and starting the rendering from there fixed the double render problems. However the reload problems happen because of this code
Template.mainLayout.events({
"click *": function(event, template){
event.stopPropagation();
console.log('body all click log');
// console.log(c0nnIp);
var clickedOne = $(event.target).html().toString();
console.log('This click ' + clickedOne);
//getting the connID
var clientIp = null // headers.getClientIP(); // no need for this anymore
var clientConnId = Meteor.connection._lastSessionId;
console.log(clientIp);
console.log(clientConnId);
Meteor.call("updateDB", {clientIp,clientConnId,clickedOne}, function(error, result){
if(error){
console.log("error", error);
}
if(result){
}
});
}, // click *
});//events
Without this event attached to the template the routing works without any reloads, however as soon as I attach it the problem persists.
Do you have any ideas why this code causes such problems?
EDIT 2 following question Rev 3:
event.stopPropagation() on "click *" event probably prevents the router from intercepting the click on link.
Then your browser performs the default behaviour, i.e. navigates to that link, reloading the whole page.
EDIT following question Rev 2:
Not sure you can directly use your body as BlazeLayout target layout.
Notice in the first code sample of BlazeLayout Usage that they use an actual template as layout (<template name="layout1">), targeted in JS as BlazeLayout.render('layout1', {});.
In the tutorial you mention, they similarly use <template name="mainLayout">.
That layout template is then appended to your page's body and filled accordingly. You can also change the placeholder for that layout with BlazeLayout.setRoot() by the way.
But strange things may happen if you try to directly target the body? In particular, that may explain why you have content rendered twice.
Original answer:
If your page is actually reloaded, then your router might not be configured properly, as your link is not being intercepted and your browser makes you actually navigate to that page. In that case, we would need to see your actual code if you need further help.
In case your page does not actually reload, but only your whole content is changed (whereas you wanted to change just a part of it), then you should make sure you properly point your dynamic templates.
You can refer to kadira:blaze-layout package doc to see how you set up different dynamic template targets in your layout, and how you can change each of them separately (or several of them simultaneously).
You should have something similar in case you use kadira:react-layout package.
I'm having trouble implementing history.js
I have a single page website that uses a jquery slider (royal slider) to slide full page divs that act as pages. The slider is operated using custom links. What I would like to do is have each link manipulate the browser history in order to 1. change the page URL. and 2. push states to the browser that are refreshable and can be navigated to and from via the browser's forward and back buttons.
What I'm not sure about is whether any pushstate will save the sliders current slide?
It's not essential if not, as the change in URL is the main thing.
Each link is controlled via a javascript click function that looks like this...
var workclick = document.getElementById('worklink');
workclick.onclick = function () {
thefooter.style.opacity = "1";
thefooter.style.filter = 'alpha(opacity=100)';
thefootdivide.style.opacity = "1";
thefootdivide.style.filter = 'alpha(opacity=100)';
$(".royalSlider").royalSlider('goTo', 1);
}
Can somebody help me with what I need to add to my page to get history.js to work with what I have here?
Thanks so much for any help
I am not an expert on History.js, but my understanding is that once it's installed, each time a slider value is changed you could call replaceState() with url parameters that reflect their values something like :
History.replaceState( null, 'My Title', '?slider1=' + $('#slider1').value );
And then, when your page loads have it read these request parameter values and (if present) set the sliders accordingly.
Again I'm not sure this is exactly what you need but I'm pretty sure it's on the right track.
I have an enhancedGrid backed by a JsonRestStore which displays summary information and can be clicked to show and edit the full information in another tab. However when I then refresh the grid with a setQuery command any items that have been edited are removed from the grid (though they still seem to be in the _index property of the store).
This happens if I just update the database manually or use a dojo editor. The json coming back from the server is still valid and if I do a page refresh in the browser the item re-appears. Any ideas what might be going on?
This is the code to create the grid.
var gridStore = new dojox.data.JsonRestStore({
target : '/api/prospects/',
idAttribute : 'prospect_id',
});
var grid = new dojox.grid.EnhancedGrid({
store: gridStore,
structure: gridStructure,
columnReordering: true,
selectionMode: 'single',
plugins: {filter: true},
});
gridPane.setContent(grid);
This is the code to set the query
dojo.connect(tree,'onClick', function(node){
if (node.type == 'project') {
grid.setQuery({project:node.project_id});
}
});
Typical after searching high and low for the reason that this is happening I find the answer after posting it here. It seems that jsonreststore has a bug in its rendering engine that could be solved by removing a few lines from the ClientFilter file (presumably, although I haven't checked JsonRestStore has the exact same bug as I tested with and without cacheing and had the same result).
Details are at the bottom of this page
I have a problem at which I have a view that will display a featured item and 6 rows on the first page of the view, while displaying 9 rows on the rest of the pages. Is such a functionality possible with views?
Thanks!
A few methods I can think of. I have mentioned them on the basis of how long it will take you.
1) Create a custom css rule which hides two entries on the first page. As for the rest of the pages you can show it.
2) Find the template file of your particular views and then use php to hide those rows. You can find the name of this file in your views theme section.
3) You could write a php module which can do the same as views. Its not that hard to get it done.
UPDATE
Below is the jquery which will help you get the logic right
$(document).ready(function() {
var pathname = window.location.pathname;
// here we assignt he current url of the page to the var pathname
});
if(pathname =='firstPageofView')
{
// if the path name is the first page of the view then we assign special css formating
$('#divid').hide();
}
else
{
$('#divid').css('width','10px');
}
Cheers,
Vishal