JQuery prepend to crash - php

If I ajax any input into my page the following code works but if I print some specific code I get an exception, alert test3 never fires.
alert("test2");
$(html).hide().prependTo("#current table.vtable").fadeIn("slow");
alert("test3");
I get the jquery exception:
Uncaught TypeError: Cannot set property 'cur' of undefined
As I've said the CSS is working proper, I have tried printing other classes and it works perfectly the only difference is I use
print <<<END
...
END;
Instead of normal print and the tr is a different class

I just ran into this issue after upgrading from jquery 1.7 to 1.9. This is a bug in the implementation of fadeIn().
It has to do with the fact that the data() method now returns undefined rather than null when you query for a key that doesn't exist.
Anyhow, a workaround that I found is to prepend the data first, and then get a jquery handle to the new, prepended content, and fade that in.
Since you're inserting the new content into a table, it's a little annoying to find the thing you just inserted, since it's not actually the first child (it's wrapped in a "tbody" tag implicitly). I worked around this by setting a temporary attribute on the inserted thing, searching for it, and then removing it. This is a gigantic hack obviously, but it does work.
var html = "<tr><td>new thing1</td><td>new thing2</td>";
$("#clickme").click(function () {
var target = $("#current table.vtable");
$(html).attr("jquery_workaround","sigh").hide().prependTo(target);
var newstuff = target.find("[jquery_workaround=sigh]");
newstuff.removeAttr("jquery_workaround").fadeIn("slow");
});
For the fiddling: http://jsfiddle.net/BUVUj/

Related

serialized class instance disappears from session

I've made an img editor which works fine in 99.9% of the situations.
However, in that rare 0.1% something weird happends, my session remember doesn't the proper value.
I have this in the page that inits the class:
$imgScreen = new img4crop();
// And here some settings like $imgScreen->setExtraJs($extraJs);
In this class I have a functions to save the $this data to an array:
private function save(){
$_SESSION['cropper'][$this->uniqid] = serialize($this);
}
In init-page.php I open a fancybox, loading the settings back into the class:
$info = unserialize($_SESSION['cropper'][$_GET['id']]);
// Should now be the same as $imgScreen
The problem
Sometimes $_SESSION['cropper'][$_GET['id']] is set to NULL. I have no clue why. This only happens very rarely. The key is set.
When I debug, and appendecho $_SESSION['cropper'][$this->uniqid]; to the save() function, it gives me the value I want it to have.
So, where does my session value go, only in that rare occation? Why isn't it there in the fancybox screen?
After 1st comment: It is possible for the init-page to start multiple instances, they each get their own value in $_SESSION['cropper']. In the situation above, they all work, just that one doesnt. On reload, I start new instances and the exact same screen doesnt work, even though I now has a new, fresh id
Edit: It gets weirder: If the location where the image has a file with the same name as the class will use, there are no problems. Weird part: The whole class has no code regarding to files, apart from the final step (the screen has 3 steps), where I use ImageMagick.
Important to know: When I installed the page where this occurs, the targetfile didn't exist either, started blank.
When you are serializing objects you have to make sure you load the base class (prototype) before unserializing the object. For PHP native objects you don't have to do anything, it will load the base classes.
Your variable $this is an instance of a class. In order for $this to exist the base class need to exist. Perhaps it's working most of the time because of an autoloader or the particular sequence you are loading items.
Turns out the solution was, as to be expected, a quircky little something unrelated to the actual code:
In my index.php I do $_SESSION['cropper'] = array(); to reset the array, then let the function which shows an editorscreen set new settings to the cropper, this works perfectly fine.
In that html I have an image with an anti cache:
echo '<img src="'.$image_url.'?'.time.'" />';
The problem occured when $image_url is empty/undefined, resulting in a source something like the following: ?1420793438. It starts with a ?, so it's effectively calling index.php?1420793438.
And at the beginning of that index.php we reset, resulting in an empty array.

Replicating preloaded HTML /DOM method results in an array using AJAX/PHP

