Witam
Jest to Mój pierwszy temat na tym forum, więc proszę o zrozumienie.
Mam skrypt menu rozwijanego Accordion dokładnie w JQuery i PHP. Menu to jest dostosowane do PHP-Fusiona, i działa prawidłowo, ale jest jeden mały problem, w którym polski support niestety nie chce pomóc.
Przedstawię problem najprościej jak się tylko da.
Do menu mogę dodawać linki oraz kategorie, które się rozwijają i zawierają w sobie inne linki, Problem jest taki, że gdy pod normalnymi linkami dodam kategorie, to wszystkie nowo utworzone linki, wędrują to tejże kategorii. Mogę dodawać nowe kategorie i nowe linki do nich, ale nie mogę dodać żadnego bezpośredniego linku, poza kategorią, ponieważ jak już pisałem każdy nowy link, wędruje do ostatnio utworzonej kategorii.
Proszę was specjalistów o zobaczenie niżej podanych kodów i modyfikację, abym mógł dodawać nowe linki, na końcu menu poza kategorią.
Proszę się tez nie zniechęcać wielkością kodu. Proszę także o odpowiedzi tylko ludzi doświadczonych i znających Bardzo Dobrze te języki, nie potrzebuję przekierowań do kursów itd itp. Potrafię korzystać z google.
PHP:
<?php
/*-------------------------------------------------------+
| PHP-Fusion Content Management System
| Copyright (C) 2002 - 2008 Nick Jones
| http://www.php-fusion.co.uk/
+--------------------------------------------------------+
| Filename: accordion_navigation_panel.php
| Author: Robert Gaudyn (Wooya)
| Version: 1.0
+--------------------------------------------------------+
| This program is released as free software under the
| Affero GPL license. You can redistribute it and/or
| modify it under the terms of this license which you
| can read by viewing the included agpl.txt or online
| at www.gnu.org/licenses/agpl.html. Removal of this
| copyright header is strictly prohibited without
| written permission from the original author(s).
+--------------------------------------------------------*/
if (!defined("IN_FUSION")) { die("Access Denied"); }
add_to_head("<style type='text/css'>
/* A few IE bug fixes */
* html ul ul li a { height: 100%; }
* html ul li a { height: 100%; }
* html ul ul li { margin-bottom: -1px; }
</style>");
add_to_head("<script type='text/javascript' src='".INFUSIONS."accordion_navigation_panel/accordion.js'></script>");
add_to_head("<script type='text/javascript'>
jQuery().ready(function(){
// applying the settings
jQuery('#navigation').Accordion({
active: 'h2.selected',
header: 'h2.head',
alwaysOpen: false,
animated: true,
showSpeed: 400,
hideSpeed: 800
});
});
</script>");
$list_open = false;
$i = 0;
openside($locale['global_001']);
$result = dbquery(
"SELECT tl.link_name, tl.link_url, tl.link_window, tl.link_order FROM ".DB_SITE_LINKS." tl
WHERE ".groupaccess('tl.link_visibility')." AND link_position<='2'
ORDER BY link_order"
);
if (dbrows($result)) {
echo "<div id='navigation'>\n";
echo "<div id='nav_bok'></div>";
while($data = dbarray($result)) {
if ($data['link_name'] != "---" && $data['link_url'] == "---") {
if ($list_open) { echo "</ul>\n"; $list_open = false; }
//echo "<h2 class='".(!$i ? "selected" : "head")."'>".$data['link_name']."</h2>\n";
echo "<h2 class='".(!$i ? "head" : "head")."' style='cursor:pointer'>".$data['link_name']."</h2>\n";
} else if ($data['link_name'] == "---" && $data['link_url'] == "---") {
if ($list_open) { echo "</ul>\n"; $list_open = false; }
echo "<hr class='side-hr' />\n";
} else {
if (!$list_open) { echo "<ul>\n"; $list_open = true; }
$link_target = ($data['link_window'] == "1" ? " target='_blank'" : "");
if (strstr($data['link_url'], "http://") || strstr($data['link_url'], "https://")) {
echo "<li><a href='".$data['link_url']."'".$link_target." class='side'>".THEME_BULLET." <span>".$data['link_name']."</span></a></li>\n";
} else {
echo "<li><a href='".BASEDIR.$data['link_url']."'".$link_target." class='side'>".THEME_BULLET." <span>".$data['link_name']."</span></a></li>\n";
}
}
$i++;
}
if ($list_open) { echo "</ul>\n"; }
echo "</div>\n";
} else {
echo $locale['global_002'];
}
closeside();
?>
JQuery:
/*
* Accordion 1.3 - jQuery menu widget
*
* Copyright (c) 2006 Jörn Zaefferer, Frank Marcia
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Revision: $Id: jquery.accordion.js 1524 2007-03-13 20:09:19Z joern $
*
*/
/**
* Make the selected elements Accordion widgets.
*
* Semantic requirements:
*
* If the structure of your container is flat with unique
* tags for header and content elements, eg. a definition list
* (dl > dt + dd), you don't have to specify any options at
* all.
*
* If your structure uses the same elements for header and
* content or uses some kind of nested structure, you have to
* specify the header elements, eg. via class, see the second example.
*
* Use activate(Number) to change the active content programmatically.
*
* A change event is triggered everytime the accordion changes. Apart from
* the event object, all arguments are jQuery objects.
* Arguments: event, newHeader, oldHeader, newContent, oldContent
*
* @example jQuery('#nav').Accordion();
* @before <dl id="nav">
* <dt>Header 1</dt>
* <dd>Content 1</dd>
* <dt>Header 2</dt>
* <dd>Content 2</dd>
* </dl>
* @desc Creates an Accordion from the given definition list
*
* @example jQuery('#nav').Accordion({
* header: 'div.title'
* });
* @before <div id="nav">
* <div>
* <div class="title">Header 1</div>
* <div>Content 1</div>
* </div>
* <div>
* <div class="title">Header 2</div>
* <div>Content 2</div>
* </div>
* </div>
* @desc Creates an Accordion from the given div structure
*
* @example jQuery('#nav').Accordion({
* header: 'a.head'
* });
* @before <ul id="nav">
* <li>
* <a class="head">Header 1</a>
* <ul>
* <li><a href="#">Link 1</a></li>
* <li><a href="#">Link 2></a></li>
* </ul>
* </li>
* <li>
* <a class="head">Header 2</a>
* <ul>
* <li><a href="#">Link 3</a></li>
* <li><a href="#">Link 4></a></li>
* </ul>
* </li>
* </ul>
* @desc Creates an Accordion from the given navigation list
*
* @example jQuery('#accordion').Accordion().change(function(event, newHeader, oldHeader, newContent, oldContent) {
* jQuery('#status').html(newHeader.text());
* });
* @desc Updates the element with id status with the text of the selected header every time the accordion changes
*
* @param Map options key/value pairs of optional settings.
* @option String|Element|jQuery|Boolean active Selector for the active element, default is the first child, set to false to display none at start
* @option String|Element|jQuery header Selector for the header element, eg. div.title, a.head, default is the first child's tagname
* @option String|Number showSpeed Speed for the slideIn, default is 'slow' (for numbers: smaller = faster)
* @option String|Number hideSpeed Speed for the slideOut, default is 'fast' (for numbers: smaller = faster)
* @option String selectedClass Class for active header elements, default is 'selected'
* @option Boolean alwaysOpen Whether there must be one content element open, default is true.
* @option Boolean animated Set to false to disable animations. Default: true
* @option String event The event on which to trigger the accordion, eg. "mouseover". Default: "click"
*
* @type jQuery
* @see activate(Number)
* @name Accordion
* @cat Plugins/Accordion
*/
/**
* Activate a content part of the Accordion programmatically at the given zero-based index.
*
* If the index is not specified, it defaults to zero, if it is an invalid index, eg. a string,
* nothing happens.
*
* @example jQuery('#accordion').activate(1);
* @desc Activate the second content of the Accordion contained in <div id="accordion">.
*
* @example jQuery('#nav').activate();
* @desc Activate the first content of the Accordion contained in <ul id="nav">.
*
* @param Number index (optional) An Integer specifying the zero-based index of the content to be
* activated. Default: 0
*
* @type jQuery
* @name activate
* @cat Plugins/Accordion
*/
/**
* Override the default settings of the Accordion. Affects only following plugin calls.
*
* @example jQuery.Accordion.setDefaults({
* showSpeed: 1000,
* hideSpeed: 150
* });
*
* @param Map options key/value pairs of optional settings, see Accordion() for details
*
* @type jQuery
* @name setDefaults
* @cat Plugins/Accordion
*/
jQuery.fn.extend({
// nextUntil is necessary, would be nice to have this in jQuery core
nextUntil: function(expr) {
var match = [];
// We need to figure out which elements to push onto the array
this.each(function(){
// Traverse through the sibling nodes
for( var i = this.nextSibling; i; i = i.nextSibling ) {
// Make sure that we're only dealing with elements
if ( i.nodeType != 1 ) continue;
// If we find a match then we need to stop
if ( jQuery.filter( expr, [i] ).r.length ) break;
// Otherwise, add it on to the stack
match.push( i );
}
});
return this.pushStack( match );
},
// the plugin method itself
Accordion: function(settings) {
// setup configuration
settings = jQuery.extend({}, jQuery.Accordion.defaults, {
// define context defaults
header: jQuery(':first-child', this)[0].tagName // take first childs tagName as header
}, settings);
// calculate active if not specified, using the first header
var container = this,
active = settings.active
? jQuery(settings.active, this)
: settings.active === false
? jQuery("<div>")
: jQuery(settings.header, this).eq(0),
running = 0;
container.find(settings.header)
.not(active || "")
.nextUntil(settings.header)
.hide();
active.addClass(settings.selectedClass);
function clickHandler(event) {
// get the click target
var clicked = jQuery(event.target);
// due to the event delegation model, we have to check if one
// of the parent elements is our actual header, and find that
if ( clicked.parents(settings.header).length ) {
while ( !clicked.is(settings.header) ) {
clicked = clicked.parent();
}
}
var clickedActive = clicked[0] == active[0];
// if animations are still active, or the active header is the target, ignore click
if(running || (settings.alwaysOpen && clickedActive) || !clicked.is(settings.header))
return;
// switch classes
active.toggleClass(settings.selectedClass);
if ( !clickedActive ) {
clicked.addClass(settings.selectedClass);
}
// find elements to show and hide
var toShow = clicked.nextUntil(settings.header),
toHide = active.nextUntil(settings.header),
data = [clicked, active, toShow, toHide];
active = clickedActive ? jQuery([]) : clicked;
// count elements to animate
running = toHide.size() + toShow.size();
var finished = function(cancel) {
running = cancel ? 0 : --running;
if ( running )
return;
// trigger custom change event
container.trigger("change", data);
};
// TODO if hideSpeed is set to zero, animations are crappy
// workaround: use hide instead
// solution: animate should check for speed of 0 and do something about it
if ( settings.animated ) {
if ( !settings.alwaysOpen && clickedActive ) {
toShow.slideToggle(settings.showSpeed);
finished(true);
} else {
toHide.filter(":hidden").each(finished).end().filter(":visible").slideUp(settings.hideSpeed, finished);
toShow.slideDown(settings.showSpeed, finished);
}
} else {
if ( !settings.alwaysOpen && clickedActive ) {
toShow.toggle();
} else {
toHide.hide();
toShow.show();
}
finished(true);
}
return false;
};
function activateHandlder(event, index) {
// call clickHandler with custom event
clickHandler({
target: jQuery(settings.header, this)[index]
});
};
return container
.bind(settings.event, clickHandler)
.bind("activate", activateHandlder);
},
// programmatic triggering
activate: function(index) {
return this.trigger('activate', [index || 0]);
}
});
jQuery.Accordion = {};
jQuery.extend(jQuery.Accordion, {
defaults: {
selectedClass: "selected",
showSpeed: 'slow',
hideSpeed: 'fast',
alwaysOpen: true,
animated: true,
event: "click"
},
setDefaults: function(settings) {
jQuery.extend(jQuery.Accordion.defaults, settings);
}
});