I have a list of links sitting inside a tag right now. I would like for the page to 'reorganize' the order of each link on page reload (page view) and display the results.
For example:
<div id="testgroup">
1
2
3
4
5
</div>
On page reload, the soure code would look like:
<div id="testgroup">
5
1
3
4
2
</div>
or some other random order
Is there a very basic jQuery DOM manipulation script to accomplish this? If it helps, the page is built on PHP as well.
If simplicity is more important than randomness:
You can use get to convert the jQuery object to an array, then use the native sort with a function designed to randomize it. Then put the randomly arranged array back into the DOM.
var array = $("#testgroup").children().get().sort( function() {
return 0.5 - Math.random();
});
$("#testgroup").append(array);
Demo: http://jsfiddle.net/4e7cs/
If you are looking for true shuffling:
You can utilize the Fisher-Yates shuffle:
var array = $("#testgroup").children().toArray();
var i = array.length,
j, temp;
while (--i) {
j = Math.floor(Math.random() * (i + 1));
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
$("#testgroup").append(array);
Demo: http://jsfiddle.net/4e7cs/3/
Here is a writeup on why the first is bad, but I'll leave it here for completeness.
PHP has a shuffle() function to randomize arrays. You can do the randomization on the server side.
<?php
$links = array(
1 => '1.html',
2 => '2.html',
3 => '3.html',
4 => '4.html',
5 => '5.html'
);
$shuffledLinks = shuffle_assoc($links);
foreach ($shuffledLinks as $value=>$key) {
echo '<a href="'.$key.'" id='.$value.'>'.$value.'</a><br/>';
}
function shuffle_assoc($list) {
if (!is_array($list)) return $list;
$keys = array_keys($list);
shuffle($keys);
$random = array();
foreach ($keys as $key)
$random[$key] = $list[$key];
return $random;
}
?>
Ok...this is now fixed and tested. Actually shuffle() did not work on associative arrays so I borrowed andjones at gmail dot com's shuffle_assoc() function for that.
I also mixed up my concatenation where I was using '+' instead of '.' O.o Mixing up my JavaScript and PHP syntax. I apologize about that.
Allen
I'm using a plugin that actualy does that : http://james.padolsey.com/javascript/sorting-elements-with-jquery/
But if you are using PHP you could sort it directly on the server?
Related
I'm trying to work with array using array_walk() function such way:
<?php
$array = array('n1' => 'b1', 'n2' => 'b2', 'n3' => 'b3');
array_walk($array, function(&$val, $key) use (&$array){
echo $key."\n";
if ($key == 'n1')
$val = 'changed_b1';
if ($key == 'n2' || $key == 'n3') {
unset($array[$key]);
}
});
print_r($array);
Get:
n1
n2
Array
(
[n1] => changed_b1
[n3] => b3
)
It seems, what after deletion of 2nd element -- 3rd element don't be sended to callback function.
Use array_filter:
<?php
$filtered = array_filter($array, function($v,$k) {
return $k !== "n2" && $k !== "n3";
}, ARRAY_FILTER_USE_BOTH);
?>
See http://php.net/array_filter
What you can do is use a secondary array, which will give the effect that those nodes have been deleted, like;
<?php
$array = array('n1' => 'b1', 'n2' => 'b2', 'n3' => 'b3');
$arrFinal = array();
array_walk($array, function($val, $key) use (&$array, &$arrFinal){
echo $key."\n";
if ($key == 'n2' || $key == 'n3') {
//Don't do anything
} else {
$arrFinal[$key] = $val;
}
});
print_r($arrFinal);
https://eval.in/206159
From the documentation:
Only the values of the array may potentially be changed; its structure cannot be altered, i.e., the programmer cannot add, unset or reorder elements. If the callback does not respect this requirement, the behavior of this function is undefined, and unpredictable.
May be that's the reason why you don't get the desired output with your code. Hope it helps.
Possible alternatives:
If you still want to use array_walk(), simply create a new array and copy the 'required' elements i.e. with indices you don't want to delete into the new array. This is a preferred alternative if number of elements to be deleted are very large.
You could look into array_filter or array_map, both rely on applying a callback to every element of your array. You could simply put a condition there barring the indices you want to delete in this callback function. This would work if the number of elements you want to delete are very few.
If however, the elements to delete are contiguous and form a 'portion' of an array (in your case you wanted to remove n2 and n3 which are adjacent). You can use the function array_splice
Sidenote - I am refraining from putting in any code snippets as I have linked the relevant documentations and getting started with them should be a good exercise in itself.
I realize this is several years old, but I found the thread while looking for the solution to a similar situation.
I wound up using preg_grep to return only the array that I wanted to walk, in case anyone finds it useful.
So, in my case, I wanted to ignore files in a scandir array with a "." prefix (system files), then apply a new prefix to the remaining files.
Here's what I wound up with:
$fl = array_map(function($i){
return $new_prefix . "/" . $i;
}, preg_grep("/^[^\.]/", scandir($path)));
If you can build a regex to exclude the undesired array elements, this solution should work.
check the "array_walk" source code and u will see. array_walk use pos to fetch item, and in every loop, the pos move forward.
do {
/* Retrieve value */
zv = zend_hash_get_current_data_ex(target_hash, &pos);
/* Retrieve key */
zend_hash_get_current_key_zval_ex(target_hash, &args[1], &pos);
/* Move to next element already now -- this mirrors the approach used by foreach
* and ensures proper behavior with regard to modifications. */
zend_hash_move_forward_ex(target_hash, &pos);
/* Back up hash position, as it may change */
EG(ht_iterators)[ht_iter].pos = pos;
and reset pos to get value
/* Reload array and position -- both may have changed */
if (Z_TYPE_P(array) == IS_ARRAY) {
pos = zend_hash_iterator_pos_ex(ht_iter, array);
target_hash = Z_ARRVAL_P(array);
} else if (Z_TYPE_P(array) == IS_OBJECT) {
target_hash = Z_OBJPROP_P(array);
pos = zend_hash_iterator_pos(ht_iter, target_hash);
} else {
php_error_docref(NULL, E_WARNING, "Iterated value is no longer an array or object");
result = FAILURE;
break;
}
if key= n1; then next pos 1
if key= n2; then next pos 2
if key= n3; then next pos 3
when run [$key == 'n2'] , the next pos is 2 ; after unset , pos 2 is unreachable ,so the loop end.
so in actually ,then $key=='n3' will not happen, and u will get the result.
I have a function in php that selects the array with that contains the most elements.
$firstArray = array('firstArray','blah','blah','blah');
$secondArray = array('secondArray','blah','blah');
$thirdArray = array('thirdArray','blah','blah','blah','blah');
then I get the name of the variable with the highest length like this:
$highest = max($firstArray, $secondArray, $thirdArray)[0];
but I am developing an application and I want to avoid using php and I have tried javascript's Math.max() to achieve the same results but it doesn't work the same way unless I do
Math.max(firstArray.length, secondArray.length, thirdArray.length)
But this is useless since I need to know the name of the array that contains the most elements. Is there any other way to achieve this?
This function takes as input an array of arrays, and returns the largest one.
function largestArray(arrays){
var largest;
for(var i = 0; i < arrays.length; i++){
if(!largest || arrays[i].length > largest.length){
largest = arrays[i];
}
}
return largest;
}
We can test it out with your example:
firstArray = ['firstArray','blah','blah','blah'];
secondArray = ['secondArray','blah','blah'];
thirdArray = ['thirdArray','blah','blah','blah','blah'];
// should print the third array
console.log(largestArray([firstArray, secondArray, thirdArray]));
The following url has a max() equivalent. It supports more then just numbers just like in php:
js max equivalent of php
If you feel ok with including 3rd-party libs, maybe http://underscorejs.org/#max does what you want:
var aList = [firstArray, secondArray, thirdArray];
_.max(aList, function(each) { return each.length; });
I have an array that I want to alter. I thought that array_walk would be the way to go but I'm having trouble figuring out how to collect that data from array_walk, deleting the data from the old array, and inserting the new data. How should I go about doing this? Here is the code.
$width_array = array(
"2.5%",
"2.6%",
"2.7%",
"2.8%",
);
function adjust_the_width($value)
{
$value = $value * 2;
}
array_walk($width_array, "adjust_the_width");
$random_width = array_rand($width_array, 10);
You where likely looking for array_map, example below:
<?
$width_array = array(
"2.5%",
"2.6%",
"2.7%",
"2.8%",
);
function adjust_the_width($value) {
return $value * 2;
}
$width_array = array_map("adjust_the_width", $width_array);
$random_width = array_rand($width_array, count($width_array));
var_dump($width_array);
Note: the percentages are dropped from the calculations because PHP interprets the string "2.5%" as a float value when it is multiplied by 2.
Also, array_map supplies each element as the parameter to the function provided and uses it's return value to fill the same place in the new array that array_map builds.
This is also why I assign $width_array = array_map(..., array_map builds a new array, it does not replace the old one by default.
You can also do this if you'd rather not build the intermediate array:
foreach($width_array as &$width) {
$width = $width * 2;
}
var_dump($width_array);
This walks the array and modifies each element as a reference to it's location (that's what &$width means).
Without the '&' this foreach loop will do nothing but chew cpu cycles.
I have a slight problem. I have several arrays in php with different team names. Each array contains teams of a certain league. When I click an add button I get the option to add a new entry to the calendar. I want the drop down to have only the teams for that league. onclick of the add button I call a javascript function that knows what division was clicked. However in order to give the javascript the information for which teams to display I have to pass it one of the php arrays. The problem I am having is telling php which array to pass to javascript depending on which league javascript is on. I don't want to specify the array myself because there is an option to add a league and this would mean having to code in more code each time a league is added. The point of the site is being dynamic.
here is some code.
for ($i = 0;$i<$sizeof($leaguesarray);$i++){
$htmlimploded[$i] = implode($html[$i]);
}
here I have used emplode to make all of my php arrays readable into javascript.
for (var h = 0; h<size; h++){ // goes through every league
if(h == leaguenum){ // finds the league for the clicked add button
// this is the line that I have trouble with I can't think of
//anyway of telling it which array to use since it is serverside code.
var myarray = ["<? echo $htmlimploded[]?>"];
}
}
Javascript code above.
Imploding works but why not json_encode($array)? It's a simpler, built in way to turn php arrays into javascript objects or arrays. If you have something like:
$league1 = array('team1', 'team2');
$league2 = array('team3, 'team4') ;
Then make a multidimensional associative array of these:
$all_teams = array('league1'=>$league1, 'league2'=>$league2);
encode it into a Javascript object and print it into your JS:
$encoded = json_encode($all_teams);
print 'var teamObject = '.$encoded.';';
If you were to console.log(teamObject) you'd see something like this:
{"league1": ["team1", "team2"], "league2": ["team3", "team4"]}
Looks complicated, but now you can pull out the array you desire very easily. The league 1 array is teamObject.league1 and the league2 array is teamObject.league2, and so on.
i think you missed something in the following code:
var myarray = ["<? echo $htmlimploded[]?>"];
By right, it should be:
var myarray = ["<?php echo $htmlimploded[]?>"];
Assuming that PHP knows the names of the leagues and the teams and that JavaScript knows the league name that is clicked, You can wrap the arrays of the team names inside an object with the league as the name of the property.
<?php
$arr = array("League1" => array("Team 1", "Team 2"),
"League2" => array("Team 3", "Team 4")
);
?>
var obj = {};
<?php foreach ($arr as $k => $v): ?>
obj.<?php echo $k; ?> = ["<?php echo implode('","', $v); ?>"];
<?php endforeach; ?>
Then when a user selects a league, you can loop through the array of the property (which is the league name) of the object.
clickedLeague = "League1";
for (var i = 0; i < obj[clickedLeague].length; i++)
{
console.log(obj[clickedLeague][i]); // Logs the team name to console
}
I have a menu system that uses a drag and drop tree structure to make it easy for a user to modify. When the javascript serializes the string, it does it in the following way:
// Assume each of these items has an ID on with the respective numbers attached
Menu Item 1
+ Menu Item 2
+ Menu Item 3
+ Menu Item 4
Menu Item 5
Menu Item 6
+ Menu Item 7
This will then get serialized as:
1>2>3>>4#5#6>7
The problem with this is that there could be an arbitrary number of sublevels, which makes it difficult to unserialize. I'm using PHP server side to unserialize it but I am at a loss as to what to do.
Any suggestions welcome, even to the method of serialization, I’ll just hack the code.
You should look into json_encode/json_decode functions in PHP, those make interacting with Javascript really easy.
With your current serialization format you are just creating headaches for yourself.
I think you can split this string first by '#', then each split result splits by regex to exactly "number>number" so ">>" will not be there, then "number>>number" and so on.
Hope it helps.Sorry for my english.
If you really wanted to use that format, something like this would work, but I think JSON would be much better.
<?php
$str = '1>2>3>>4#5#6>7';
preg_match_all('~([^\d]+)?([\d]+)~', $str, $matches, PREG_SET_ORDER);
//$current is the nodes from the top to the node we are at currently
$current = array();
$result = array();
foreach ($matches as $item) {
$id = $item[2];
if (!$item[1] || $item[1] == '#') {
$level = 0;
} else {
$level = strlen($item[1]);
}
$tmp = array( 'id' => $id );
$current[ $level ] = & $tmp;
if ($level == 0) {
$result[] = & $tmp;
} elseif (isset($current[ $level - 1 ])) {
$parent = & $current[ $level - 1 ];
if (!isset($parent['children'])) {
$parent['children'] = array();
}
$parent['children'][] = & $tmp;
unset($parent);
}
unset($tmp);
}
print_r($result);
What about to serialize (instead of your string 1>2>3>>4#5#6>7) into JSON form like this:
{'1': {'2': {'3': {'4': true}}}, '5': true, '6': {'7': true}}
Then you can unserialize it using json_decode in PHP.
EDIT: for the people voting this down months after it was asked, the original format of this question DID NOT mention json or javascript. Therefore I answered in PHP, as the OP answered in the comments he corrected himself after my response, I left my answer for people getting to this page when they're searching for the PHP answer for this question even though this question isn't (now) directly answering it.
hmm...
http://php.net/manual/en/function.serialize.php
http://php.net/manual/en/function.unserialize.php
so:
$var_name = serialize( array("Menu Item 1, Menu Item 2, Menu Item 3, etc...") );
// do whatever
$var_name2 = unserialize($var_name);
Would that be a good method for you to use?