I have a function that creates an array that contains the return value from the HTML DOM method : window.document.getElementById()
function makearray1(){
var array1=[1,window.document.getElementById('divID'),['a','b'],[1,2]];
}
then I pass the array into another function
use(array1)
function use(xxx){
xxx[1].innerHTML=xxx[2][0];
}
and 'a' is written in the appropriate div
later I decided to put the array in a form and post it to a txt file on the server using php and:
JSON.stringify(array)
So now I use AJAX to call the data from the txt file after the rest of the page has loaded etc... and the original function used to make the array is not included at all.
so my php is basically this:
$a1='use(';
$data1 =file_get_contents("text_file.txt") ;
$a2=')';
echo $a1.$data1.$a2;
and the response text:
var n= XMLHttpRequestObject.responseText;
eval(n);
which pretty much means this:
use(text_file)
function use(xxx){
xxx[1].innerHTML=xxx[2][0];
}
the problem is that the array in the text file looks like this:
[1,null,['a','b'],[1,2]]
instead of:
[1,window.document.getElementById('divID'),['a','b'],[1,2]]
My question: Is there any way that I can do the equivalent of what I'm trying to do here, which is immediately replicate the return value of the HTML/DOM method in an array using AJAX/php?
To clarify: this is a simple example. I actually have a huge, multidimensional array that already has established pointers, or prefetched DOM nodes in it. Now I'm trying to replicate the array when a text version is loaded using ajax. I'm looking for a recursive approach to changing all of the null assignments with something that will immediately fetch the appropriate DOM node. Most likely I will need to do it with the response text, but was hoping I could do it with the php portion.
You're trying to stringify a reference to a javascript object in the memory of whatever computer is evaluating getElementById first, and that has no chance to represent something on the end client's computer.
Send the id instead:
function makearray1(){
array1=[1,'divID',['a','b'],[1,2]];
}
then, in the client:
function use(xxx){
window.document.getElementById(xxx[1]).innerHTML=xxx[2][0];
}
If you really want to eval it at the end, you can use this, I guess
function makearray1(){
array1=[1,"window.document.getElementById(\"divID\")",['a','b'],[1,2]];
}
I've no idea why you would want to do that though
Assuming the dom element exists in the second page, it should look something like this.
JS:
function packDomData(){
return {
"MySpecificYetBriefProperty0":1,
"DomID":"divID",
"MySpecificYetBriefProperty1":['a','b'],
"MySpecificYetBriefProperty2":[1,2]
};
}
function useDomData(domData){
document.getElementByID(domData.DomID).innerHTML=domData.MySpecificYetBriefProperty1[0];
}
PHP:
//Make sure the contents of this file is the json from packDomData. use json_encode in php or JSON.stringify in js
echo file_get_contents("text_file.txt");
var myData = JSON.parse(XMLHttpRequestObject.responseText);
useDomData(myData);
I used to code like you. Here are some tips that have helped turn my coding horror into a fun job:
Use objects with descriptive properties instead of arrays whenever you aren't actually looping through the array - I promise it will save you and others headache! "DomID" is much more flexible than 1, and if you change the order in the array, javascript gods help you that array is everywhere - including however many random text files on your server!
Also use descriptive names for functions
Always return a value from a function instead of using globals whenever possible, even where the result is then used as a nasty global. Trust me.
Never put javascript function names in an ajax call. Use JSON instead and keep the functions and other script in the javascript file where it belongs.
Mysql will save your life!!
Disclaimer - I didn't run this code but it should basically work when you get everything hooked up right.

PHP dynamic variable as jQuery selector

After hours of frustration, I finally found the line of code that has been causing an error, but now I need to know why.
jQuery was throwing this error: Uncaught Error: Syntax error, unrecognized expression: .
I've researched it and found that this is a Sizzle error that occurs when jQuery cannot find the selector that is referenced. As was suggested in other questions on SO, this was not actually an error in my jQuery code, it was elsewhere.
I was defining a variable to use as a target element to load content, and was using PHP to dynamically define the variable, like so:
var $container = $(".<? echo $target ?>");
This did not work, as the . is flagged as an unrecognized expression. However, replacing the PHP variable with a static string works fine:
var $container = $(".target");
This was so hard for me to find because I couldn't pinpoint the line that was throwing the error, and in the source from the browser, the initial line above looks just like the second line.
Why does the first example not work? Does it have to do with order of execution? And, how can I use a dynamic variable as a selector?
you have to use
<?php echo $test; ?>
or the shortcut:
<?= $test ?>
You can try trim($target) before doing this. If it works you probably have some unwanted spaces in that variable of yours.
Also consider using json_encode to pass variables from php to javascript. Like so:
var selector = <?php echo json_encode($target); ?>;
var $container = $(selector);
This will allow you to pass not only simple strings but more complex variable structures as well (and with encoding safety).
Turns out the page I was loading wasn't having the variable $target passed to it. On the initial page, $target was initialized with a value, and thus the source output looked as specified in the question. However, the ajax call I was making to reload the page with new data was not passing the variable.

