How to load a div after the line break on click event? - ajax

I'm creating under Wordpress a single page portfolio. Each gallery thumbnail is a list item.
When you click an item, it loads a sliding drawer (#DrawerContainer) pulling the content from the post with ajax.
I want this drawer to appear on the line after the clicked item.
Since it's a fluid layout, I don't know if the browser is displaying 1,2,3,4 or 5 items in a row.
I tried to append my drawer to every <li> but I'm afraid if I click a thumbnail,
the slider will open and make the other thumbnails jump to the next line.
So I thought the best way to prevent layout problems is to call the drawer only after a line break.
How can I target the last li item in the row, and load a div after the line break of this row?
If I'm not clear, here is the code I'd like to see rendered
EDIT: I just added the code to jsfiddle if you want to put your hands on it. http://jsfiddle.net/F6MvZ/10/
<ul id="portfolio-list">
<li>item1</li>
<li>item2</li>
<li>item3</li> //end of first row (br/)
<li>item4</li> //if I click this item
<li>item5</li>
<li>item6</li> //end of second row (br/)
<div id="DrawerContainer"></div> // the content of item4 appears here
<li>item7</li> //end of third row
</ul>
and here is the code I'm struggling with
$(document).ready(function(){
$.ajaxSetup({cache:false});
$(".ProjectWrap,.mosaic-overlay,.mosaic-backdrop").click(function(){
var post_link = $(this).attr("href");
//$('#DrawerContainer').slideToggle(500);
$("#DrawerContainer").html("loading...");
$("#DrawerContainer").load(post_link + " #container > * ");
return false;
});
//Here is the part I'm stuck with now
$(#portfolio-list).click(function(){
$("<br/>").append('<section id="DrawerContainer"></section>');
});
//I assume the #DrawerContainer will generate a br/
});

Looking for something like this?
http://jsfiddle.net/RF6df/1/
Its an extension of what I originally wrote. Hope this helps.

Related

Kendo ScrollView - Refresh/redraw current page

