I want to make HTML5 datepicker like control. (http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_input_type_date). For this purpose I want to prevent any user selection while I'm still able to make selection through code. I prevent selection on mousedown and selectstart events, but after that I can't get the right cursor position. Can anyone give me directions or samples that do the work
Example code (with ext core framework):
this.root.on('mousedown', function (evt, el) {
me.select(el);
evt.preventDefault();
});
select : function(el) {
var cur = this.getCursorPos(el);
var section = this.modes[this.format].getSectionByPos(cur);
this.setTextSelection(el, section.start, section.end);
},
getCursorPos : function (input) {
if ("selectionStart" in input && document.activeElement == input) {
return {
start: input.selectionStart,
end: input.selectionEnd
};
}
else if (input.createTextRange) {
// code that supports other browser
}
return -1;
}
setTextSelection : function(el, start, end) {
if ("selectionStart" in el) {
setTimeout(function() {
el.selectionStart = start;
el.selectionEnd = end;
}, 1);
}
else if (el.createTextRange) {
// code that supports other browser
}
},
Related
I am struggling with handling the selection of multiple objects. The desired behaviour would be that each object that is clicked will be added to the current selection. Similar to holding shift-key, but also selections using the drag-options should be added to the existing selection. The current behaviour of fabricjs is creating a new selection even when pressing shift-key. In addition the selection should not be cleared when clicking a blank space on the canvas. Deselecting objects should only be possible when clicking a single object which is part of the selection (when dragging selected objects should stay selected). Or by clicking an additional button to clear the full selection (with additional user confirmation).
I tried different setups using "selection:created" and "selection:updated" but this either messed up the selection or resulted in an endless loop because modifying the selection inside the update also triggers the update again.
canvas.on("selection:updated", (event) => {
event.selected.forEach((fabImg) => {
if (!this.selectedImages.includes(fabImg)) {
this.selectedImages.push(fabImg);
}
});
var groupSelection = new fabric.ActiveSelection(this.selectedImages);
canvas.setActiveObject(groupSelection);
});
Preventing the clear when clicking on the blank canvas was solved by:
var selection = [];
canvas.on("before:selection:cleared", (selected) => {
selection = this.canvas.getActiveObjects();
});
canvas.on("selection:cleared", (event) => {
var groupSelection = new fabric.ActiveSelection(selection);
canvas.setActiveObject(groupSelection);
});
Just in case someone else is interested, I ended up changing 3 functions in the fabricjs code to achieve the desired behaviour:
canvas.class.js:
_shouldClearSelection: function (e, target) {
var activeObjects = this.getActiveObjects(),
activeObject = this._activeObject;
return (
(target &&
activeObject &&
activeObjects.length > 1 &&
activeObjects.indexOf(target) === -1 &&
activeObject !== target &&
!this._isSelectionKeyPressed(e)) ||
(target && !target.evented) ||
(target &&
!target.selectable &&
activeObject &&
activeObject !== target)
);
}
just removed the check if an object was clicked, to stop deselecting when clicking on blank space.
_isSelectionKeyPressed: function (e) {
var selectionKeyPressed = false;
if (this.selectionKey == "always") {
return true;
}
if (
Object.prototype.toString.call(this.selectionKey) === "[object Array]"
) {
selectionKeyPressed = !!this.selectionKey.find(function (key) {
return e[key] === true;
});
} else {
selectionKeyPressed = e[this.selectionKey];
}
return selectionKeyPressed;
}
just adding a "dummy" key called "always" to pretend always holding the shift-key. In canvas definition just add this key:
this.canvas = new fabric.Canvas("c", {
hoverCursor: "hand",
selection: true,
backgroundColor: "#F0F8FF",
selectionBorderColor: "blue",
defaultCursor: "hand",
selectionKey: "always",
});
And in canvas_grouping.mixin.js:
_groupSelectedObjects: function (e) {
var group = this._collectObjects(e),
aGroup;
var previousSelection = this._activeObject;
if (previousSelection) {
if (previousSelection.type === "activeSelection") {
var currentActiveObjects = previousSelection._objects.slice(0);
group.forEach((obj) => {
if (!previousSelection.contains(obj)) {
previousSelection.addWithUpdate(obj);
}
});
this._fireSelectionEvents(currentActiveObjects, e);
} else {
aGroup = new fabric.ActiveSelection(group.reverse(), {
canvas: this,
});
this.setActiveObject(aGroup, e);
var objects = this._activeObject._objects.slice(0);
this._activeObject.addWithUpdate(previousSelection);
this._fireSelectionEvents(objects, e);
}
} else {
// do not create group for 1 element only
if (group.length === 1 && !previousSelection) {
this.setActiveObject(group[0], e);
} else if (group.length > 1) {
aGroup = new fabric.ActiveSelection(group.reverse(), {
canvas: this,
});
this.setActiveObject(aGroup, e);
}
}
}
This will extend existing groups on drag-select instead of overwriting the existing selection.
I am using Openseadragon library with fabricjs overlay. I have a case where I want to drag the canvas but instead of mouse primary button, I want to drag it with middle mouse button press. Could anyone please help me get the desired behavior?
OpenSeadragon doesn't have a flag for that, but you can easily build it using the MouseTracker. Here's an example (coded from memory and not tested, but it should give you the idea).
var drag;
var mouseTracker = new OpenSeadragon.MouseTracker({
element: viewer.container,
nonPrimaryPressHandler: function(event) {
if (event.button === 1) { // Middle
drag = {
lastPos: event.position.clone()
};
}
},
moveHandler: function(event) {
if (drag) {
var deltaPixels = drag.lastPos.minus(event.position);
var deltaPoints = viewer.viewport.deltaPointsFromPixels(deltaPixels);
viewer.viewport.panBy(deltaPoints);
drag.lastPos = event.position.clone();
}
},
nonPrimaryReleaseHandler: function(event) {
if (event.button === 1) {
drag = null;
}
}
});
EDIT: I had a bug in the example code above; fixed.
Expanding on #iangilman 's answer...
To improve the user experience when the middle button is released outside the MouseTracker's element while dragging, causing the nonPrimaryReleaseHandler to never get called, the pointer can be captured...something like this:
var trackerElement = viewer.container;
var drag;
function capturePointer(event) {
if (OpenSeadragon.MouseTracker.havePointerCapture) {
if (OpenSeadragon.MouseTracker.havePointerEvents) {
// Can throw InvalidPointerId
try {
trackerElement.setPointerCapture(event.originalEvent.pointerId);
} catch () {
//
}
} else {
trackerElement.setCapture(true);
}
}
}
function releasePointer(event) {
if (OpenSeadragon.MouseTracker.havePointerCapture) {
if (OpenSeadragon.MouseTracker.havePointerEvents) {
// Can throw InvalidPointerId
try {
trackerElement.releasePointerCapture(event.originalEvent.pointerId);
} catch () {
//
}
} else {
trackerElement.releaseCapture();
}
}
}
var mouseTracker = new OpenSeadragon.MouseTracker({
element: trackerElement,
nonPrimaryPressHandler: function(event) {
if (event.button === 1) { // Middle
capturePointer(event);
drag = {
lastPos: event.position.clone()
};
}
},
moveHandler: function(event) {
if (drag) {
var deltaPixels = drag.lastPos.minus(event.position);
var deltaPoints = viewer.viewport.deltaPointsFromPixels(deltaPixels);
viewer.viewport.panBy(deltaPoints);
drag.lastPos = event.position.clone();
}
},
nonPrimaryReleaseHandler: function(event) {
if (event.button === 1) {
releasePointer(event);
drag = null;
}
}
});
I am using 'jquery.ui.autocomplete.js'. What issue I am facing is that during TAB Press default Naviagtion get stuck
when it reached in Autocomplete Text Box. The issue is reflecting only in Mozilla Firefox. What I want is that on TAB key press
it shold move to next elemnt. Can anyone please assist me to fix this issue?
I have tried Googled solutions but not able to fix. I am posting some link hope it will help you to understand isue.
1. http://bugs.jqueryui.com/ticket/6661
I think issue is somewhere in these lines:
case keyCode.ENTER:
case keyCode.NUMPAD_ENTER:
// when menu is open or has focus
if (self.menu.element.is(":visible")) {
event.preventDefault();
}
//passthrough - ENTER and TAB both select the current element
case keyCode.TAB:
if (!self.menu.active) {
return;
}
self.menu.select(event);
break;
case keyCode.ESCAPE:
self.element.val(self.term);
self.close(event);
break;
default:
// keypress is triggered before the input value is changed
clearTimeout(self.searching);
self.searching = setTimeout(function () {
// only search if the value has changed
if (self.term != self.element.val()) {
self.selectedItem = null;
self.search(null, event);
}
}, self.options.delay);
break;
}
})
My jquery code is here:
(function ($, undefined) {
$.widget("ui.autocomplete", {
options: {
appendTo: "body",
delay: 300,
minLength: 1,
position: {
my: "left top",
at: "left bottom",
collision: "none"
},
source: null
},
_create: function () {
var self = this,
doc = this.element[0].ownerDocument;
this.element
.addClass("ui-autocomplete-input")
.attr("autocomplete", "off")
// TODO verify these actually work as intended
.attr({
role: "textbox",
"aria-autocomplete": "list",
"aria-haspopup": "true"
})
.bind("keydown.autocomplete", function (event) {
if (self.options.disabled || self.element.attr("readonly")) {
return;
}
var keyCode = $.ui.keyCode;
switch (event.keyCode) {
case keyCode.PAGE_UP:
self._move("previousPage", event);
break;
case keyCode.PAGE_DOWN:
self._move("nextPage", event);
break;
case keyCode.UP:
self._move("previous", event);
// prevent moving cursor to beginning of text field in some browsers
event.preventDefault();
break;
case keyCode.DOWN:
self._move("next", event);
// prevent moving cursor to end of text field in some browsers
event.preventDefault();
break;
case keyCode.ENTER:
case keyCode.NUMPAD_ENTER:
// when menu is open or has focus
if (self.menu.element.is(":visible")) {
event.preventDefault();
}
//passthrough - ENTER and TAB both select the current element
case keyCode.TAB:
if (!self.menu.active) {
return;
}
self.menu.select(event);
break;
case keyCode.ESCAPE:
self.element.val(self.term);
self.close(event);
break;
default:
// keypress is triggered before the input value is changed
clearTimeout(self.searching);
self.searching = setTimeout(function () {
// only search if the value has changed
if (self.term != self.element.val()) {
self.selectedItem = null;
self.search(null, event);
}
}, self.options.delay);
break;
}
})
.bind("focus.autocomplete", function () {
if (self.options.disabled) {
return;
}
self.selectedItem = null;
self.previous = self.element.val();
})
.bind("blur.autocomplete", function (event) {
if (self.options.disabled) {
return;
}
clearTimeout(self.searching);
// clicks on the menu (or a button to trigger a search) will cause a blur event
self.closing = setTimeout(function () {
self.close(event);
self._change(event);
}, 150);
});
this._initSource();
this.response = function () {
return self._response.apply(self, arguments);
};
this.menu = $("<ul></ul>")
.addClass("ui-autocomplete")
.appendTo($(this.options.appendTo || "body", doc)[0])
// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
.mousedown(function (event) {
// clicking on the scrollbar causes focus to shift to the body
// but we can't detect a mouseup or a click immediately afterward
// so we have to track the next mousedown and close the menu if
// the user clicks somewhere outside of the autocomplete
var menuElement = self.menu.element[0];
if (event.target === menuElement) {
setTimeout(function () {
$(document).one('mousedown', function (event) {
if (event.target !== self.element[0] &&
event.target !== menuElement &&
!$.ui.contains(menuElement, event.target)) {
self.close();
}
});
}, 1);
}
// use another timeout to make sure the blur-event-handler on the input was already triggered
setTimeout(function () {
clearTimeout(self.closing);
}, 13);
})
.menu({
focus: function (event, ui) {
var item = ui.item.data("item.autocomplete");
if (false !== self._trigger("focus", null, { item: item })) {
// use value to match what will end up in the input, if it was a key event
if (/^key/.test(event.originalEvent.type)) {
self.element.val(item.value);
}
}
},
selected: function (event, ui) {
var item = ui.item.data("item.autocomplete"),
previous = self.previous;
// only trigger when focus was lost (click on menu)
if (self.element[0] !== doc.activeElement) {
self.element.focus();
self.previous = previous;
}
if (false !== self._trigger("select", event, { item: item })) {
self.element.val(item.value);
}
self.close(event);
self.selectedItem = item;
},
blur: function (event, ui) {
// don't set the value of the text field if it's already correct
// this prevents moving the cursor unnecessarily
if (self.menu.element.is(":visible") &&
(self.element.val() !== self.term)) {
self.element.val(self.term);
}
}
})
.zIndex(this.element.zIndex() + 1)
// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
.css({ top: 0, left: 0 })
.hide()
.data("menu");
if ($.fn.bgiframe) {
this.menu.element.bgiframe();
}
},
destroy: function () {
this.element
.removeClass("ui-autocomplete-input")
.removeAttr("autocomplete")
.removeAttr("role")
.removeAttr("aria-autocomplete")
.removeAttr("aria-haspopup");
this.menu.element.remove();
$.Widget.prototype.destroy.call(this);
},
_setOption: function (key, value) {
$.Widget.prototype._setOption.apply(this, arguments);
if (key === "source") {
this._initSource();
}
if (key === "appendTo") {
this.menu.element.appendTo($(value || "body", this.element[0].ownerDocument)[0])
}
},
_initSource: function () {
var array,
url;
if ($.isArray(this.options.source)) {
array = this.options.source;
this.source = function (request, response) {
response($.ui.autocomplete.filter(array, request.term));
};
} else if (typeof this.options.source === "string") {
url = this.options.source;
this.source = function (request, response) {
$.getJSON(url, request, response);
};
} else {
this.source = this.options.source;
}
},
search: function (value, event) {
value = value != null ? value : this.element.val();
if (value.length < this.options.minLength) {
return this.close(event);
}
clearTimeout(this.closing);
if (this._trigger("search") === false) {
return;
}
return this._search(value);
},
_search: function (value) {
this.term = this.element
.addClass("ui-autocomplete-loading")
// always save the actual value, not the one passed as an argument
.val();
this.source({ term: value }, this.response);
},
_response: function (content) {
if (content.length) {
content = this._normalize(content);
this._suggest(content);
this._trigger("open");
} else {
this.close();
}
this.element.removeClass("ui-autocomplete-loading");
},
close: function (event) {
clearTimeout(this.closing);
if (this.menu.element.is(":visible")) {
this._trigger("close", event);
this.menu.element.hide();
this.menu.deactivate();
}
},
_change: function (event) {
if (this.previous !== this.element.val()) {
this._trigger("change", event, { item: this.selectedItem });
}
},
_normalize: function (items) {
// assume all items have the right format when the first item is complete
if (items.length && items[0].label && items[0].value) {
return items;
}
return $.map(items, function (item) {
if (typeof item === "string") {
return {
label: item,
value: item
};
}
return $.extend({
label: item.label || item.value,
value: item.value || item.label
}, item);
});
},
_suggest: function (items) {
var ul = this.menu.element
.empty()
.zIndex(this.element.zIndex() + 1),
menuWidth,
textWidth;
this._renderMenu(ul, items);
// TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
this.menu.deactivate();
this.menu.refresh();
this.menu.element.show().position($.extend({
of: this.element
}, this.options.position));
menuWidth = ul.width("").outerWidth();
textWidth = this.element.outerWidth();
ul.outerWidth(Math.max(menuWidth, textWidth));
},
_renderMenu: function (ul, items) {
var self = this;
$.each(items, function (index, item) {
self._renderItem(ul, item);
});
},
_renderItem: function (ul, item) {
return $("<li></li>")
.data("item.autocomplete", item)
.append($("<a></a>").text(item.label))
.appendTo(ul);
},
_move: function (direction, event) {
if (!this.menu.element.is(":visible")) {
this.search(null, event);
return;
}
if (this.menu.first() && /^previous/.test(direction) ||
this.menu.last() && /^next/.test(direction)) {
this.element.val(this.term);
this.menu.deactivate();
return;
}
this.menu[direction](event);
},
widget: function () {
return this.menu.element;
}
});
$.extend($.ui.autocomplete, {
escapeRegex: function (value) {
return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
},
filter: function (array, term) {
var matcher = new RegExp($.ui.autocomplete.escapeRegex(term), "i");
return $.grep(array, function (value) {
return matcher.test(value.label || value.value || value);
});
}
});
} (jQuery));
Yes, that bug ticket you linked to shows the changeset you need to follow.
Notice how instead of saying $('selector').autocomplete(...) you're expected to do:
$('selector').bind('keydown', function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).data('autocomplete').menu.active ) {
event.preventDefault();
}
}).autocomplete(...)
Notice that you're intercepting TAB keydowns if the menu is "active" and preventing the event from doing the default behavior, which in a browser is focusing the next statically laid out element.
I am trying to use the history api to make some rudimentary filtering a bit more usable for people using my site.
I have it working quite well for the most part but I am stuck on some edge cases: hitting the start of the history chain (and avoiding infinte back) and loosing the forward button.
The full source with working examples can be found here: http://jsfiddle.net/YDFCS/
The JS code:
$(document).ready(function () {
"use strict";
var $noResults, $searchBox, $entries, searchTimeout, firstRun, loc, hist, win;
$noResults = $('#noresults');
$searchBox = $('#searchinput');
$entries = $('#workshopBlurbEntries');
searchTimeout = null;
firstRun = true;
loc = location;
hist = history;
win = window;
function reset() {
if (hist.state !== undefined) { // Avoid infinite loops
hist.pushState({"tag": undefined}, "theMetaCity - Workshop", "/workshop/");
}
$noResults.hide();
$entries.fadeOut(150, function () {
$('header ul li', this).removeClass('searchMatchTag');
$('header h1 a span', this).removeClass('searchMatchTitle'); // The span remains but it is destroyed when filtering using the text() function
$(".workshopentry", this).show();
});
$entries.fadeIn(150);
}
function filter(searchTerm) {
if (searchTerm === undefined) { // Only history api should push undefined to this, explicitly taken care of otherwise
reset();
} else {
var rePattern = searchTerm.replace(/[.?*+^$\[\]\\(){}|]/g, "\\$&"), searchPattern = new RegExp('(' + rePattern + ')', 'ig'); // The brackets add a capture group
$entries.fadeOut(150, function () {
$noResults.hide();
$('header', this).each(function () {
$(this).parent().hide();
// Clear results of previous search
$('li', this).removeClass('searchMatchTag');
// Check the title
$('h1', this).each(function () {
var textToCheck = $('a', this).text();
if (textToCheck.match(searchPattern)) {
textToCheck = textToCheck.replace(searchPattern, '<span class="searchMatchTitle">$1</span>'); //capture group ($1) used so that the replacement matches the case and you don't get weird capitolisations
$('a', this).html(textToCheck);
$(this).closest('.workshopentry').show();
} else {
$('a', this).html(textToCheck);
}
});
// Check the tags
$('li', this).each(function () {
if ($(this).text().match(searchPattern)) {
$(this).addClass('searchMatchTag');
$(this).closest('.workshopentry').show();
}
});
});
if ($('.workshopentry[style*="block"]').length === 0) {
$noResults.show();
}
$entries.fadeIn(150);
});
}
}
$('header ul li a', $entries).on('click', function () {
hist.pushState({"tag": $(this).text()}, "theMetaCity - Workshop - " + $(this).text(), "/workshop/tag/" + $(this).text());
$searchBox.val('');
filter($(this).text());
return false; // Using the history API so no page reloads/changes
});
$searchBox.on('keyup', function () {
clearTimeout(searchTimeout);
if ($(this).val().length) {
searchTimeout = setTimeout(function () {
var searchVal = $searchBox.val();
hist.pushState({"tag": searchVal}, "theMetaCity - Workshop - " + searchVal, "/workshop/tag/" + searchVal);
filter(searchVal);
}, 500);
}
if ($(this).val().length === 0) {
searchTimeout = setTimeout(function () {
reset();
}, 500);
}
});
$('#reset').on('click', function () {
$searchBox.val('');
reset();
});
win.addEventListener("popstate", function (event) {
console.info(hist.state);
if (event.state === null) { // Start of history chain on this page, direct entry to page handled by firstRun)
reset();
} else {
$searchBox.val(event.state.tag);
filter(event.state.tag);
}
});
$noResults.hide();
if (firstRun) { // 0 1 2 3 4 (if / present)
var locArray = loc.pathname.split('/'); // '/workshop/tag/searchString/
if (locArray[2] === 'tag' && locArray[3] !== undefined) { // Check for direct link to tag (i.e. if something in [3] search for it)
hist.pushState({"tag": locArray[3]}, "theMetaCity - Workshop - " + locArray[3], "/workshop/tag/" + locArray[3]);
filter(locArray[3]);
} else if (locArray[2] === '') { // Root page and really shouldn't do anything
hist.pushState({"tag": undefined}, "theMetaCity - Workshop", "/workshop/");
} // locArray[2] === somepagenum is an actual page and what should be allowed to happen by itself
firstRun = false;
// Save state on first page load
}
});
I feel that there is something I am not quite getting with the history api. Any help would be appreciated.
You need to use onpopstate event handler for the back and forward capabilities:
https://developer.mozilla.org/en-US/docs/Web/API/window.onpopstate
Check out this question I answered a while back, I believe they had the same issues you are facing:
history.pushstate fails browser back and forward button
I'm really struggling with the following bit of code. I'm still really new to using DOM with Javascript and this script is running flawlessly in FireFox, Chrome and Safari. In Internet Explorer it requires two clicks. If you visit the link in FireFox and then the same link in Internet Explorer you'll see that if you click a shape in FireFox it immediately shows the colour options if you do this in Internet Explorer it will not show the colour options until you've clicked on the shape twice or on a shape and then another shape. Can an IE, DOM, Javascript Ninja tell me what's wrong with the script that cause the need for two clicks in IE?
<?php
$swatches = $this->get_option_swatches();
?>
<script type="text/javascript">
document.observe('dom:loaded', function() {
try {
var swatches = <?php echo Mage::helper('core')->jsonEncode($swatches); ?>;
function find_swatch(key, value) {
for (var i in swatches) {
if (swatches[i].key == key && swatches[i].value == value)
return swatches[i];
}
return null;
}
function has_swatch_key(key) {
for (var i in swatches) {
if (swatches[i].key == key)
return true;
}
return false;
}
function create_swatches(label, select) {
// create swatches div, and append below the <select>
var sw = new Element('div', {'class': 'swatches-container'});
select.up().appendChild(sw);
// store these element to use later for recreate swatches
select.swatchLabel = label;
select.swatchElement = sw;
// hide select
select.setStyle({position: 'absolute', top: '-9999px'});
$A(select.options).each(function(opt, i) {
if (opt.getAttribute('value')) {
var elm;
var key = trim(opt.innerHTML);
// remove price
if (opt.getAttribute('price')) key = trim(key.replace(/\+([^+]+)$/, ''));
var item = find_swatch(label, key);
if (item)
elm = new Element('img', {
src: '<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA); ?>swatches/'+item.img,
alt: opt.innerHTML,
title: opt.innerHTML,
'class': 'swatch-img'});
else {
console.debug(label, key, swatches);
elm = new Element('a', {'class': 'swatch-span'});
elm.update(opt.innerHTML);
}
elm.observe('click', function(event) {
select.selectedIndex = i;
fireEvent(select, 'change');
var cur = sw.down('.current');
if (cur) cur.removeClassName('current');
elm.addClassName('current');
});
sw.appendChild(elm);
}
});
}
// Hide Second Option's Label
function hideStuff(id) {
if (document.getElementById(id)) {
document.getElementById(id).style.display = 'none';
}
}
hideStuff("last-option-label");
function showStuff(id) {
if (document.getElementById(id)) {
document.getElementById(id).style.display = '';
}
}
function recreate_swatches_recursive(select) {
// remove the old swatches
if (select.swatchElement) {
select.up().removeChild(select.swatchElement);
select.swatchElement = null;
}
// create again
if (!select.disabled)
showStuff("last-option-label");
create_swatches(select.swatchLabel, select);
// recursively recreate swatches for the next select
if (select.nextSetting)
recreate_swatches_recursive(select.nextSetting);
}
function fireEvent(element,event){
if (document.createEventObject){
// dispatch for IE
var evt = document.createEventObject();
return element.fireEvent('on'+event, evt);
}
else{
// dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true ); // event type,bubbling,cancelable
return !element.dispatchEvent(evt);
}
}
function trim(str) {
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}
$$('#product-options-wrapper dt').each(function(dt) {
// get custom option's label
var label = '';
$A(dt.down('label').childNodes).each(function(node) {
if (node.nodeType == 3) label += node.nodeValue;
});
label = trim(label);
var dd = dt.next();
var select = dd.down('select');
if (select && has_swatch_key(label)) {
create_swatches(label, select);
// if configurable products, recreate swatches of the next select when the current select change
if (select.hasClassName('super-attribute-select')) {
select.observe('change', function() {
recreate_swatches_recursive(select.nextSetting);
});
}
}
});
}
catch(e) {
alert("Color Swatches javascript error. Please report this error to support#galathemes.com. Error:" + e.message);
}
});
</script>
console.debug has been deprecated. In the "function create_swatches(label, select)" where it is written "console.debug(label, key, swatches);" change it to "console.log(label, key, swatches);" or you can just delete that line of code all together....... thaterrorbegone