Inserting output into page after document has been executed

In PHP have a situation where I need the page to be mostly executed, but have an item inserted into the output from that page.
I think output buffering may be of some help, but I can't work out how to implement it in my situation.
My code looks like this:
//this document is part of a global functions file
function pageHeader (){
//I'm using $GLOBALS here because it works, however I would really rather a better method if possible
$GLOBALS['error_handler'] = new ErrorHandler(); //ErrorHandler class sets a function for set_error_handler, which gets an array of errors from the executed page
require_once($_SERVER['DOCUMENT_ROOT'].'/sales/global/_header.php');
//I would like the unordered list from ->displayErrorNotice() to be displayed here, but if I do that the list is empty because the list was output before the rest of the document was executed
}
function pageFooter (){
$GLOBALS['error_handler'] ->displayErrorNotice(); //this function displays the errors as an html unordered list
include($_SERVER['DOCUMENT_ROOT']."/sales/global/_footer.php");
}
Most pages on the site include this document and use the pageHeader() and pageFooter() functions. What I am trying to achieve is to put an unordered list of the PHP generated errors into an HTML list just at a point after _header.php has been included. I can get the list to work as intended if I put it in the footer (after the document has been executed), but I don't want it there. I guess I could move it with JS, but I think there must be a PHP solution.
UPDATE
I'm wondering whether a callback function for ob_start() which searches the buffer by regex where to put the error list, and then inserts it will be the solution.
UPDATE 2 I have solved the problem, my answer is below. I will accept it in 2 days when I am allowed.
Worked it out finally. The key was to buffer the output, and search the buffer for a given snippet of html, and replace it with the unordered list.
My implementation is like this:
function outputBufferCallback($buffer){
return str_replace("<insert_errors>", $GLOBALS['error_handler']->returnErrorNotice(), $buffer);
}
function pageHeader (){
ob_start('outputBufferCallback');
//I'm using $GLOBALS here because it works, however I would really rather a better method if possible
$GLOBALS['error_handler'] = new ErrorHandler(); //ErrorHandler class sets a function for set_error_handler, which gets an array of errors from the executed page
require_once($_SERVER['DOCUMENT_ROOT'].'/sales/global/_header.php');
echo '<insert_errors>'; //this snippet is replaced by the ul at buffer flush
}
function pageFooter (){
include($_SERVER['DOCUMENT_ROOT']."/sales/global/_footer.php");
ob_end_flush();
}
If I'm getting this right, you're trying to insert some calculated code/errors between the header and footer. I'm guessing that the errors are being totalled/summed up at the very end of the page and would be completed after the page footer.
If this is true, I can't think of anyway to do this with pure php. It can only run through a page once, and cannot double back. What you can do is create an element after the footer and move it using javascript to the area where you want to display it. This would be the easiest way I would think. You can do this easily with jquery.
I can explain further if I am on the right track, but I'm not 100% sure what you're asking yet...
The jquery command you would use is .appendTo().

Manipulate $session->flash() view output in CakePHP

I am looking to manipulate the $session->flash() output in my CakePHP app, Currently I have the very simple default implementation of showing flash and auth error messages:
<?php
$session->flash();
$session->flash('auth');
?>
This produces a <div> with an ID and class that has the message inside. What I would like to do is wrap/replace the generated HTML, specifically with some jQuery UI classes, but wrapping is difficult as I am unable to tell when there is actually a message going to be displayed so I end up with an empty but style error div. What I really need for wrapping to work is to check in $session->flash() returns anything, but I get 'can't use method return value in write context' when checking it with empty();
As far as I can tell the generated HTML is hard coded into the session helper! Bonus points if you can work out how to change the class on the auth message and normal flash message independently.
To check if a message is going to be flashed, put this in the layout
<?php if($session->check('Message')){ echo $this->Session->flash();} ?>
CSS attributs can be set when you set the message to be flashed
http://book.cakephp.org/view/1311/Methods#setFlash-1313
read up on setFlash() and use the other params that the method takes to define your own elements. you can then do what ever you like.
http://book.cakephp.org/view/400/setFlash
A work-around solution I have found is to set $session->flash() to a variable and then check it with empty() so I can echo out the appropriate <div> if necessary.
$flashMessage = $this->flash();
$authMessage = $this->flash('auth');
.. and then check if each one is empty. Of course I have some unnecessary html inside there but as far as the auth message goes, I think this is as flexible as I can get.

Categories