在Joomla 2.5上运行 在iphone上测试
工作示例 http://demo.gavick.com/joomla25/twn2/
非工作示例 http://www.prpg-tc.org.sg/
我无法在移动版本上切换菜单以打开/关闭。检查了CSS和JS,所有工作正常,没有损坏的链接不确定发生了什么?
还比较了这两个来源,我认为它不应该是JS冲突。
这是调用移动版本的php。
<?php
// No direct access.
defined('_JEXEC') or die;
$mobile_logo_image = $this->getParam('mobile_logo_image', '');
if($mobile_logo_image == '') {
$mobile_logo_image = $this->URLtemplate() . '/images/mobile/header_logo.png';
} else {
$mobile_logo_image = $this->URLbase() . $mobile_logo_image;
}
$tpl_name = str_replace(' ', '_', JText::_('TPL_GK_LANG_NAME'));
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
<head>
<jdoc:include type="head" />
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0" />
<?php $this->loadBlock('mobile' . DS . 'head.iphone'); ?>
</head>
<body>
<div id="gkWrap">
<div id="gkTopWrap">
<?php if($this->getParam('mobile_logo_type', 'image') == 'css') : ?>
<h1 id="gkHeader" class="cssLogo">
<a href="./"><?php echo $this->getPageName(); ?></a>
<?php else : ?>
<h1 id="gkHeader"> <a href="./"><img src="<?php echo $mobile_logo_image; ?>" alt="<?php echo $this->getPageName(); ?>" /></a>
<?php endif; ?>
</h1>
<?php //if($this->getParam('mobile_desktop', 0) == '1') : ?>
<!--a href="#" id="gk-btn-switch" ><span><?php //echo JText::_('TPL_GK_LANG_GK_MOBILE_DESKTOP'); ?></span></a-->
<?php //endif; ?>
<?php if($this->getParam('mobile_register', 0) == '1') : ?>
<a href="<?php echo $this->URLbase(); ?>index.php?option=com_users&view=registration" id="gk-btn-register" ><span><?php echo JText::_('TPL_GK_LANG_GK_MOBILE_REGISTER'); ?></span></a>
<?php endif; ?>
<?php if($this->getParam('mobile_login', 0) == '1') : ?>
<a href="<?php echo $this->URLbase(); ?>index.php?option=com_users&view=login" id="gk-btn-login" ><span><?php echo JText::_('TPL_GK_LANG_GK_MOBILE_LOGIN'); ?></span></a>
<?php endif; ?>
</div>
<div id="gkNav">
<div id="gkNavContent"> <a href="#" id="gk-btn-menu" ><?php echo JText::_('TPL_GK_LANG_GK_MOBILE_MENU'); ?></a>
<?php if($this->getParam('mobile_search', 0) == '1') : ?>
<a href="#" id="gk-btn-search" ><?php echo JText::_('TPL_GK_LANG_GK_MOBILE_SEARCH'); ?></a>
<?php endif; ?>
<!--jdoc:include type="modules" name="m_feedback" style="gk_mobile" /-->
<a href="index.php/feedback" id="gk-btn-feedback">Feedback</a> <a href="#" id="gk-btn-nav-prev" class="button"><span><?php echo JText::_('TPL_GK_LANG_GK_MOBILE_BACK'); ?></span></a> <a href="#" id="gk-btn-nav-close" class="button"><span><?php echo JText::_('TPL_GK_LANG_GK_MOBILE_CLOSE'); ?></span></a> </div>
<div id="gkMenuContent">
<?php
$this->menu->loadMenu($this->getParam('mobile_menu_name','mainmenu'));
$this->menu->genMenu(0, -1);
?>
</div>
</div>
<?php if($this->getParam('mobile_search', 0) == '1') : ?>
<div id="gkSearch">
<form method="post" action="index.php">
<p>
<input type="text" class="inputbox" id="mod-search-searchword" name="searchword">
<input type="hidden" value="search" name="task">
<input type="hidden" value="com_search" name="option">
<input type="hidden" value="435" name="Itemid">
</p>
</form>
</div>
<?php endif; ?>
<div id="gkContent">
<?php if($this->modules('mobile_top')) : ?>
<div id="gkTop">
<jdoc:include type="modules" name="mobile_top" style="gk_mobile" />
</div>
<?php endif; ?>
<div id="gkMain">
<jdoc:include type="message" />
<jdoc:include type="component" />
</div>
<?php //if($this->modules('mobile_bottom')) : ?>
<jdoc:include type="modules" name="mobile_main" style="gk_mobile" />
<div id="mobile_custom">
<jdoc:include type="modules" name="msearch_mp" style="gk_mobile" />
</div>
<div id="gkBottom">
<jdoc:include type="modules" name="mobile_links" style="gk_mobile" />
<!--jdoc:include type="modules" name="bottom4" style="gk_mobile" /-->
<jdoc:include type="modules" name="mobile_bottom" style="gk_mobile" />
</div>
<?php //endif; ?>
<div id="gkFooter">
<p id="gkCopyrights"><?php echo $this->getParam('copyrights', ''); ?></p>
<p id="gkOptions"> <a href="#gkHeader"><?php echo JText::_('TPL_GK_LANG_MOBILE_TOP'); ?></a> <a href="javascript:setCookie('gkGavernMobile<?php echo $tpl_name; ?>', 'desktop', 365);window.location.reload();"><?php echo JText::_('TPL_GK_LANG_MOBILE_SWITCH_DESKTOP'); ?></a> </p>
</div>
</div>
</div>
<div id="gkTranslations"> <span id="translation-name"><?php echo JText::_('TPL_GK_LANG_NAME'); ?></span> <span id="translation-confirm"><?php echo JText::_('TPL_GK_LANG_MOBILE_SWITCH_AGREE'); ?></span> </div>
<?php
// put Google Analytics code
$this->googleAnalyticsParser();
?>
</body>
</html>
这是切换这种情况的JS
$ = Zepto;
$(document).ready(function(){
/*
Menu code
*/
// stack of opened submenus
var openedStack = [];
// array of all submenus
var submenus = [];
// change all hrefs in links with submenu to #
$('#gkNav a.haschild').each(function(i,el){
$(el).attr('href', '#'+i);
var submenu = $(el).parent().find('ul').first();
submenu.css('display', 'none');
$('#gkMenuContent').dom[0].appendChild(submenu.dom[0]);
submenus[i] = submenu;
});
// prepare events
$('#gkNav a.haschild').bind('click', function(e){
var submenu = $(submenus[parseInt($(e.target).attr('href').replace('#', ''))]);
openedStack.push(submenu);
btnBack.css('display', 'inline-block');
openedStack[openedStack.length-2].css('display', 'none');
submenu.css('display', 'block');
});
// prepare buttons handlers
var btnMenu = $('#gk-btn-menu');
var btnSearch = $('#gk-btn-search');
var btnSwitch = $('#gk-btn-switch');
var btnBack = $('#gk-btn-nav-prev');
var btnClose = $('#gk-btn-nav-close');
// switcher desktop-mobile
if(btnSwitch) {
btnSwitch.bind('click', function(e){
e.preventDefault();
var agree = confirm($('#translation-confirm').html());
if(agree) {
setCookie('gkGavernMobile'+$('#translation-name').html(), 'desktop', 365);
window.location.reload();
}
});
}
// menu button
btnMenu.bind('click', function() {
$('#gkMenuContent').css('display', 'block');
$('#gkContent').css('opacity', 0.3);
// hide / show buttons
btnMenu.css('display', 'none');
btnSearch.css('display', 'none');
btnClose.css('display', 'block');
openedStack.push($('#gkMenuContent').find('ul').first());
});
// menu close button
btnClose.bind('click', function() {
$('#gkMenuContent').css('display', 'none');
$('#gkContent').css('opacity', 1.0);
// hide / show buttons
btnMenu.css('display', 'inline-block');
btnSearch.css('display', 'inline-block');
btnClose.css('display', 'none');
btnBack.css('display', 'none');
// reset menu
$('#gkMenuContent ul').css('display', 'none');
$('#gkMenuContent > ul').first().css('display', 'block');
openedStack = [];
});
// menu back button
btnBack.bind('click', function() {
var toHide = openedStack.pop();
if(openedStack.length == 1) btnBack.css('display', 'none');
$('#gkMenuContent ul').css('display', 'none');
openedStack[openedStack.length-1].css('display', 'block');
});
if(btnSearch) {
var search_opened = false;
btnSearch.bind('click', function() {
$('#gkSearch').css('display', (search_opened) ? 'none' : 'block');
search_opened = !search_opened;
});
}
/*
Collapsible blocks code
*/
if($('.gkCollapsible').length > 0) {
$('.gkCollapsible').each(function(i, el) {
$(el).bind('click', function(){
var toggled = $($('.gkFeaturedItem').get(i));
if(toggled.css('display') == 'none' || toggled.css('display') == '') {
$($('.gkFeaturedItem').get(i)).css('display', 'block');
$($('.gkToggle').get(i)).attr('class', 'gkToggle hide');
} else {
$($('.gkFeaturedItem').get(i)).css('display', 'none');
$($('.gkToggle').get(i)).attr('class', 'gkToggle show');
}
});
$('a',el).bind('click', function(e) {
e.preventDefault(); // disable links on toggler
});
});
}
});
function setCookie(c_name, value, expire) {
var exdate=new Date();
exdate.setDate(exdate.getDate()+expire);
document.cookie=c_name+ "=" +escape(value) + ((expire==null) ? "" : ";expires=" + exdate.toUTCString());
}
这是zepto.js
var Zepto = (function() {
var slice = [].slice, key, css, $$, fragmentRE, container, document = window.document, undefined;
// fix for iOS 3.2
if (String.prototype.trim === undefined)
String.prototype.trim = function(){ return this.replace(/^\s+/, '').replace(/\s+$/, '') };
function classRE(name){ return new RegExp("(^|\\s)" + name + "(\\s|$)") }
function compact(array){ return array.filter(function(item){ return item !== undefined && item !== null }) }
function flatten(array){ return array.reduce(function(a,b){ return a.concat(b) }, []) }
function camelize(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }
fragmentRE = /^\s*<.+>/;
container = document.createElement("div");
function fragment(html) {
container.innerHTML = ('' + html).trim();
var result = slice.call(container.childNodes);
container.innerHTML = '';
return result;
}
function Z(dom, selector){
this.dom = dom || [];
this.length = this.dom.length;
this.selector = selector || '';
}
function $(selector, context){
if (selector == document) return new Z;
else if (context !== undefined) return $(context).find(selector);
else if (typeof selector === 'function') return $(document).ready(selector);
else {
var dom;
if (selector instanceof Z) dom = selector.dom;
else if (selector instanceof Array) dom = compact(selector);
else if (selector instanceof Element || selector === window) dom = [selector];
else if (fragmentRE.test(selector)) dom = fragment(selector);
else dom = $$(document, selector);
return new Z(dom, selector);
}
}
$.extend = function(target, source){ for (key in source) target[key] = source[key]; return target }
$.qsa = $$ = function(element, selector){ return slice.call(element.querySelectorAll(selector)) }
$.fn = {
ready: function(callback){
document.addEventListener('DOMContentLoaded', callback, false); return this;
},
get: function(idx){ return idx === undefined ? this.dom : this.dom[idx] },
size: function(){ return this.length },
remove: function(){ return this.each(function(){ this.parentNode.removeChild(this) }) },
each: function(callback){
this.dom.forEach(function(el, idx){ callback.call(el, idx, el) });
return this;
},
filter: function(selector){
return $(this.dom.filter(function(element){
return $$(element.parentNode, selector).indexOf(element) >= 0;
}));
},
is: function(selector){
return this.length > 0 && $(this.dom[0]).filter(selector).length > 0;
},
first: function(){ return $(this.get(0)) },
last: function(){ return $(this.get(this.length - 1)) },
find: function(selector){
var result;
if (this.length == 1) result = $$(this.get(0), selector);
else result = flatten(this.dom.map(function(el){ return $$(el, selector) }));
return $(result);
},
closest: function(selector, context){
var node = this.dom[0], nodes = $$(context !== undefined ? context : document, selector);
if (nodes.length === 0) node = null;
while(node && node !== document && nodes.indexOf(node) < 0) node = node.parentNode;
return $(node);
},
parents: function(selector){
var ancestors = [], nodes = this.get();
while (nodes.length > 0)
nodes = compact(nodes.map(function(node){
if ((node = node.parentNode) && node !== document && ancestors.indexOf(node) < 0) {
ancestors.push(node);
return node;
}
}));
ancestors = $(ancestors);
return selector === undefined ? ancestors : ancestors.filter(selector);
},
parent: function(selector){
var node, nodes = [];
this.each(function(){
if ((node = this.parentNode) && nodes.indexOf(node) < 0) nodes.push(node);
});
nodes = $(nodes);
return selector === undefined ? nodes : nodes.filter(selector);
},
pluck: function(property){ return this.dom.map(function(element){ return element[property] }) },
show: function(){ return this.css('display', 'block') },
hide: function(){ return this.css('display', 'none') },
prev: function(){ return $(this.pluck('previousElementSibling')) },
next: function(){ return $(this.pluck('nextElementSibling')) },
html: function(html){
return html === undefined ?
(this.length > 0 ? this.dom[0].innerHTML : null) :
this.each(function(){ this.innerHTML = html });
},
text: function(text){
return text === undefined ?
(this.length > 0 ? this.dom[0].innerText : null) :
this.each(function(){ this.innerText = text });
},
attr: function(name, value){
return (typeof name == 'string' && value === undefined) ?
(this.length > 0 && this.dom[0].nodeName === 'INPUT' && this.dom[0].type === 'text' && name === 'value') ? (this.dom[0].value) :
(this.length > 0 ? this.dom[0].getAttribute(name) || undefined : null) :
this.each(function(){
if (typeof name == 'object') for (key in name) this.setAttribute(key, name[key])
else this.setAttribute(name, value);
});
},
offset: function(){
var obj = this.dom[0].getBoundingClientRect();
return {
left: obj.left + document.body.scrollLeft,
top: obj.top + document.body.scrollTop,
width: obj.width,
height: obj.height
};
},
css: function(property, value){
if (value === undefined && typeof property == 'string') return this.dom[0].style[camelize(property)];
css = "";
for (key in property) css += key + ':' + property[key] + ';';
if (typeof property == 'string') css = property + ":" + value;
return this.each(function() { this.style.cssText += ';' + css });
},
index: function(element){
return this.dom.indexOf($(element).get(0));
},
hasClass: function(name){
return classRE(name).test(this.dom[0].className);
},
addClass: function(name){
return this.each(function(){
!$(this).hasClass(name) && (this.className += (this.className ? ' ' : '') + name)
});
},
removeClass: function(name){
return this.each(function(){
this.className = this.className.replace(classRE(name), ' ').trim()
});
},
toggleClass: function(name, when){
return this.each(function(){
((when !== undefined && !when) || $(this).hasClass(name)) ?
$(this).removeClass(name) : $(this).addClass(name)
});
}
};
['width', 'height'].forEach(function(property){
$.fn[property] = function(){ return this.offset()[property] }
});
var adjacencyOperators = {append: 'beforeEnd', prepend: 'afterBegin', before: 'beforeBegin', after: 'afterEnd'};
for (key in adjacencyOperators)
$.fn[key] = (function(operator) {
return function(html){
return this.each(function(){
this['insertAdjacent' + (html instanceof Element ? 'Element' : 'HTML')](operator, html);
});
};
})(adjacencyOperators[key]);
Z.prototype = $.fn;
return $;
})();
'$' in window || (window.$ = Zepto);
/* assets.js */
(function($){
var cache = [], timeout;
$.fn.remove = function(){
return this.each(function(element){
if(element.tagName == 'IMG'){
cache.push(element);
element.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
if (timeout) clearTimeout(timeout);
timeout = setTimeout(function(){ cache = [] }, 60000);
}
element.parentNode.removeChild(element);
});
}
})(Zepto);
/* event.js */
(function($){
var $$ = $.qsa, handlers = {}, _zid = 1;
function zid(element) {
return element._zid || (element._zid = _zid++);
}
function findHandlers(element, event, fn, selector) {
event = parse(event);
if (event.ns) var matcher = matcherFor(event.ns);
return (handlers[zid(element)] || []).filter(function(handler) {
return handler
&& (!event.e || handler.e == event.e)
&& (!event.ns || matcher.test(handler.ns))
&& (!fn || handler.fn == fn)
&& (!selector || handler.sel == selector);
});
}
function parse(event) {
var parts = ('' + event).split('.');
return {e: parts[0], ns: parts.slice(1).sort().join(' ')};
}
function matcherFor(ns) {
return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)');
}
function add(element, events, fn, selector, delegate){
var id = zid(element), set = (handlers[id] || (handlers[id] = []));
events.split(/\s/).forEach(function(event){
var handler = $.extend(parse(event), {fn: fn, sel: selector, del: delegate, i: set.length});
set.push(handler);
element.addEventListener(handler.e, delegate || fn, false);
});
}
function remove(element, events, fn, selector){
var id = zid(element);
(events || '').split(/\s/).forEach(function(event){
findHandlers(element, event, fn, selector).forEach(function(handler){
delete handlers[id][handler.i];
element.removeEventListener(handler.e, handler.del || handler.fn, false);
});
});
}
$.event = {
add: function(element, events, fn){
add(element, events, fn);
},
remove: function(element, events, fn){
remove(element, events, fn);
}
};
$.fn.bind = function(event, callback){
return this.each(function(){
add(this, event, callback);
});
};
$.fn.unbind = function(event, callback){
return this.each(function(){
remove(this, event, callback);
});
};
var eventMethods = ['preventDefault', 'stopImmediatePropagation', 'stopPropagation'];
function createProxy(event) {
var proxy = $.extend({originalEvent: event}, event);
eventMethods.forEach(function(key) {
proxy[key] = function() {return event[key].apply(event, arguments)};
});
return proxy;
}
$.fn.delegate = function(selector, event, callback){
return this.each(function(i, element){
add(element, event, callback, selector, function(e){
var target = e.target, nodes = $$(element, selector);
while (target && nodes.indexOf(target) < 0) target = target.parentNode;
if (target && !(target === element) && !(target === document)) {
callback.call(target, $.extend(createProxy(e), {
currentTarget: target, liveFired: element
}));
}
});
});
};
$.fn.undelegate = function(selector, event, callback){
return this.each(function(){
remove(this, event, callback, selector);
});
}
$.fn.live = function(event, callback){
$(document.body).delegate(this.selector, event, callback);
return this;
};
$.fn.die = function(event, callback){
$(document.body).undelegate(this.selector, event, callback);
return this;
};
$.fn.trigger = function(event){
return this.each(function(){
var e = document.createEvent('Events');
this.dispatchEvent(e, e.initEvent(event, true, false));
});
};
})(Zepto);
/* touch.js */
(function($){
var touch = {}, touchTimeout;
function parentIfText(node){
return 'tagName' in node ? node : node.parentNode;
}
$(document).ready(function(){
$(document.body).bind('touchstart', function(e){
var now = Date.now(), delta = now - (touch.last || now);
touch.target = parentIfText(e.touches[0].target);
touchTimeout && clearTimeout(touchTimeout);
touch.x1 = e.touches[0].pageX;
if (delta > 0 && delta <= 250) touch.isDoubleTap = true;
touch.last = now;
}).bind('touchmove', function(e){
touch.x2 = e.touches[0].pageX
}).bind('touchend', function(e){
if (touch.isDoubleTap) {
$(touch.target).trigger('doubleTap');
touch = {};
} else if (touch.x2 > 0) {
Math.abs(touch.x1 - touch.x2) > 30 && $(touch.target).trigger('swipe') &&
$(touch.target).trigger('swipe' + (touch.x1 - touch.x2 > 0 ? 'Left' : 'Right'));
touch.x1 = touch.x2 = touch.last = 0;
} else if ('last' in touch) {
touchTimeout = setTimeout(function(){
touchTimeout = null;
$(touch.target).trigger('tap')
touch = {};
}, 250);
}
}).bind('touchcancel', function(){ touch = {} });
});
['swipe', 'swipeLeft', 'swipeRight', 'doubleTap', 'tap'].forEach(function(m){
$.fn[m] = function(callback){ return this.bind(m, callback) }
});
})(Zepto);