Drupal.js Konflikt
Eingetragen von DanielS (20)
am 27.02.2015 - 19:26 Uhr in
am 27.02.2015 - 19:26 Uhr in
Guten Abend !
Ich versuche in meine Drupal Installation eine neue Java (JQuery) Bibliothek einzubauen, leider funktioniert diese nicht wenn diese zusammen mit Drupal.js geladen wird.
Die Konsole gibt keine Fehlermeldungen aus. Ich habe zwar Kentnise in einigen Programmiersprachen, hatte aber mit Java an sich nie zu tun und stehe daher im Dunkeln.
Könnte mir Einer helfen, den Konflikt zu beseitigen ? Woran könnte das liegen ?
Meine Bibliothek:
/*
===============================================================
jQuery plugin to expand/collapse a content element when a
expander element is clicked. When expanding/collapsing the plug-in
also toggles a class on the element.
See https://github.com/redhotsly/simple-expand
===============================================================
Copyright (C) 2012 Sylvain Hamel
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
===============================================================
*/
/*globals $:false, window:false*/
(function ($) {
"use strict";
// SimpleExpand
function SimpleExpand() {
var that = this;
that.defaults = {
// hideMode
// -----------
// Specifies method to hide the content element.
//
// Default: fadeToggle
//
// Values:
// - fadeToggle: Use jquery.fadeToggle()
// - basic: Use jquery.toggle()
// - css: relies on user provided css to show/hide. you can define
// classes for "collapsed" and "expanded" classes.
// - a function : custom toggle function. The function receives 3 arguments
// expander: the element that triggered the toggle
// targets: the items to toggle
// expanded: true if expanding; false if collapsing
//
// If un an unknown value is specified, the plug-in reverts to "css".
'hideMode': 'fadeToggle',
// searchMode
// -----------
// Specifies the defaut value for data-expander-target-search
// when none is specified on the expander element.
//
// Default: parent
//
// Values:
// - parent: go up the expander's parents hierarchy searching
// each parent's childens looking for a target
//
// - absolute : finds a target globally in the document (useful when
// matching an id)
//
// - relative : finds a target nested inside the expander
//
// If un an unknown value is specified, no targets will be found.
'defaultSearchMode': 'parent',
// defaultTarget
// -----------
// Specifies the defaut value for data-expander-target when
// none is specified on the expander element.
//
// Default: .content
'defaultTarget': '.content',
// throwOnMissingTarget
// -----------
// Specifies whether the plug-in throws an exception if it
// cannot find a target for the expander
//
// Default: true
'throwOnMissingTarget': true,
// keepStateInCookie
// -----------
// Specifies whether the plug-in keeps the expended/collapsed state
// in a cookie for the next time.
//
// Default: false
//
// Notes:
// - This only works for expanders with an Id attribute.
// - Make sure you load the jQuery cookie plug-in (https://github.com/carhartl/jquery-cookie/)
// before simple-expand is loaded.
//
'keepStateInCookie': false,
'cookieName': 'simple-expand'
};
that.settings = {};
$.extend(that.settings, that.defaults);
// Search in the children of the 'parent' element for an element that matches 'filterSelector'
// but don't search deeper if a 'stopAtSelector' element is met.
// See this question to better understand what this does.
// http://stackoverflow.com/questions/10902077/how-to-select-children-eleme...
that.findLevelOneDeep = function (parent, filterSelector, stopAtSelector) {
return parent.find(filterSelector).filter(function () {
return !$(this).parentsUntil(parent, stopAtSelector).length;
});
};
// Hides targets
that.setInitialState = function (expander, targets) {
var isExpanded = that.readState(expander);
if (isExpanded) {
expander.removeClass("collapsed").addClass("expanded");
that.show(targets);
} else {
expander.removeClass("expanded").addClass("collapsed");
that.hide(targets);
}
};
that.hide = function (targets) {
if (that.settings.hideMode === "fadeToggle") {
targets.hide();
} else if (that.settings.hideMode === "basic") {
targets.hide();
}
};
that.show = function (targets) {
if (that.settings.hideMode === "fadeToggle") {
targets.show();
} else if (that.settings.hideMode === "basic") {
targets.show();
}
};
// assert that $.cookie if 'keepStateInCookie' option is enabled
that.checkKeepStateInCookiePreconditions = function () {
if (that.settings.keepStateInCookie && $.cookie === undefined){
throw new Error("simple-expand: keepStateInCookie option requires $.cookie to be defined.");
}
};
// returns the cookie
that.readCookie = function () {
var jsonString = $.cookie(that.settings.cookieName);
if ( jsonString === null || jsonString === '' || jsonString === undefined ){
return {};
}
else{
return JSON.parse(jsonString);
}
};
// gets state for the expander from cookies
that.readState = function (expander) {
// if cookies and not enabled, use the current
// style of the element as the initial value
if (!that.settings.keepStateInCookie){
return expander.hasClass("expanded");
}
var id = expander.attr('Id');
if (id === undefined){
return;
}
var cookie = that.readCookie();
var cookieValue = cookie[id];
// if a cookie is stored for this id, used that value
if (typeof cookieValue !== "undefined"){
return cookie[id] === true;
}
else{
// otherwise use the current
// style of the element as the initial value
return expander.hasClass("expanded");
}
};
// save states of the item in the cookies
that.saveState = function (expander, isExpanded) {
if (!that.settings.keepStateInCookie){
return;
}
var id = expander.attr('Id');
if (id === undefined){
return;
}
var cookie = that.readCookie();
cookie[id] = isExpanded;
$.cookie(that.settings.cookieName, JSON.stringify(cookie), { raw: true, path:window.location.pathname });
};
// Toggles the targets and sets the 'collapsed' or 'expanded'
// class on the expander
that.toggle = function (expander, targets) {
var isExpanded = that.toggleCss(expander);
if (that.settings.hideMode === "fadeToggle") {
targets.fadeToggle(150);
} else if (that.settings.hideMode === "basic") {
targets.toggle();
} else if ($.isFunction(that.settings.hideMode)) {
that.settings.hideMode(expander, targets, isExpanded);
}
that.saveState(expander, isExpanded);
// prevent default to stop browser from scrolling to: href="#"
return false;
};
// Toggles using css
that.toggleCss = function (expander) {
if (expander.hasClass("expanded")) {
expander.toggleClass("collapsed expanded");
return false;
}
else {
expander.toggleClass("expanded collapsed");
return true;
}
};
// returns the targets for the given expander
that.findTargets = function (expander, searchMode, targetSelector) {
// find the targets using the specified searchMode
var targets = [];
if (searchMode === "absolute") {
targets = $(targetSelector);
}
else if (searchMode === "relative") {
targets = that.findLevelOneDeep(expander, targetSelector, targetSelector);
}
else if (searchMode === "parent") {
// Search the expander's parents recursively until targets are found.
var parent = expander.parent();
do {
targets = that.findLevelOneDeep(parent, targetSelector, targetSelector);
// No targets found, prepare for next iteration...
if (targets.length === 0) {
parent = parent.parent();
}
} while (targets.length === 0 && parent.length !== 0);
}
return targets;
};
that.activate = function (jquery, options) {
$.extend(that.settings, options);
that.checkKeepStateInCookiePreconditions();
// Plug-in entry point
//
// For each expander:
// search targets
// hide targets
// register to targets' click event to toggle them on click
jquery.each(function () {
var expander = $(this);
var targetSelector = expander.attr("data-expander-target") || that.settings.defaultTarget;
var searchMode = expander.attr("data-expander-target-search") || that.settings.defaultSearchMode;
var targets = that.findTargets(expander, searchMode, targetSelector);
// no elements match the target selector
// there is nothing we can do
if (targets.length === 0) {
if (that.settings.throwOnMissingTarget) {
throw "simple-expand: Targets not found";
}
return this;
}
that.setInitialState(expander, targets);
// hook the click on the expander
expander.click(function () {
return that.toggle(expander, targets);
});
});
};
}
// export SimpleExpand
window.SimpleExpand = SimpleExpand;
// expose SimpleExpand as a jQuery plugin
$.fn.simpleexpand = function (options) {
var instance = new SimpleExpand();
instance.activate(this, options);
return this;
};
}(jQuery));
Drupal.js:
var Drupal = Drupal || { 'settings': {}, 'behaviors': {}, 'locale': {} };
// Allow other JavaScript libraries to use $.
jQuery.noConflict();
(function ($) {
/**
* Override jQuery.fn.init to guard against XSS attacks.
*
* See http://bugs.jquery.com/ticket/9521
*/
var jquery_init = $.fn.init;
$.fn.init = function (selector, context, rootjQuery) {
// If the string contains a "#" before a "<", treat it as invalid HTML.
if (selector && typeof selector === 'string') {
var hash_position = selector.indexOf('#');
if (hash_position >= 0) {
var bracket_position = selector.indexOf('<');
if (bracket_position > hash_position) {
throw 'Syntax error, unrecognized expression: ' + selector;
}
}
}
return jquery_init.call(this, selector, context, rootjQuery);
};
$.fn.init.prototype = jquery_init.prototype;
/**
* Attach all registered behaviors to a page element.
*
* Behaviors are event-triggered actions that attach to page elements, enhancing
* default non-JavaScript UIs. Behaviors are registered in the Drupal.behaviors
* object using the method 'attach' and optionally also 'detach' as follows:
* @code
* Drupal.behaviors.behaviorName = {
* attach: function (context, settings) {
* ...
* },
* detach: function (context, settings, trigger) {
* ...
* }
* };
* @endcode
*
* Drupal.attachBehaviors is added below to the jQuery ready event and so
* runs on initial page load. Developers implementing AHAH/Ajax in their
* solutions should also call this function after new page content has been
* loaded, feeding in an element to be processed, in order to attach all
* behaviors to the new content.
*
* Behaviors should use
* @code
* $(selector).once('behavior-name', function () {
* ...
* });
* @endcode
* to ensure the behavior is attached only once to a given element. (Doing so
* enables the reprocessing of given elements, which may be needed on occasion
* despite the ability to limit behavior attachment to a particular element.)
*
* @param context
* An element to attach behaviors to. If none is given, the document element
* is used.
* @param settings
* An object containing settings for the current context. If none given, the
* global Drupal.settings object is used.
*/
Drupal.attachBehaviors = function (context, settings) {
context = context || document;
settings = settings || Drupal.settings;
// Execute all of them.
$.each(Drupal.behaviors, function () {
if ($.isFunction(this.attach)) {
this.attach(context, settings);
}
});
};
/**
* Detach registered behaviors from a page element.
*
* Developers implementing AHAH/Ajax in their solutions should call this
* function before page content is about to be removed, feeding in an element
* to be processed, in order to allow special behaviors to detach from the
* content.
*
* Such implementations should look for the class name that was added in their
* corresponding Drupal.behaviors.behaviorName.attach implementation, i.e.
* behaviorName-processed, to ensure the behavior is detached only from
* previously processed elements.
*
* @param context
* An element to detach behaviors from. If none is given, the document element
* is used.
* @param settings
* An object containing settings for the current context. If none given, the
* global Drupal.settings object is used.
* @param trigger
* A string containing what's causing the behaviors to be detached. The
* possible triggers are:
* - unload: (default) The context element is being removed from the DOM.
* - move: The element is about to be moved within the DOM (for example,
* during a tabledrag row swap). After the move is completed,
* Drupal.attachBehaviors() is called, so that the behavior can undo
* whatever it did in response to the move. Many behaviors won't need to
* do anything simply in response to the element being moved, but because
* IFRAME elements reload their "src" when being moved within the DOM,
* behaviors bound to IFRAME elements (like WYSIWYG editors) may need to
* take some action.
* - serialize: When an Ajax form is submitted, this is called with the
* form as the context. This provides every behavior within the form an
* opportunity to ensure that the field elements have correct content
* in them before the form is serialized. The canonical use-case is so
* that WYSIWYG editors can update the hidden textarea to which they are
* bound.
*
* @see Drupal.attachBehaviors
*/
Drupal.detachBehaviors = function (context, settings, trigger) {
context = context || document;
settings = settings || Drupal.settings;
trigger = trigger || 'unload';
// Execute all of them.
$.each(Drupal.behaviors, function () {
if ($.isFunction(this.detach)) {
this.detach(context, settings, trigger);
}
});
};
/**
* Encode special characters in a plain-text string for display as HTML.
*
* @ingroup sanitization
*/
Drupal.checkPlain = function (str) {
var character, regex,
replace = { '&': '&', '"': '"', '<': '<', '>': '>' };
str = String(str);
for (character in replace) {
if (replace.hasOwnProperty(character)) {
regex = new RegExp(character, 'g');
str = str.replace(regex, replace[character]);
}
}
return str;
};
/**
* Replace placeholders with sanitized values in a string.
*
* @param str
* A string with placeholders.
* @param args
* An object of replacements pairs to make. Incidences of any key in this
* array are replaced with the corresponding value. Based on the first
* character of the key, the value is escaped and/or themed:
* - !variable: inserted as is
* - @variable: escape plain text to HTML (Drupal.checkPlain)
* - %variable: escape text and theme as a placeholder for user-submitted
* content (checkPlain + Drupal.theme('placeholder'))
*
* @see Drupal.t()
* @ingroup sanitization
*/
Drupal.formatString = function(str, args) {
// Transform arguments before inserting them.
for (var key in args) {
switch (key.charAt(0)) {
// Escaped only.
case '@':
args[key] = Drupal.checkPlain(args[key]);
break;
// Pass-through.
case '!':
break;
// Escaped and placeholder.
case '%':
default:
args[key] = Drupal.theme('placeholder', args[key]);
break;
}
str = str.replace(key, args[key]);
}
return str;
};
/**
* Translate strings to the page language or a given language.
*
* See the documentation of the server-side t() function for further details.
*
* @param str
* A string containing the English string to translate.
* @param args
* An object of replacements pairs to make after translation. Incidences
* of any key in this array are replaced with the corresponding value.
* See Drupal.formatString().
*
* @param options
* - 'context' (defaults to the empty context): The context the source string
* belongs to.
*
* @return
* The translated string.
*/
Drupal.t = function (str, args, options) {
options = options || {};
options.context = options.context || '';
// Fetch the localized version of the string.
if (Drupal.locale.strings && Drupal.locale.strings[options.context] && Drupal.locale.strings[options.context][str]) {
str = Drupal.locale.strings[options.context][str];
}
if (args) {
str = Drupal.formatString(str, args);
}
return str;
};
/**
* Format a string containing a count of items.
*
* This function ensures that the string is pluralized correctly. Since Drupal.t() is
* called by this function, make sure not to pass already-localized strings to it.
*
* See the documentation of the server-side format_plural() function for further details.
*
* @param count
* The item count to display.
* @param singular
* The string for the singular case. Please make sure it is clear this is
* singular, to ease translation (e.g. use "1 new comment" instead of "1 new").
* Do not use @count in the singular string.
* @param plural
* The string for the plural case. Please make sure it is clear this is plural,
* to ease translation. Use @count in place of the item count, as in "@count
* new comments".
* @param args
* An object of replacements pairs to make after translation. Incidences
* of any key in this array are replaced with the corresponding value.
* See Drupal.formatString().
* Note that you do not need to include @count in this array.
* This replacement is done automatically for the plural case.
* @param options
* The options to pass to the Drupal.t() function.
* @return
* A translated string.
*/
Drupal.formatPlural = function (count, singular, plural, args, options) {
var args = args || {};
args['@count'] = count;
// Determine the index of the plural form.
var index = Drupal.locale.pluralFormula ? Drupal.locale.pluralFormula(args['@count']) : ((args['@count'] == 1) ? 0 : 1);
if (index == 0) {
return Drupal.t(singular, args, options);
}
else if (index == 1) {
return Drupal.t(plural, args, options);
}
else {
args['@count[' + index + ']'] = args['@count'];
delete args['@count'];
return Drupal.t(plural.replace('@count', '@count[' + index + ']'), args, options);
}
};
/**
* Generate the themed representation of a Drupal object.
*
* All requests for themed output must go through this function. It examines
* the request and routes it to the appropriate theme function. If the current
* theme does not provide an override function, the generic theme function is
* called.
*
* For example, to retrieve the HTML for text that should be emphasized and
* displayed as a placeholder inside a sentence, call
* Drupal.theme('placeholder', text).
*
* @param func
* The name of the theme function to call.
* @param ...
* Additional arguments to pass along to the theme function.
* @return
* Any data the theme function returns. This could be a plain HTML string,
* but also a complex object.
*/
Drupal.theme = function (func) {
var args = Array.prototype.slice.apply(arguments, [1]);
return (Drupal.theme[func] || Drupal.theme.prototype[func]).apply(this, args);
};
/**
* Freeze the current body height (as minimum height). Used to prevent
* unnecessary upwards scrolling when doing DOM manipulations.
*/
Drupal.freezeHeight = function () {
Drupal.unfreezeHeight();
$('<div id="freeze-height"></div>').css({
position: 'absolute',
top: '0px',
left: '0px',
width: '1px',
height: $('body').css('height')
}).appendTo('body');
};
/**
* Unfreeze the body height.
*/
Drupal.unfreezeHeight = function () {
$('#freeze-height').remove();
};
/**
* Encodes a Drupal path for use in a URL.
*
* For aesthetic reasons slashes are not escaped.
*/
Drupal.encodePath = function (item, uri) {
uri = uri || location.href;
return encodeURIComponent(item).replace(/%2F/g, '/');
};
/**
* Get the text selection in a textarea.
*/
Drupal.getSelection = function (element) {
if (typeof element.selectionStart != 'number' && document.selection) {
// The current selection.
var range1 = document.selection.createRange();
var range2 = range1.duplicate();
// Select all text.
range2.moveToElementText(element);
// Now move 'dummy' end point to end point of original range.
range2.setEndPoint('EndToEnd', range1);
// Now we can calculate start and end points.
var start = range2.text.length - range1.text.length;
var end = start + range1.text.length;
return { 'start': start, 'end': end };
}
return { 'start': element.selectionStart, 'end': element.selectionEnd };
};
/**
* Build an error message from an Ajax response.
*/
Drupal.ajaxError = function (xmlhttp, uri) {
var statusCode, statusText, pathText, responseText, readyStateText, message;
if (xmlhttp.status) {
statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") + "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status});
}
else {
statusCode = "\n" + Drupal.t("An AJAX HTTP request terminated abnormally.");
}
statusCode += "\n" + Drupal.t("Debugging information follows.");
pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri} );
statusText = '';
// In some cases, when statusCode == 0, xmlhttp.statusText may not be defined.
// Unfortunately, testing for it with typeof, etc, doesn't seem to catch that
// and the test causes an exception. So we need to catch the exception here.
try {
statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)});
}
catch (e) {}
responseText = '';
// Again, we don't have a way to know for sure whether accessing
// xmlhttp.responseText is going to throw an exception. So we'll catch it.
try {
responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) } );
} catch (e) {}
// Make the responseText more readable by stripping HTML tags and newlines.
responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi,"");
responseText = responseText.replace(/[\n]+\s+/g,"\n");
// We don't need readyState except for status == 0.
readyStateText = xmlhttp.status == 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
message = statusCode + pathText + statusText + responseText + readyStateText;
return message;
};
// Class indicating that JS is enabled; used for styling purpose.
$('html').addClass('js');
// 'js enabled' cookie.
document.cookie = 'has_js=1; path=/';
/**
* Additions to jQuery.support.
*/
$(function () {
/**
* Boolean indicating whether or not position:fixed is supported.
*/
if (jQuery.support.positionFixed === undefined) {
var el = $('<div style="position:fixed; top:10px" />').appendTo(document.body);
jQuery.support.positionFixed = el[0].offsetTop === 10;
el.remove();
}
});
//Attach all behaviors.
$(function () {
Drupal.attachBehaviors(document, Drupal.settings);
});
/**
* The default themes.
*/
Drupal.theme.prototype = {
/**
* Formats text for emphasized display in a placeholder inside a sentence.
*
* @param str
* The text to format (plain-text).
* @return
* The formatted text (html).
*/
placeholder: function (str) {
return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>';
}
};
})(jQuery);
Danke für eure Hilfe !
MfG
D
- Anmelden oder Registrieren um Kommentare zu schreiben
Auf welche Art und Weise hast
am 27.02.2015 - 19:58 Uhr
Auf welche Art und Weise hast du denn versucht das Script zu laden?
Benutzt du ein eigenes Theme?
WEBTRANSFORMER
Hallo ! Ja, ich verwende ein
am 28.02.2015 - 18:19 Uhr
Hallo !
Ja, ich verwende ein stark von mir modifiziertes Theme.
Das Script wird auf vielen Seiten benötigt, deshalb binde ich dieses in der html.tpl.php ein:
<script type="text/javascript" src="http://xxxxxxx.com/documents/simple-expand.min.js"></script>
<script type="text/javascript">
$(function () {
$('.expander').simpleexpand();
});
</script>
MfG
Das wird so in Durpal nicht
am 28.02.2015 - 20:27 Uhr
Das wird so in Durpal nicht funktionieren, da das "Selektorzeichen" - also das "$" Zeichen erstmal nicht von Drupal erkannt wird. Neben dem Namespace (jQuery) werden in Drupal Javascript auch in sogenannte Behaviours gepackt - diese sorgen unter Anderem dafür, dass die Funktionalität auch noch zur Verfügung steht, wenn auf der Seite bspw. per Ajax etwas nachgeladen wird (Views ajax pager o.ä.)
Du müsstest dein Javascript wie folgt einbauen:
(function($) {
Drupal.behaviors.myCustomModule = {
attach : function(context) {
$('.expander').simpleexpand();
};
};
})(jQuery);
Außerdem ist es sinnvoll, wenn du das Javascript in einer eigenen Datei speicherst und dann per .info Datei deines Themes mit einbindest.
Gleiches gilt natürlich auch für jQuery Plugins, die du einbindest.
name = My custom theme
description = Theme description
core = 7.x
engine = phptemplate
stylesheets[all][] = style.css
scripts[] = js/lib/simple-expand/simple-expand.min.js
scripts[] = js/scripts.js
Weitere Infos dazu: https://www.drupal.org/node/171205#scripts
SteffenR
http://www.twitter.com/_steffenr
Drupal-Initiative e.V.
Guten Abend ! Vielen Dank für
am 28.02.2015 - 20:31 Uhr
Guten Abend !
Vielen Dank für die ausführliche Antwort, so werde ich es machen =)
MfG
D