I'm using a Kendo ScrollView to display person images on a form.
Separate from the ScrollView, users can change the display order of the images. After they save their changes to the display order, the ScrollView is reloaded, scrolls to the first item, and should display the images in their new order.
However, I've noticed that when the ScrollView is currently on the first page, that page does not get refreshed/redrawn.
My ScrollView looks something like this:
#(Html.Kendo().ScrollView()
.Name("personImage")
.TemplateId("personImageTemplate")
.DataSource(d => d
.Custom()
.Type("aspnetmvc-ajax")
.Transport(t => t
.Read(r => r.Action("PersonImages_Read", "Person", new { personID = Model.ID } ))
)
.Schema(s => s.Data("Data").Total("Total"))
.ServerPaging(false)
.PageSize(1)
)
)
The template looks like this:
<script type="text/x-kendo-tmpl" id="personImageTemplate">
<img class="personImage"
src="#(Url.Action("ImageRender", "Person"))?imageID=#= data.ID #"
title="#= data.Filename #" />
</script>
And here is my refresh function:
function refreshPersonImageScrollView() {
var scrollView = $("#personImage").data("kendoScrollView");
if (scrollView) {
scrollView.dataSource.read();
// https://docs.telerik.com/kendo-ui/api/javascript/ui/scrollview/methods/refresh
// redraws, doesn't re-read from datasource
scrollView.refresh();
// scroll to first image
scrollView.scrollTo(0);
}
}
When I watch the requests being made when I call this function, I see this:
A. When a page other than the first page is selected:
PersonImages_Read (the ScrollView's dataSource read)
The ScrollView scrolls to the first image
3x ImageRender, as it renders the first 3 items in the ScrollView
B. When the first page is selected:
PersonImages_Read (the ScrollView's dataSource read)
Nothing else
I tried switching the order of scrollView.refresh() and scrollView.scrollTo(0), but the result does not change.
Is there any way to get Kendo to refresh/redraw the current page? I thought refresh would do it, based on the documentation, but it does not.
Edit
I've been able to replicate this issue in REPL. To see the behavior in action:
Note the "Rendered" time under the first image.
Scroll to the second image in the ScrollView.
Wait several seconds, then click the "Refresh" button.
The ScrollView should scroll back to the first image.
Observe that the "Rendered" time under the first image matches the "Last clicked" time reported below the "Refresh" button, and is no longer what it was in step #1. (This is the correct behavior.)
Remain on the first image for several seconds. Note the "Rendered" time listed before continuing.
Click the "Refresh" button.
Note that the "Last clicked" time has updated, and in the "Log" section, there is an entry that reads "dataSource read complete" at approx. the same time. However, the "Rendered" time under the image has not changed, and there is no log entry that says "image for product #X loaded".
I am using Kendo version 2021.3.1109 in my project. The Kendo version in the REPL above is 2022.3.913 and it still occurs in that version.
I have found a way to resolve the issue, but this may be worth opening a possible bug ticket with Telerik, because you would think that scrollView.refresh call would work.
What I changed in your refreshPersonImageScrollview function was to call setDataSource on the scrollview rather than calling the refresh method. Like so:
function refreshPersonImageScrollView() {
$("#refresh-last-clicked").text("Last clicked: " + getCurrentTime());
addToLog("refresh button clicked");
var scrollView = $("#personImage").data("kendoScrollView");
if (scrollView) {
scrollView.dataSource.read();
scrollView.setDataSource(scrollView.dataSource);
// scroll to first image
scrollView.scrollTo(0);
}
}
This appears to force the scrollView to re-evaluate its life choices and properly refresh :) However, it does seem to trigger additional dataSource reads, so it's not ideal.
One other thing I tried that didn't resolve the problem, but may be a good thing to change to anyway, would be to utilize the promise returned by the dataSource.read call. Meaning, do your scrollView setDataSource and scrollTo calls after the dataSource read promise is settled, like so:
scrollView.dataSource.read().then(function() {
scrollView.setDataSource(scrollView.dataSource);
// scroll to first image
scrollView.scrollTo(0);
});
REPL link here

Scrolling to elements in CKEditor via JavaScript

My CKEditor fields often contain lots of content with h1, h2, h3, etc headings, and I've written a script that presents all the headings in a sidebar for quick reference. I'd also like to use this sidebar as a navigation menu for the editor content, so clicking a heading in the sidebar scrolls the editor to the related heading, but I can't figure out how to wire it all up.
This post at https://davidwalsh.name/scroll-element-ckeditor leads me to believe that it should be possible, but I can't figure out how to get to the "editor" element described in the post.
My sidebar is built with jQuery from a CKEditor textarea with id="content" like this...
var content = $('<div/>').append($('#content').val());
var sidebar = "";
$(content).find('h1,h2,h3,h4,h5,h6').addClass('heading');
$(content).find('.heading').each(function () {
sidebar += this.outerHTML;
});
$('#sidebar').html(sidebar);
I imagine using jQuery :contains() to identify heading elements in the editor based on the text they contain, but I can't figure out how to hook back into the CKEditor instance in a way that enables this kind of DOM activity.
I am using CKEditor 4 but am happy to upgrade to version 5 if it offers a better solution to my problem.
Thanks!
This is what wound up working for me:
var content = $('<div/>').append($('#content').val());
var sidebar = "";
$(content).find('h1,h2,h3,h4,h5,h6').addClass('heading');
$(content).find('.heading').each(function () {
sidebar += this.outerHTML;
});
$('#sidebar').html(sidebar);
$('#sidebar .heading').click(function() {
var element = $('#cke_content iframe').contents().find(':contains(' + $(this).text() + ')')[2];
if (element) {
element.scrollIntoView();
}
});

Randomly placed draggable divs - organize/sort function?

Currently I have a page which on load scatters draggable divs randomly over a page using math.random
Using media queries however the page uses packery to display the same images for browser widths under 769px in a grided fashion.
I had the idea that it could be interesting to create a 'sort/organize' button which would rearrange these divs using packery and remove the draggable class already applied, however i have no idea if this is possible or how to go about it. If there is any method of animating this process that would also be a bonus!
If anyone could at the very least point me in the right direction i would be extremely thankful!!
Hopefully this gives you a bit of a starting point.
I would read up on JQuery as it has some useful helpers for DOM manipulation.
I don't think this is the most efficient way to do it, and I think you will need to rethink your test harness for doing this in the future, but hopefully this gets you started.
Firstly I've added a button to trigger the sort
<div class="rotate" id="contact">Contact</div>
<div id="logo">Andrew Ireland</div>
<button id="sort">sort</button>
Then updated the script to override the css setting to switch between draggable view and item view.
// general wait for jquery syntax
$(function(){
// trigger the layour to sort get the packery container
var container = document.querySelector('#container.packery');
var pckry = new Packery( container );
//button function
$("#sort").click(function(){
//Hide all the dragged divs
//ui-helper-hidden is a jquery ui hider class
if($('.box').css('display') == 'block') {
$('.box').css({'display':'none'});
//Show all the item class's
$('.item').css({'display':'block'});
//show the container
$('#container').css({'display':'block'});
// trigger the layour to sort
pckry.layout();
} else {
//hide all the item class's
$('.item').css({'display':'none'});
//hide the container
$('#container').css({'display':'none'});
//show the draggable box's
$('.box').css({'display':'block'});
}
});
$( ".pstn" ).draggable({ scroll: false });
$(".pstn").each(function(i,el){
var tLeft = Math.floor(Math.random()*1000),
tTop = Math.floor(Math.random()*1000);
$(el).css({position:'absolute', left: tLeft, top: tTop});
});
});
As I said this is more to get started. The packery documentation details how to trigger its layout functions so another approach would be to only have the draggable elements, and put these inside a packery container. Then when you want to sort them you can just trigger that the packery.layout() function.
I hope this is helpful, I am only just getting started on stack overflow so any feedback would be appreciated.

Consuming GWT click events

Due to performance reasons, I have a custom made table. The table consists of columns that are created as HTML DIVs, and the row is wrapped into an AbsolutePanel. The position of the column(s) and the row(s) is absolute and calculated on the render loop. The table is added into a ScrollPanel and only renders the visible portion of the rows, and adds rows when the user scrolls.
Customer requirement is to open a PopupPanel to show details about the row when the row is clicked. I've added a ClickHandler to the row panel by sinking the click event into it, which works fine.
The problem is, if I add e.g. a standard link or any clickable item into one of the cells in the table, clicking on the said item(s) results in also the row click handler firing, which I want to somehow prevent. The source of the event is the row Element, not the link/icon/whatever that was clicked.
Any help solving this (perhaps a completely different approach ?) is much appreciated.
I would use gwtquery because of its simplicity and performance.
I don't know the final dom renderized by your app, but if we suppose you have something like this:
<div id="column1">
<div id="row1_1" class="my_row" product_id="whatever"> content </div>
...
</div>
Your code could be something like this:
import static com.google.gwt.query.client.GQuery.*;
$(".my_row").click(new Function(){
public void f() {
// The gquery instance of the row clicked
GQuery thisRow = $(this);
// Use gquery methods to get some info of your row
String thisId = thisRow.id();
String productId = thisRow.attr("product_id");
Element thisElement = thisRow.get(0);
// do Something with your row
...
}
});

jQuery Functions need to run again after ajax is complete

I am developing a website that parses rss feeds and displays them based on category. You can view it here: http://vitaminjdesign.com/adrian
I am using tabs to display each category. The tabs use ajax to display a new set of feeds when they are clicked.
I am also using two other scripts- One called equalheights, which re-sizes all of the heights to that of the tallest item. And the other script I am using is called smart columns, which basically resize your columns so it always fills the screen.
The first problem I am having is when you click a new tab (to display feeds within that category). When a new tab is clicked, the console shows a jQuery error:
$(".block").equalHeights is not a function
[Break On This Error] $(".block").equalHeights();
The main problem is that each feed box fills up the entire screen's width (after you click on a tab), even if there are multiple feed boxes in that category.
MY GUESS - although all of the feeds (across all tabs) are loaded on pageload, when a new tab is selected, both jQuery scripts need to be run again. any ideas on how I can make this work properly?
One thing to note - I used the ajaxSuccess method for making equalHeights work on the first page...but it wont work after a tab is clicked.
My jQuery code for the tabs are below:
$(".tab_content").hide(); //Hide all content
$("ul.tabs li:first").addClass("active").show(); //Activate first tab
$(".tab_content:first").show(); //Show first tab content
$("#cities li:nth-child(1)").addClass('zebra');
$("#column li ul li:nth-child(6)").addClass('zebra1');
//On Click Event
$("ul.tabs li").click(function() {
$("ul.tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content
var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content
$(activeTab).fadeIn(); //Fade in the active ID content
$(".block").equalHeights();
return false;
});
Thanks to Macy (see answer below), I have brought my jQuery script to the following: (still does not work)
$(document).ajaxSuccess(function(){
var script = document.createElement('script');
script.src = 'js/equalHeight.js';
document.body.appendChild(script);
equalHeight($(".block"));
I found some small problems in your code. I am not sure that my suggestions will solve all the problems, but I decide to describe my first results here.
1) You should remove comma before the '}'. Currently the call look like $("#column").sortable({/**/,});
2) The function equalHeight is not jQuery plugin. It is the reason why the call $(".block").equalHeights(); inside your 'click' event handler follows to the error "$(".block").equalHeights is not a function" which you described. You should change the place of the code to equalHeight($(".block")); like you use it on other places.
3) The script http://vitaminjdesign.com/adrian/js/equalHeight.js defines the function equalHeight only and not start any actions. Once be loaded it stay on the page. So you should not load it at the end of every ajax request. So I suggest to reduce the script
$(document).ajaxSuccess(function(){
var script = document.createElement('script');
script.src = 'http://vitaminjdesign.com/adrian/js/equalHeight.js';
document.body.appendChild(script);
equalHeight($(".block"));
$("a[href^='http:']:not([href*='" + window.location.host + "'])").each(function() {
$(this).attr("target", "_blank");
});
});
to
$(document).ajaxSuccess(function(){
equalHeight($(".block"));
$("a[href^='http:']:not([href*='" + window.location.host + "'])").each(function() {
$(this).attr("target", "_blank");
});
});
4) I suggest to change the code of http://vitaminjdesign.com/adrian/js/equalHeight.js from
function equalHeight(group) {
tallest = 0;
group.each(function() {
thisHeight = $(this).height();
if(thisHeight > tallest) {
tallest = thisHeight;
}
});
group.height(tallest);
}
to
function equalHeight(group) {
var tallest = 0;
group.each(function() {
var thisHeight = $(this).height();
if(thisHeight > tallest) {
tallest = thisHeight;
}
});
group.height(tallest);
}
to eliminate the usage of global variables tallest and thisHeight. I recommend you to use JSLint to verify all your JavaScript codes. I find it very helpful.
5) I recommend you to use any XHTML validator to find some small but sometime very important errors in the markup. Try this for example to see some errors. The more you follow the XHTML standards the more is the probability to have the same results of the page in different web browsers. By the way, you can dramatically reduce the number of the errors in your current code if the scripts included in the page will be in the following form
<script type="text/javascript">
//<![CDATA[
/* here is the JavaScript code */
//]]>
</script>
I didn't analysed the full code but I hope that my suggestions will solve at least some of problems which you described in your question.
Essentially, when you add a new element to the document, the equalheights script has not attached its behavior to that new element. So, the "quick fix", is probably to re-embed the equalheights script after an ajax request has completed so that it re-attaches itself to all elements on the page, including the elements you just added.
Before this line: $(".block").equalHeights(); , add a line of script which re-embeds/re-runs your equalheights script.
$.getScript('<the location of your equalHeightsScript>');
$.getScript('<the location of your smartColumnsScript>');
$(".block").equalHeights();
or
var script = document.createElement('script');
script.src = '<the location of your script>';
document.body.appendChild(script);
A better solution would be to upgrade the plugin so it takes advantage of live. However, I'm not up to that at the moment :)
Some Error Here
$("ul.tabs li").click(function() {
$("ul.tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content
.
.
.
});
Should be re-written like this
$("ul.tabs li").click(function() {
$(this).addClass("active").Siblings("li").removeClass("active");; //Remove any "active" class Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content
.
.
.
});
I don't think you need to run the scripts again after the ajax, or at least that's not the "main" problem.
You seem to have some problems in the script smartColumn.js
Right now it seems to only operate on the ul with the id "column" ('#column'), and it is working on the one UL#column you do have, but of course your HTML has many other "columns" all of which have the class "column" ('.column') that you want it to work on as well.
Just to get the beginning of what you are trying to do, change all the selectors in smartColumn.js that say 'ul#column' to say 'ul.column' instead, and then alter the HTML so that the first "column" has a class="column" rather than an id="column".
That should solve the 100% wide columns at least.
That should solve your "Main" Problem. But there are other problems.

Resources