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.
Related
How to prevent jQuery $('body').load('something.php'); from changing any DOM till all the content from something.php (including images,js) is fully loaded
-Lets say some actual content is:
Hello world
And something.php content is:
image that loads for 10 seconds
20 js plugins
After firing .load() function nothing should happen, till images an js files are fully loaded, and THEN instantly change the content.
some preloader may appear, but its not subject of question.
[edit]----------------------------------------------------------------------
My solution for that was css code (css is loaded always before dom is build) that has cross-browser opacity 0.
.transparent{
-moz-opacity: 0.00;
opacity: 0.00;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha"(Opacity=0);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);
filter:alpha(opacity=0);
}
And it prevent from bad flickr of content usually but not always. Now its possible to detect somehow that content is loaded by jQuery ajax and apply some show timeout and so on. But in fact question is still open.
To make now a little more simple example for that question:
How to begin changing DOM after $('body').load('something.php') with 3000ms delay after clicking the link that fire .load('something.php') function? (Browser should start downloading instantly, but DOM changing has to be initiated later)
Use .get instead and assign the contents in the success callback:
$.get('something.php', function(result) {
$('body').html(result);
});
There are some implementation details you may have to solve yourself, but here's a rough solution:
Don't use .load() directly. It can't be changed to wait for all images to load.
Use $.get() to fetch the HTML into a variable, let's call it frag.
Use $(frag).find('img').each(fn) to find all images and dump each this.src inside a preloader.
var images = [],
$frag = $(frag),
loaded = 0;
function imageLoaded()
{
++loaded;
// reference images array here to keep it alive
if (images.ready && loaded >= images.length) {
// add $frag to the DOM
$frag.appendTo('#container');
}
}
$frag.find('img').each(function() {
var i = new Image();
i.onload = i.onerror = imageLoaded;
i.src = this.src;
images[images.length] = i;
});
// signal that images contains all image objects that we wish to monitor
images.ready = true;
Demo
Once all images are loaded, append the earlier frag to the DOM using $frag.appendTo('#container').
Here is a quick proof of concept that loads relevant images before inserting an HTML fragment into the DOM: http://jsfiddle.net/B8B6u/5/
You can preload the images using the onload handler to trigger iterations:
var images = $(frag).find('img'),
loader = $('<img/>');
function iterate(i, callback) {
if (i > 0) {
i--;
loader.unbind("load");
loader.load(function() {
iterate(i, callback);
});
loader.attr('src', images[i].src);
}else{
callback();
}
}
iterate(images.length,function(){
$('#container').html(frag);
});
This should work, since each image is loaded after the previous one has finished loading.
Have you tried this?
$(function(){$('body').load('something.php')});
Edit: I just realized you are actually wanting to wait for the stuff to load before it get's placed in the body.
Here are three links to similar questions.
Preloading images with jQuery
Is it possible to preload page contents with ajax/jquery technique?
Preloading images using PHP and jQuery - Comma seperated array?
You can probably adapt those to scripts too.
This might work too.
$.ajax({
'url': 'content.php',
'dataType': 'text',
'success': function(data){
var docfrag = document.createDocumentFragment();
var tmp = document.createElement('div'), child;
//get str from data here like: str data.str
tmp.innerHTML = str;
while(child = tmp.firstChild){
docfrag.appendChild(child);
}
$('body').append(docfrag);
}
});
It's a longer way of doing what Shadow Wizard suggests, but it will probably work.
Hm. Never mind. Jack's answer looks the best. I'll wait a while and if no one likes my answer I'll delete it.
Edit: It looks like appending to documentfragments can do http requests.
Any script using createDocumentFrament may benefit from preloading.
In this question they want no http requests even though that's what createDocumentFragment is doing:
Using documentFragment to parse HTML without sending HTTP requests.
I can't be sure if this is true for all browsers or just when the console.log is run, but it could be a good option for preloading if this behavior is universal.
I am trying to implement CKEditor 4 into an ASP NET website that I am working on, but I cannot figure out how I would save the edited material from the inline editor I know how to do it with the the old version, but I just don't understand the process for this.
I have looked in the forums... There is not v4 forum.
I looked in for the documentation.... Couldn't find it.
I have a feeling that this is a simple task, but I just don't know how.
You can get your data with CKEDITOR.instances.editor1.getData(). Then you can send it via AJAX or store it as a value of some input field. To do this periodically, follow this method:
CKEDITOR.disableAutoInline = true;
var editor = CKEDITOR.inline( 'editable' );
var savedData, newData;
function saveEditorData() {
setTimeout( function() {
newData = editor.getData();
if ( newData !== savedData ) {
savedData = newData;
// Send it with jQuery Ajax
$.ajax({
url: 'yourUrl',
data: savedData
});
// Or store it anywhere...
// ...
// ...
}
saveEditorData();
}, 500 );
};
// Start observing the data.
saveEditorData();
You can also observe the submit event and update some (hidden) form field with your data.
Have fun!
Are you trying to get it with AJAX or send with a form? The value of for example the top right inline editor area with Lorem Ipsum can be gotten like in the older version with simply
CKEDITOR.instances.editor1.getData().
In the XHTML output example they have a simple form that seems to work and I believe that using an (static) inline editor is just the same.
If you transform elements into editors inline dynamically, I would try to bind to the submit event and before submitting loop through all CKEDITOR.instances, get their data into hidden from fields. As for the hidden field naming or identifying which hidden field corresponds to which dynamic editor you'll have to figure out yourself :)
i know its sounds a bit crazy, but so many clients have problems with not saving their article properly.
I just wanted to use a simple method to trigger the onclick of the APPLY button inside a joomla article in edit mode.
Primarily back end editing as i have a good admin template that allows me to show clients the bare bones.
I know that by clicking apply the page reloads but thats better than nothing.
How on earth do i add do this?
I was hoping something like this would work but i dont quite know how to trigger a button that seems to reside inside a toolbar function of some sort.
I have this:
<script type="text/javascript">
$(document).ready(function() {
$('??????').trigger('click');
});
</script>
What would replace the question marks?
Also i know i would need to put a timer into the jquery code but how do i get the link below to trigger?
http://mydomain.com/administrator/index.php?option=com_content§ionid=1&task=edit&cid[]=97
In the toolbar.content.html.php file joomla has this:
class TOOLBAR_content
{
function _EDIT($edit)
{
$cid = JRequest::getVar( 'cid', array(0), '', 'array' );
$cid = intval($cid[0]);
$text = ( $edit ? JText::_( 'Edit' ) : JText::_( 'New' ) );
JToolBarHelper::title( JText::_( 'Article' ).': <small><small>[ '. $text.' ]</small></small>', 'addedit.png' );
JToolBarHelper::preview( 'index.php?option=com_content&id='.$cid.'&tmpl=component', true );
JToolBarHelper::save();
/////////////////////////////////////
JToolBarHelper::apply(); // < // THIS IS WHAT I WANT TO TRIGGER
/////////////////////////////////////
if ( $edit ) {
// for existing articles the button is renamed `close`
JToolBarHelper::cancel( 'cancel', 'Close' );
} else {
JToolBarHelper::cancel();
}
}
...... more stuff here
}
I know this might sound crazy but wouldnt it be great if autosave could happen even without a reload, but i guess that would mean posting all the data using jquery rather than the php post and reload page method.
Anyways im not expecting a miracle here but if anyone could help that would be great.
Cheers in advance
John
PS:
i just tried something like this hoping maybe it will work but it just reloads the page:
function autosave()
{
window.location = "index.php?option=com_content§ionid=<?php echo $_GET['sectionid'];?>&task=edit&cid[]=<?php echo $row->id;?>"
}
You won't be able to do it without forcing a reload unless you decide to re-write the whole of com_content with an ajax implementation.
Looking at the code you've posted I guessing Joomla! 1.5 - which by default has MooTools 1.12 or 1.2.5 (if you enabled the MooTools upgrade plugin in later versions of 1.5.x) - so more of a question but why not use that?
You will have to modify the admin template to embed the JS you need, 1.5 has few triggers and none that are really worth using in the admin screens (unless you're up for a fair bit of PHP coding)
Somewhere in the <head> tag of com_content's Article view you will need to add this:
<script type="text/javascript">
var interval = 30 //seconds
var timer = setTimeout(submitbutton('apply'),(interval * 1000));
}
</script>
Please note I haven't tried this just typed it straight into here.
Since you're on 1.5 have you tried the Simple Content Versioning extension - it has autosave functionality that appears to be what you want - and probably works whereas who knows with my code in #3.
So i I have a page that contains links that call an httpRequest. The request calls a php file that grabs data from mysql and pre populates a form which is then returned to the browser/webpage. My problem is that when the page is returned to the browser via the httpRequest/ajax the text area does not display the tinymce editor, it just displays a normal text area. It looks like my request and ajax is working fine the text area just doesn't have the tinycme editor on it.
When i don't use ajax it works fine but when i put it in a separate file and call it via ajax it doesn't bring in the tinymce editor.
Does anyone know how to fix this problem so that my ajax generated page displays the text area with the tinymce editor. Thank you.
Lets presume that your thinyMCE instance is initialized with code below
// initialize tinyMCE in page
tinyMCE.init({
mode: "textareas",
theme: "advanced"
});
and you have some kind of button somewhere in the page. For purpose of this tip, i will not give it any ID but you may. Now, using jQuery you can easily attach event handler to that button which will call through AJAX your server and take content which you want to put tinyMCE editor. Code which will do such job would look somehow like below.
$(function() {
$("button").bind("click", function() {
var ed = tinyMCE.get('content');
ed.setProgressState(1); // Show progress
$.getJSON('/page/12.json', { /* your data */
}, function(data) {
ed.setProgressState(0); // Hide progress
ed.setContent(data["body"]);
}
});
});
});
You can see that on button.click ajax will call url /page/12.json which will return JSON as response. bare minimum of that response could be:
{
title: "Page title",
body: "<html><head><title>Page title</title>......</html>"
}
I attached anonymous function as callback which will handle response from server. and hide progress indicator which is shown before ajax call.
About JSON
JSON is shorten of JavaScript Object Notation. It is JavaScript code!!! So don't be confused about it. Using JSON you can make javascript object which can have attributes you can use later in your code to access particular peace of data which that object "holds". You can look at it as some kind of data structure if it is easier to you.
Anyway, to show you how this JSON can be created by hand look at examples below
var data = new Object();
data.title = "Page title";
data.body = "<html....";
or
var data = {
title: "page title",
body: "<html...."
};
it is very same thing.
If you want to learn more about JSON point your browser to http://json.org.
===== alternative =====
Alternative to json solution could be just plane ajax call to server and response can be plain HTML (from your question I can assume that you have something like this already). So instad of calling $.getJSON you can use $.get(url, callback); to do same thing. The code at the top of my answer will not dramatically change. Instead of geting JSON in response you will get string which is HTML.
----------- BOTTOM LINE -------
I prefer JSON since it can be easily extended later with other attributes, so there is no painful code changes later ;)
Problem here will be that when you return the full page and render it using the ajax response, your tinymce instance has not been shut down before.
In order to do this you can call this small piece of code before you render the ajax response:
tinymce.execCommand('mceRemoveControl',true,'editor_id');
In this case the editor should initialize correctly. You are not allowed to initialize a tinymce editor with the same id before shutting the first one down.
Strangely i ran into this problem yesterday. Following code should work, but YMMV. Trick is to use the correct steps in ajax events. I used the Regular TinyMCE and made use of the jQuery library already included.
Following goes into your tinyMCE initialization tinyMCE.init() . All of the below block should be outside the document.ready.
myTinyInit = {
//.......All essential keys/values ...........
setup : function(ed) {
ed.onChange.add(function( ed ) {
tinyMCE.triggerSave();
}) }
//.....................
};
// Init the tinyMCE
tinyMCE.init(myTinyInit);
This ensures the content is being saved regularly onto the textarea that holds the value. Next step is setting up the request events.
Normally tinyMCE mceAddControl before the ajax post and mceRemoveControl after the ajax success should do the trick. But I found that often does not work.
I used the form as the jQuery selector in my case.
jQuery( '.myForm' )
.find( 'textarea#myTextArea' )
.ajaxStart(function() {
// If you need to copy over the values, you can do it here.
// If you are using jQuery form plugin you can bind to form-pre-serialize event instead.
// jQuery( this ).val( tinyMCE.get( jQuery( this ).attr( 'id' )).getContent() );
}).ajaxSend( function() {
// ! - step 2
// My case was multiple editors.
myEds = tinyMCE.editors;
for( edd in myEds ) {
myEds[ eds ].remove();
}
// tinyMCE.get( 'myTextarea' ).remove();
// strangely mceRemoveControl didnt work for me.
// tinyMCE.execCommand( 'mceRemoveControl', false, jQuery( this ).attr('id'));
}).ajaxSuccess(function() {
// Now we got the form again, Let's put up tinyMCE again.
txtID = jQuery( this ).attr( 'id' );
// ! - step 3
tinyMCE.execCommand( 'mceAddControl', false, txtID );
// Restore the contents into TinyMCE.
tinyMCE.get( txtID ).setContent( jQuery( this ).val());
});
Problems i came across :
Using mceRemoveControl always gave me r is undefined error persistently.
If you get a blank tinyMCE editor, check the DOM whether the ID of the textarea is replaced with something like mce_02, this means that TinyMCE is being initialized again or something is wrong with the order. If so, the tinyMCE is duplicated with each save.
if you are new to JS, I recommend using jQuery with the form plugin, it might be easier for you. But do use the regular non-jquery tinyMCE, as it is well documented.
I fixed this problem by recalling the function after the ajax call. In this part of my ajax:
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("Content").innerHTML=xmlhttp.responseText;
tinymce();
Now it works fine.
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.