jQuery UI Widget Factory, modify start, drag, stop of Draggable - jquery-ui

I am working to extend the Draggable widget by adding guides to the draggable element.
Example Fiddle: https://jsfiddle.net/Twisty/0mgrqy48/181/
JavaScript
$(function() {
$.widget("custom.guidedDrag", $.ui.draggable, {
options: {
autoShowGuides: true,
guideWidth: "1px",
guideStyle: "dashed",
guideColor: "#55f",
guideSides: ["top", "left"]
},
_create: function() {
this._makeGuides();
return this._super();
},
_makeGuides: function() {
var target = this.options.appendTo;
if (target == "parent") {
target = this.element.parent();
}
var self = this;
$.each(self.options.guideSides, function(i, side) {
var styles = {};
styles['border-' + side + '-width'] = self.options.guideWidth;
styles['border-' + side + '-style'] = self.options.guideStyle;
styles['border-' + side + '-color'] = self.options.guideColor;
styles.position = "absolute";
styles.top = 0;
styles.left = 0;
if (side == "top" || side == "bottom") {
styles.width = "100%";
styles.height = "";
$("<div>", {
class: "ui-draggable-guide-horizontal-" + side,
"data-elem-rel": self.uuid
}).css(styles).appendTo(target);
} else {
styles.width = "";
styles.height = "100%";
$("<div>", {
class: "ui-draggable-guide-vertical-" + side,
"data-elem-rel": self.uuid
}).css(styles).appendTo(target);
}
console.log("Guide Created for " + self.uuid + " on " + side + " side.");
});
},
_showGuides: function() {
if (this.options.autoShowGuides) {
this._moveGuides();
$("div[class*='ui-draggable-guide-'][data-elem-rel='" + this.uuid + "']").show();
}
},
_hideGuides: function() {
if (this.options.autoShowGuides) {
$("div[class*='ui-draggable-guide-'][data-elem-rel='" + this.uuid + "']").hide();
}
},
_moveGuides: function() {
var guides = $("div[class*='ui-draggable-guide-'][data-elem-rel='" + this.uuid + "']");
var t = this.element.position().top,
l = this.element.position().left,
b = t + this.element.outerHeight(),
r = l + this.element.outerWidth();
$(".ui-draggable-guide-horizontal-top", guides).css("top", t + "px");
$(".ui-draggable-guide-horizontal-left", guides).css("left", l + "px");
$(".ui-draggable-guide-horizontal-bottom", guides).css("top", b + "px");
$(".ui-draggable-guide-horizontal-right", guides).css("left", r + "px");
},
start: function(event, ui) {
console.log("Drag Start");
this._showGuides();
return this._super();
},
drag: function(event, ui) {
self._moveGuides();
return this._super();
},
stop: function(event, ui) {
console.log("Stop Drag");
self._hideGuides();
return this._super();
},
_destroy: function() {
$("div[class*='ui-draggable-guide-'][data-elem-rel='" + this.uuid + "']").remove();
return this._super()
}
});
$(".draggable").guidedDrag({
guideSides: ["top", "right"],
scroll: false
});
});
Currently, the guides are created and appear where expected. When I drag the element, the start event should be triggered and move the guides to the element (and unhide them later).
In console, I see the following, after running and dragging the element:
Guide Created for 0 on top side.
Guide Created for 0 on right side.
So I can tell that _create is running but start and stop do not seem to fire.
I have also tried to use .on() to bind to dragstart with no change. Example:
_create: function() {
this._makeGuides();
var self = this;
this.element.on("dragstart", function(event, ui){
console.log("Drag Start");
self._moveGuides();
});
return this._super();
}
Based on documentation, I should just be able to call the same widget and use _super().
To make the parent's methods available, the widget factory provides two methods - _super() and _superApply().
This never seems to work.

To resolve this, I have to make use of the _mouseStart, _mouseDrag, and _mouseStop event callbacks.
Example: https://jsfiddle.net/Twisty/0mgrqy48/245/
JavaScript
$(function() {
$.widget("app.guidedDrag", $.ui.draggable, {
options: {
autoShowGuides: true,
guideWidth: "1px",
guideStyle: "dashed",
guideColor: "#55f",
guideSides: ["top", "left"]
},
_create: function() {
this._makeGuides();
this._super();
},
_guideElems: {},
_makeGuides: function() {
var target = this.options.appendTo;
switch (target) {
case "parent":
target = this.element.parent();
break;
case "window":
target = $(window);
break;
case "document":
target = $(document);
break;
default:
target = $(target);
}
var self = this;
$.each(self.options.guideSides, function(i, side) {
var styles = {};
styles['border-' + side + '-width'] = self.options.guideWidth;
styles['border-' + side + '-style'] = self.options.guideStyle;
styles['border-' + side + '-color'] = self.options.guideColor;
styles.position = "absolute";
styles.top = 0;
styles.left = 0;
if (self.options.autoShowGuides) {
styles.display = "none";
}
if (side == "top" || side == "bottom") {
styles.width = "100%";
self._guideElems[side] = $("<div>", {
class: "ui-draggable-guide-horizontal-" + side,
}).data("ui-draggable-rel", self.uuid).css(styles).appendTo(target);
} else {
styles.height = "100%";
self._guideElems[side] = $("<div>", {
class: "ui-draggable-guide-vertical-" + side,
}).data("ui-draggable-rel", self.uuid).css(styles).appendTo(target);
}
console.log("Guide Created for " + self.uuid + " on " + side + " side.");
});
},
_showGuides: function() {
if (this.options.autoShowGuides) {
this._moveGuides();
$.each(this._guideElems, function(i, g) {
g.show();
});
}
},
_hideGuides: function() {
if (this.options.autoShowGuides) {
$.each(this._guideElems, function(i, g) {
g.hide();
});
}
},
_moveGuides: function() {
var t = this.element.position().top,
l = this.element.position().left,
b = t + this.element.outerHeight(),
r = l + this.element.outerWidth();
$.each(this._guideElems, function(i, g) {
if (g.hasClass("ui-draggable-guide-horizontal-top")) {
g.css("top", t + "px");
}
if (g.hasClass("ui-draggable-guide-horizontal-bottom")) {
g.css("top", b + "px");
}
if (g.hasClass("ui-draggable-guide-vertical-left")) {
g.css("left", l + "px");
}
if (g.hasClass("ui-draggable-guide-vertical-right")) {
g.css("left", r + "px");
}
});
},
_mouseStart: function(event) {
this._moveGuides();
this._showGuides();
this._super(event);
},
_mouseDrag: function(event) {
this._moveGuides();
return this._super(event);
},
_mouseStop: function(event) {
this._hideGuides();
return this._super(event);
},
_destroy: function(event) {
$(this._guideElems).remove();
return this._super(event);
}
});
$(".draggable").guidedDrag({
guideSides: ["top", "right"],
scroll: false
});
});

Related

How to create autocomplete form with MaterializeCss?

I am looking for autocomplete form for MaterializeCss, any plugins for this? i has try to use select2 but that's css not looks good
Materialize is an awesome library, I was able to get it to work.
$('document').ready(function() {
var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea';
/**************************
* Auto complete plugin *
*************************/
$(input_selector).each(function() {
var $input = $(this);
if ($input.hasClass('autocomplete')) {
var $array = $input.data('array'),
$inputDiv = $input.closest('.input-field'); // Div to append on
// Check if "data-array" isn't empty
if ($array !== '') {
// Create html element
var $html = '<ul class="autocomplete-content hide">';
for (var i = 0; i < $array.length; i++) {
// If path and class aren't empty add image to auto complete else create normal element
if ($array[i]['path'] !== '' && $array[i]['path'] !== undefined && $array[i]['path'] !== null && $array[i]['class'] !== undefined && $array[i]['class'] !== '') {
$html += '<li class="autocomplete-option"><img src="' + $array[i]['path'] + '" class="' + $array[i]['class'] + '"><span>' + $array[i]['value'] + '</span></li>';
} else {
$html += '<li class="autocomplete-option"><span>' + $array[i]['value'] + '</span></li>';
}
}
$html += '</ul>';
$inputDiv.append($html); // Set ul in body
// End create html element
function highlight(string) {
$('.autocomplete-content li').each(function() {
var matchStart = $(this).text().toLowerCase().indexOf("" + string.toLowerCase() + ""),
matchEnd = matchStart + string.length - 1,
beforeMatch = $(this).text().slice(0, matchStart),
matchText = $(this).text().slice(matchStart, matchEnd + 1),
afterMatch = $(this).text().slice(matchEnd + 1);
$(this).html("<span>" + beforeMatch + "<span class='highlight'>" + matchText + "</span>" + afterMatch + "</span>");
});
}
// Perform search
$(document).on('keyup', $input, function() {
var $val = $input.val().trim(),
$select = $('.autocomplete-content');
// Check if the input isn't empty
$select.css('width',$input.width());
if ($val != '') {
$select.children('li').addClass('hide');
$select.children('li').filter(function() {
$select.removeClass('hide'); // Show results
// If text needs to highlighted
if ($input.hasClass('highlight-matching')) {
highlight($val);
}
var check = true;
for (var i in $val) {
if ($val[i].toLowerCase() !== $(this).text().toLowerCase()[i])
check = false;
};
return check ? $(this).text().toLowerCase().indexOf($val.toLowerCase()) !== -1 : false;
}).removeClass('hide');
} else {
$select.children('li').addClass('hide');
}
});
// Set input value
$('.autocomplete-option').click(function() {
$input.val($(this).text().trim());
$('.autocomplete-option').addClass('hide');
});
} else {
return false;
}
}
});
});
.autocomplete-content {
position: absolute;
background: #383838;
margin-top: -.9rem;
}
.autocomplete-content li {
clear: both;
color: rgba(0, 0, 0, 0.87);
cursor: pointer;
line-height: 0;
width: 100%;
text-align: left;
text-transform: none;
padding: 10px;
}
.autocomplete-content li > span {
color: #ffa726;
font-size: .9rem;
padding: 1.2rem;
display: block;
}
.autocomplete-content li > span .highlight {
color: #000000;
}
.autocomplete-content li img {
height: 52px;
width: 52px;
padding: 5px;
margin: 0 15px;
}
.autocomplete-content li:hover {
background: #eee;
cursor: pointer;
}
.autocomplete-content > li:hover {
background: #292929;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="row">
<div class="input-field col s12">
<label class="active">State</label>
<input type="text" id="autocompleteState" class="autocomplete inputFields">
</div>
</div>
<script>
var stateData = [{
value: "Alabama"
}, {
value: "Alaska"
}, {
value: "Arizona"
}, {
value: "Arkansas"
}, {
value: "California"
}, {
value: "Colorado"
}, {
value: "Connecticut"
}, {
value: "District of Columbia"
}, {
value: "Delaware"
}, {
value: "Florida"
}, {
value: "Georgia"
}, {
value: "Hawaii"
}, {
value: "Idaho"
}, {
value: "Illinois"
}, {
value: "Indiana"
}, {
value: "Iowa"
}, {
value: "Kansas"
}, {
value: "Kentucky"
}, {
value: "Louisiana"
}, {
value: "Maine"
}, ];
$('#autocompleteState').data('array', stateData);
</script>
Hope this helps people who are new to this just like me.:)
UPDATED 1/09/2016:
Autocomplete is already available officially:
http://materializecss.com/forms.html#autocomplete
I was looking for exactly the same and I think We have been lucky. They added the autocomplete recently, (not yet in the documentation). But you can see the info here https://github.com/SuperDJ/materialize/commit/3648f74542e41c3b3be4596870b7485f6ebdf176#diff-e4535828acef79852aa104417c16fe3dR157
and the code:
https://github.com/SuperDJ/materialize/blob/master/bin/materialize.css
https://github.com/SuperDJ/materialize/blob/master/bin/materialize.js
(function (root, factory) {
if(typeof module === 'object' && module.exports) {
module.exports = factory(require('jquery'));
} else if(typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else {
factory(root.jQuery);
}
}(this, function ($) {
var template = function (text) {
var matcher = new RegExp('<%=([\\s\\S]+?)%>|<%([\\s\\S]+?)%>|$', 'g');
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, interpolate, evaluate, offset) {
source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
index = offset + match.length;
if (match == "<% item.value %>")
interpolate = " item.value ";
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} else if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
return match;
});
source += "';\n";
source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + 'return __p;\n';
var render;
try {
render = new Function('obj', source);
} catch (e) {
e.source = source;
throw e;
}
var _template = function(data) {
return render.call(this, data);
};
_template.source = 'function(obj){\n' + source + '}';
return _template;
};
var Autocomplete = function (el, options) {
this.options = $.extend(true, {}, Autocomplete.defaults, options);
this.$el = $(el);
this.$wrapper = this.$el.parent();
this.compiled = {};
this.$dropdown = null;
this.$appender = null;
this.$hidden = null;
this.resultCache = {};
this.value = '';
this.initialize();
};
Autocomplete.defaults = {
cacheable: true,
limit: 10,
multiple: {
enable: false,
maxSize: 4,
onExist: function (item) {
Materialize.toast('Tag: ' + item.text + '(' + item.id + ') is already added!', 2000);
},
onExceed: function (maxSize, item) {
Materialize.toast('Can\'t add over ' + maxSize + ' tags!', 2000);
},
onAppend: function (item) {
var self = this;
self.$el.removeClass('active');
self.$el.click();
},
onRemove: function (item) {
var self = this;
self.$el.removeClass('active');
self.$el.click();
}
},
hidden: {
enable: true,
el: '',
inputName: '',
required: false
},
appender: {
el: '',
tagName: 'ul',
className: 'ac-appender',
tagTemplate: '<div class="chip" data-id="<%= item.id %>" data-value="<% item.value %> data-text="<% item.text %>" "><%= item.text %>(<%= item.id %>)<i class="material-icons close">close</i></div>'
},
dropdown: {
el: '',
tagName: 'ul',
className: 'ac-dropdown',
itemTemplate: '<li class="ac-item" data-id="<%= item.id %>" data-value="<% item.value %>" data-text="<%= item.text %>" ><%= item.text %></li>',
noItem: ''
},
handlers: {
'setValue': '.ac-dropdown .ac-item',
'.ac-appender .ac-tag .close': 'remove'
},
getData: function (value, callback) {
callback(value, []);
},
onSelect: function (item) { },
onRemove: function (item) { alert('delete'); },
ignoreCase: true,
throttling: true,
showListOnFocus: false,
minLength:0
};
Autocomplete.prototype = {
constructor: Autocomplete,
initialize: function () {
var self = this;
var timer;
var fetching = false;
function getItemsHtml (list) {
var itemsHtml = '';
if (!list.length) {
return self.options.dropdown.noItem;
}
list.forEach(function (item, idx) {
if (idx >= self.options.limit) {
return false;
}
itemsHtml += self.compiled.item({ 'item': item});
});
return itemsHtml;
}
function handleList (value, list) {
var itemsHtml = getItemsHtml(list);
var currentValue = self.$el.val();
if (self.options.ignoreCase) {
currentValue = currentValue.toUpperCase();
}
if (self.options.cacheable && !self.resultCache.hasOwnProperty(value)) {
self.resultCache[value] = list;
}
if (value !== currentValue) {
return false;
}
if(itemsHtml) {
self.$dropdown.html(itemsHtml);
self.$dropdown.show();
} else {
self.$dropdown.hide();
}
}
self.value = self.options.multiple.enable ? [] : '';
self.compiled.tag = template(self.options.appender.tagTemplate);
self.compiled.item = template(self.options.dropdown.itemTemplate);
self.render();
if (self.options.showListOnFocus) {
self.$el.on('focus', function (e) {
if (self.options.throttling) {
clearTimeout(timer);
timer = setTimeout(function () {
self.options.getData('', handleList);
}, 200);
return true;
}
// self.$dropdown.show();
});
}
self.$el.on('input', function (e) {
var $t = $(this);
var value = $t.val();
if (!value) {
self.$dropdown.hide();
return false;
}
if (self.options.ignoreCase) {
value = value.toUpperCase();
}
if (self.resultCache.hasOwnProperty(value) && self.resultCache[value]) {
handleList(value, self.resultCache[value]);
return true;
}
if (self.options.showListOnFocus || self.options.minLength <= value.length) {
if (self.options.throttling) {
clearTimeout(timer);
timer = setTimeout(function () {
self.options.getData(value, handleList);
}, 200);
return true;
}
self.options.getData(value, handleList);
}
});
self.$el.on('keydown', function (e) {
var $t = $(this);
var keyCode = e.keyCode;
var $items, $hover;
// BACKSPACE KEY
if (keyCode == '8' && !$t.val()) {
if (!self.options.multiple.enable) {
return true;
}
if (!self.value.length) {
return true;
}
var lastItem = self.value[self.value.length - 1];
self.remove(lastItem);
return false;
}
// UP DOWN ARROW KEY
if (keyCode == '38' || keyCode == '40') {
$items = self.$dropdown.find('[data-id]');
if (!$items.size()) {
return false;
}
$hover = $items.filter('.ac-hover');
if (!$hover.size()) {
$items.removeClass('ac-hover');
$items.eq(keyCode == '40' ? 0 : -1).addClass('ac-hover');
} else {
var index = $hover.index();
$items.removeClass('ac-hover');
$items.eq(keyCode == '40' ? (index + 1) % $items.size() : index - 1).addClass('ac-hover');
}
return false;
}
// ENTER KEY CODE
if (keyCode == '13') {
$items = self.$dropdown.find('[data-id]');
if (!$items.size()) {
return false;
}
$hover = $items.filter('.ac-hover');
if (!$hover.size()) {
return false;
}
self.setValue({
id: $hover.data('id'),
text: $hover.data('text'),
value: $hover.data('value')
});
return false;
}
});
self.$dropdown.on('click', '[data-id]', function (e) {
var $t = $(this);
var item = {
id: $t.data('id'),
text: $t.data('text'),
value : $t.data('value')
};
self.setValue(item);
});
self.$appender.on('click', '[data-id] .close', function (e) {
var $t = $(this);
var $li = $t.closest('[data-id');
var item = {
id: $li.data('id'),
text: $li.data('text'),
value:$t.data('value')
};
self.remove(item);
});
},
render: function () {
var self = this;
if (self.options.dropdown.el) {
self.$dropdown = $(self.options.dropdown.el);
} else {
self.$dropdown = $(document.createElement(self.options.dropdown.tagName));
self.$dropdown.insertAfter(self.$el);
}
self.$dropdown.addClass(self.options.dropdown.className);
if (self.options.appender.el) {
self.$appender = $(self.options.appender.el);
} else {
self.$appender = $(document.createElement(self.options.appender.tagName));
self.$appender.insertBefore(self.$el);
}
if (self.options.hidden.enable) {
if (self.options.hidden.el) {
self.$hidden = $(self.options.hidden.el);
} else {
self.$hidden = $('<input type="hidden" class="validate" />');
self.$wrapper.append(self.$hidden);
}
if (self.options.hidden.inputName) {
self.$el.attr('name', self.options.hidden.inputName);
}
if (self.options.hidden.required) {
self.$hidden.attr('required', 'required');
}
}
self.$appender.addClass(self.options.appender.className);
},
setValue: function (item) {
var self = this;
if (self.options.multiple.enable) {
self.append(item);
} else {
self.select(item);
}
},
append: function (item) {
var self = this;
var $tag = self.compiled.tag({ 'item': item });
if (self.value.some(function (selectedItem) {
return selectedItem.id === item.id;
})) {
if ('function' === typeof self.options.multiple.onExist) {
self.options.multiple.onExist.call(this, item);
}
return false;
}
if (self.value.length >= self.options.multiple.maxSize) {
if ('function' === typeof self.options.multiple.onExceed) {
self.options.multiple.onExceed.call(this, self.options.multiple.maxSize);
}
return false;
}
self.value.push(item);
self.$appender.append($tag);
var valueStr = self.value.map(function (selectedItem) {
return selectedItem.id;
}).join(',');
if (self.options.hidden.enable) {
self.$hidden.val(valueStr);
}
self.$el.val('');
self.$el.data('value', valueStr);
self.$dropdown.html('').hide();
if ('function' === typeof self.options.multiple.onAppend) {
self.options.multiple.onAppend.call(self, item);
}
},
remove: function (item) {
var self = this;
self.$appender.find('[data-id="' + item.id + '"]').remove();
self.value = self.value.filter(function (selectedItem) {
return selectedItem.id !== item.id;
});
var valueStr = self.value.map(function (selectedItem) {
return selectedItem.id;
}).join(',');
if (self.options.hidden.enable) {
self.$hidden.val(valueStr);
self.$el.data('value', valueStr);
}
self.$dropdown.html('').hide();
if ('function' === typeof self.options.multiple.onRemove) {
self.options.multiple.onRemove.call(self, item);
}
self.options.onRemove(item);
},
select: function (item) {
var self = this;
self.value = item.text;
self.$el.val(item.text);
self.$el.data('value', item.id);
self.$dropdown.html('').hide();
if (self.options.hidden.enable) {
self.$hidden.val(item.id);
}
self.options.onSelect(item);
}
};
$.fn.materialize_autocomplete = function (options) {
var el = this;
var $el = $(el).eq(0);
var instance = $el.data('autocomplete');
if (instance && arguments.length) {
return instance;
}
var autocomplete = new Autocomplete(el, options);
$el.data('autocomplete', autocomplete);
$el.dropdown();
return autocomplete;
};
}));
down load this js and save inside your js folder jquery.materialize-autocomplete.js and u can over ride onSelect,minLength,showListOnFocus
Visit the link for demo https://ampersandacademy.com/demo/autocomplete/
you can easily achieve the autocomplete functionality using the Devberidge plugin.
Get Devbridge plugin using https://github.com/devbridge/jQuery-Autocomplete
<script type="text/javascript">
$(document).ready(function() {
$("#country").devbridgeAutocomplete({
//lookup: countries,
serviceUrl:"getCountry.php", //tell the script where to send requests
type:'POST',
//callback just to show it's working
onSelect: function (suggestion) {
// $('#selection').html('You selected: ' + suggestion.value + ', ' + suggestion.data);
},
showNoSuggestionNotice: true,
noSuggestionNotice: 'Sorry, no matching results',
});
});
Here the getCountry.php file returns the JSON data. For more info visit https://ampersandacademy.com/tutorials/materialize-css/materialize-css-framework-ajax-autocomplete-example-using-php
According to the commit done by SuperDJ (https://goo.gl/0Mbrtg), I didn't manage to get it works...
Here is the code :
<div class="row">
<div class="col s12">
<div class="row">
<div class="input-field col s12">
<input type="text" id="autocomplete" class="autocomplete highlight-matching" data-array='[{"value": "example","path": "","class": ""},{"value": "example 2","path": "","class": ""},{"value": "test","path": "","class": ""}]'>
<label for="autocomplete">Autocomplete</label>
</div>
</div>
</div>
</div>
Here is a codepen test :
http://codepen.io/anthonyvialleton/pen/BjPjKM
Need some help to get this work.
As per, here.
You just need to do this simple thing (From the example there only):
HTML:
<div class="row">
<div class="col s12">
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">textsms</i>
<input type="text" id="autocomplete-input" class="autocomplete">
<label for="autocomplete-input">Autocomplete</label>
</div>
</div>
</div>
JS:
$('input.autocomplete').autocomplete({
data: {
"Apple": null,
"Microsoft": null,
"Google": null
}
});
(function (root, factory) {
if(typeof module === 'object' && module.exports) {
module.exports = factory(require('jquery'));
} else if(typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else {
factory(root.jQuery);
}
}(this, function ($) {
var template = function (text) {
var matcher = new RegExp('<%=([\\s\\S]+?)%>|<%([\\s\\S]+?)%>|$', 'g');
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, interpolate, evaluate, offset) {
source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
index = offset + match.length;
if (match == "<% item.value %>")
interpolate = " item.value ";
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} else if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
return match;
});
source += "';\n";
source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + 'return __p;\n';
var render;
try {
render = new Function('obj', source);
} catch (e) {
e.source = source;
throw e;
}
var _template = function(data) {
return render.call(this, data);
};
_template.source = 'function(obj){\n' + source + '}';
return _template;
};
var Autocomplete = function (el, options) {
this.options = $.extend(true, {}, Autocomplete.defaults, options);
this.$el = $(el);
this.$wrapper = this.$el.parent();
this.compiled = {};
this.$dropdown = null;
this.$appender = null;
this.$hidden = null;
this.resultCache = {};
this.value = '';
this.initialize();
};
Autocomplete.defaults = {
cacheable: true,
limit: 10,
multiple: {
enable: false,
maxSize: 4,
onExist: function (item) {
Materialize.toast('Tag: ' + item.text + '(' + item.id + ') is already added!', 2000);
},
onExceed: function (maxSize, item) {
Materialize.toast('Can\'t add over ' + maxSize + ' tags!', 2000);
},
onAppend: function (item) {
var self = this;
self.$el.removeClass('active');
self.$el.click();
},
onRemove: function (item) {
var self = this;
self.$el.removeClass('active');
self.$el.click();
}
},
hidden: {
enable: true,
el: '',
inputName: '',
required: false
},
appender: {
el: '',
tagName: 'ul',
className: 'ac-appender',
tagTemplate: '<div class="chip" data-id="<%= item.id %>" data-value="<% item.value %> data-text="<% item.text %>" "><%= item.text %>(<%= item.id %>)<i class="material-icons close">close</i></div>'
},
dropdown: {
el: '',
tagName: 'ul',
className: 'ac-dropdown',
itemTemplate: '<li class="ac-item" data-id="<%= item.id %>" data-value="<% item.value %>" data-text="<%= item.text %>" ><%= item.text %></li>',
noItem: ''
},
handlers: {
'setValue': '.ac-dropdown .ac-item',
'.ac-appender .ac-tag .close': 'remove'
},
getData: function (value, callback) {
callback(value, []);
},
onSelect: function (item) { },
onRemove: function (item) { alert('delete'); },
ignoreCase: true,
throttling: true,
showListOnFocus: false,
minLength:0
};
Autocomplete.prototype = {
constructor: Autocomplete,
initialize: function () {
var self = this;
var timer;
var fetching = false;
function getItemsHtml (list) {
var itemsHtml = '';
if (!list.length) {
return self.options.dropdown.noItem;
}
list.forEach(function (item, idx) {
if (idx >= self.options.limit) {
return false;
}
itemsHtml += self.compiled.item({ 'item': item});
});
return itemsHtml;
}
function handleList (value, list) {
var itemsHtml = getItemsHtml(list);
var currentValue = self.$el.val();
if (self.options.ignoreCase) {
currentValue = currentValue.toUpperCase();
}
if (self.options.cacheable && !self.resultCache.hasOwnProperty(value)) {
self.resultCache[value] = list;
}
if (value !== currentValue) {
return false;
}
if(itemsHtml) {
self.$dropdown.html(itemsHtml);
self.$dropdown.show();
} else {
self.$dropdown.hide();
}
}
self.value = self.options.multiple.enable ? [] : '';
self.compiled.tag = template(self.options.appender.tagTemplate);
self.compiled.item = template(self.options.dropdown.itemTemplate);
self.render();
if (self.options.showListOnFocus) {
self.$el.on('focus', function (e) {
if (self.options.throttling) {
clearTimeout(timer);
timer = setTimeout(function () {
self.options.getData('', handleList);
}, 200);
return true;
}
// self.$dropdown.show();
});
}
self.$el.on('input', function (e) {
var $t = $(this);
var value = $t.val();
if (!value) {
self.$dropdown.hide();
return false;
}
if (self.options.ignoreCase) {
value = value.toUpperCase();
}
if (self.resultCache.hasOwnProperty(value) && self.resultCache[value]) {
handleList(value, self.resultCache[value]);
return true;
}
if (self.options.showListOnFocus || self.options.minLength <= value.length) {
if (self.options.throttling) {
clearTimeout(timer);
timer = setTimeout(function () {
self.options.getData(value, handleList);
}, 200);
return true;
}
self.options.getData(value, handleList);
}
});
self.$el.on('keydown', function (e) {
var $t = $(this);
var keyCode = e.keyCode;
var $items, $hover;
// BACKSPACE KEY
if (keyCode == '8' && !$t.val()) {
if (!self.options.multiple.enable) {
return true;
}
if (!self.value.length) {
return true;
}
var lastItem = self.value[self.value.length - 1];
self.remove(lastItem);
return false;
}
// UP DOWN ARROW KEY
if (keyCode == '38' || keyCode == '40') {
$items = self.$dropdown.find('[data-id]');
if (!$items.size()) {
return false;
}
$hover = $items.filter('.ac-hover');
if (!$hover.size()) {
$items.removeClass('ac-hover');
$items.eq(keyCode == '40' ? 0 : -1).addClass('ac-hover');
} else {
var index = $hover.index();
$items.removeClass('ac-hover');
$items.eq(keyCode == '40' ? (index + 1) % $items.size() : index - 1).addClass('ac-hover');
}
return false;
}
// ENTER KEY CODE
if (keyCode == '13') {
$items = self.$dropdown.find('[data-id]');
if (!$items.size()) {
return false;
}
$hover = $items.filter('.ac-hover');
if (!$hover.size()) {
return false;
}
self.setValue({
id: $hover.data('id'),
text: $hover.data('text'),
value: $hover.data('value')
});
return false;
}
});
self.$dropdown.on('click', '[data-id]', function (e) {
var $t = $(this);
var item = {
id: $t.data('id'),
text: $t.data('text'),
value : $t.data('value')
};
self.setValue(item);
});
self.$appender.on('click', '[data-id] .close', function (e) {
var $t = $(this);
var $li = $t.closest('[data-id');
var item = {
id: $li.data('id'),
text: $li.data('text'),
value:$t.data('value')
};
self.remove(item);
});
},
render: function () {
var self = this;
if (self.options.dropdown.el) {
self.$dropdown = $(self.options.dropdown.el);
} else {
self.$dropdown = $(document.createElement(self.options.dropdown.tagName));
self.$dropdown.insertAfter(self.$el);
}
self.$dropdown.addClass(self.options.dropdown.className);
if (self.options.appender.el) {
self.$appender = $(self.options.appender.el);
} else {
self.$appender = $(document.createElement(self.options.appender.tagName));
self.$appender.insertBefore(self.$el);
}
if (self.options.hidden.enable) {
if (self.options.hidden.el) {
self.$hidden = $(self.options.hidden.el);
} else {
self.$hidden = $('<input type="hidden" class="validate" />');
self.$wrapper.append(self.$hidden);
}
if (self.options.hidden.inputName) {
self.$el.attr('name', self.options.hidden.inputName);
}
if (self.options.hidden.required) {
self.$hidden.attr('required', 'required');
}
}
self.$appender.addClass(self.options.appender.className);
},
setValue: function (item) {
var self = this;
if (self.options.multiple.enable) {
self.append(item);
} else {
self.select(item);
}
},
append: function (item) {
var self = this;
var $tag = self.compiled.tag({ 'item': item });
if (self.value.some(function (selectedItem) {
return selectedItem.id === item.id;
})) {
if ('function' === typeof self.options.multiple.onExist) {
self.options.multiple.onExist.call(this, item);
}
return false;
}
if (self.value.length >= self.options.multiple.maxSize) {
if ('function' === typeof self.options.multiple.onExceed) {
self.options.multiple.onExceed.call(this, self.options.multiple.maxSize);
}
return false;
}
self.value.push(item);
self.$appender.append($tag);
var valueStr = self.value.map(function (selectedItem) {
return selectedItem.id;
}).join(',');
if (self.options.hidden.enable) {
self.$hidden.val(valueStr);
}
self.$el.val('');
self.$el.data('value', valueStr);
self.$dropdown.html('').hide();
if ('function' === typeof self.options.multiple.onAppend) {
self.options.multiple.onAppend.call(self, item);
}
},
remove: function (item) {
var self = this;
self.$appender.find('[data-id="' + item.id + '"]').remove();
self.value = self.value.filter(function (selectedItem) {
return selectedItem.id !== item.id;
});
var valueStr = self.value.map(function (selectedItem) {
return selectedItem.id;
}).join(',');
if (self.options.hidden.enable) {
self.$hidden.val(valueStr);
self.$el.data('value', valueStr);
}
self.$dropdown.html('').hide();
if ('function' === typeof self.options.multiple.onRemove) {
self.options.multiple.onRemove.call(self, item);
}
self.options.onRemove(item);
},
select: function (item) {
var self = this;
self.value = item.text;
self.$el.val(item.text);
self.$el.data('value', item.id);
self.$dropdown.html('').hide();
if (self.options.hidden.enable) {
self.$hidden.val(item.id);
}
self.options.onSelect(item);
}
};
$.fn.materialize_autocomplete = function (options) {
var el = this;
var $el = $(el).eq(0);
var instance = $el.data('autocomplete');
if (instance && arguments.length) {
return instance;
}
var autocomplete = new Autocomplete(el, options);
$el.data('autocomplete', autocomplete);
$el.dropdown();
return autocomplete;
};
}));
You can use the above .js file and you can over ride
Onselect
showListOnFocus: false,
minLength:2
according to your requirement and it will work.
Just write the Initialisation script inside $(document).ready(function(){});
i.e.
$(document).ready(function(){
$('input.autocomplete').autocomplete({
data: {
"Apple": null,
"Microsoft": null,
"Google": null
}
});
});
As mentioned above, autocomplete has been added the the materialize framework but it is still pretty limited. I'm waiting for a solution that supports values (ex Ids) icons and text.
Re: https://github.com/Dogfalo/materialize/issues/4086

Polyline Fusion table action on click

I've edit this function :
In the first part of the code ,I display polyline from my fusion table. In the seconde part I want to affect an event on click to change style of polyline selected, but he doesn't work, he hidde all polylines..
function filterTC() {
var filter = [];
var j = document.getElementsByName('sousmenu4');
for (var i = 0, k; k = j[i]; i++) {
if (k.checked) {
filter.push('\'' + k.value + '\'');
}
}
if (filter.length) {
if (!layer3.getMap()) {
layer3.setMap(map);
}
layer3.setOptions({
query: {
select: 'geometry',
from: '1twRoA12Qc7toIRQe_Uk6XKFS8Ts-V_AvcHZahGlx',
where: '\'indice\' IN (' + filter.join(',') + ')',
},
options: {
styleId: 2,
templateId: 3
}
});
}
else {
layer3.setMap(null);
}
The problem is with the code below :
selected={};
google.maps.event.addListener(layer3, 'click', function(e) {
var val=e.row['name'].value,
vals=[];
//update the selected-object
selected[val]=(!selected[val])?true:false;
for(var l in selected){
if(selected[l]){
vals.push(l);
}
}
layer3.set("styles", [{
where: "'name' IN('"+vals.join("','")+"')",
polylineOptions: {
strokeColor: "#cc0000",
strokeWeight: "4" }
}]);
});
}
Thanks for your help

Add a additional <li> tag to the end of rails3-jquery-autocomplete plugin

I'm trying to add an addition tag to the end of the autocomplete list.
$('#address ul.ui-autocomplete').append("<li>Add Venue</li>");
I'm trying to figure out where I can place the code above to add the extra li to the autocomplete list.
Any help will be deeply appreciated.
This is the rails3-jquery-autocomplete file.
source: function( request, response ) {
$.getJSON( $(e).attr('data-autocomplete'), {
term: extractLast( request.term )
}, function() {
$(arguments[0]).each(function(i, el) {
var obj = {};
obj[el.id] = el;
$(e).data(obj);
});
response.apply(null, arguments);
});
},
open: function() {
// when appending the result list to another element, we need to cancel the "position: relative;" css.
if (append_to){
$(append_to + ' ul.ui-autocomplete').css('position', 'static');
}
},
search: function() {
// custom minLength
var minLength = $(e).attr('min_length') || 2;
var term = extractLast( this.value );
if ( term.length < minLength ) {
return false;
}
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
terms.push( ui.item.value );
// add placeholder to get the comma-and-space at the end
if (e.delimiter != null) {
terms.push( "" );
this.value = terms.join( e.delimiter );
} else {
this.value = terms.join("");
if ($(this).attr('data-id-element')) {
$($(this).attr('data-id-element')).val(ui.item.id);
}
if ($(this).attr('data-update-elements')) {
var data = $(this).data(ui.item.id.toString());
var update_elements = $.parseJSON($(this).attr("data-update-elements"));
for (var key in update_elements) {
$(update_elements[key]).val(data[key]);
}
}
}
var remember_string = this.value;
$(this).bind('keyup.clearId', function(){
if($(this).val().trim() != remember_string.trim()){
$($(this).attr('data-id-element')).val("");
$(this).unbind('keyup.clearId');
}
});
$(this).trigger('railsAutocomplete.select');
return false;
}
});
}
Solved it with this.
$('#address').bind('autocompleteopen', function(event,data){
$('<li id="ac-add-venue">Add venue</li>').appendTo('ul.ui-autocomplete');
});

jQuery Mobile Slider / Carousel

I need to make a jQuery "Carousel" pretty similar to the one in this page: http://m.henrys.com/
There are plenty of "carousel" jQuery plugins, but how can I bind a carousel next/prev page action to the "swipe" mobile phone/tablet gesture?
Either you use a JQM plugin for that (I've seen some available), or you add your own touch event management and manually call the next/prev on your chosen plugin.
For example,
$(document).swiperight(function(){
jqPlugin.goPrev();
});
$(document).swipeleft(function(){
jqPlugin.goNext();
});
More details on JQM events can be found in their documentation
Here is code of their jQuery carousel plugin
(function ($) {
$.fn.slideCarousel = function (options) {
var options = jQuery.extend({
duration: 500,
current_slide: 0,
counter_slide: false,
structure_counter_parent: "<div class='slider-counter'></div>",
structure_counter_el: "<span></span>",
counter_slide_number: false,
btn_next: false,
btn_prev: false,
slide_switch: false,
slide_timer: 10000
}, options);
return this.each(function () {
var elem = this;
var slides = $(elem).children();
var slide_last = slides.length - 1;
var img_list = $(elem).find('img');
var current_slide = options.current_slide;
var current_slide_counter = options.current_slide;
var width_elem;
var nav_version = navigator.appVersion;
var permit_next = true;
var css_transitions;
var css_transform;
var _timer;
var transit_timer;
var agent = null;
var orient_change = true;
var link_counter;
$(elem).closest("*[data-role='page']").bind('pageshow', setup);
$(window).bind('resize orientationchange', function () {
if (!permit_next) {
orient_change = false;
return;
}
size_change();
});
function size_change() {
size_slider();
fix_slider();
return false;
}
if (css_supports('transition')) {
css_transitions = true;
if (agent === null) {
agent = GetAgent();
}
var agent_low = agent.replace(/^[a-zA-Z]/, function (value) {
return value.toLowerCase();
});
slides.bind(agent_low + 'TransitionEnd transitionend', TransitionEnd);
}
if (css_supports('transform')) {
if (agent === null) {
agent = GetAgent();
}
if (agent == 'Webkit') {
if (nav_version.indexOf('BlackBerry') == -1 || nav_version.indexOf('Version/7') == -1) {
if (nav_version.indexOf('Android') == -1 || $(elem).closest("*[data-role='page']").find('select').length == 0) {
css_transform = true;
slides.css(agent + 'Transform', 'translate3d(0px,0px,0px)');
}
}
}
}
if (nav_version.indexOf('Android 2.1') != -1) {
if (document.getElementsByTagName('iframe').length > 0) {
$(elem).closest("*[data-role='page']").bind('pagebeforehide', function () {
$(this).nextAll("[data-role='page']").bind('pagebeforeshow', function () {
window.location.reload();
});
});
}
}
function css_supports(css_prop) {
var div = document.createElement('div'),
vendors = 'Khtml Ms O Moz Webkit'.split(' '),
len = vendors.length;
if (css_prop in div.style) return true;
css_prop = css_prop.replace(/^[a-z]/, function (val) {
return val.toUpperCase();
});
while (len--) {
if (vendors[len] + css_prop in div.style) {
agent = vendors[len];
return true;
}
}
return false;
}
function GetAgent() {
$.browser.chrome = /chrome/.test(navigator.userAgent.toLowerCase());
if ($.browser.chrome) return "Moz";
if ($.browser.mozilla) return "Moz";
if ($.browser.opera) return "O";
if ($.browser.safari) return "Webkit";
if ($.browser.msie) return "Ms";
}
function setup() {
if (agent == 'Webkit') {
if (img_list.length > 0) img();
}
loadEnd();
}
function img() {
var call_back = 0;
var error_back = 0;
img_list.each(function () {
$(this).bind('error', function () {
error_back++;
img_event(call_back + error_back);
});
$(this).bind('load', function () {
call_back++;
img_event(call_back + error_back);
});
});
}
function img_event(event_back) {
if (event_back == img_list.length) {
loadEnd();
}
}
function loadEnd() {
addClass();
size_slider();
fix_slider();
};
function addClass() {
var i = 0;
slides.each(function () {
$(this).addClass('slide-item-' + i);
i++;
})
}
function size_slider() {
var height = 0;
offTransition();
width_elem = $(elem).width();
slides.css('width', width_elem);
slides.each(function () {
if ($(this).outerHeight() > height) height = $(this).outerHeight();
});
$(elem).css('height', height);
}
function fix_slider() {
offTransition();
if (css_transform) {
slides.not('.slide-item-' + current_slide).css(agent + 'Transform', 'translate3d' + '(' + width_elem + 'px,0,0)');
slides.filter('.slide-item-' + current_slide).css(agent + 'Transform', 'translate3d(0,0,0)');
return;
}
slides.not('.slide-item-' + current_slide).css('left', width_elem);
slides.filter('.slide-item-' + current_slide).css('left', 0);
}
if (options.counter_slide) {
$(elem).after(options.structure_counter_parent);
link_counter = $(elem).next();
slides.each(function () {
link_counter.append(options.structure_counter_el);
});
if (options.counter_slide_number) {
var i = 1;
link_counter.find("*:empty").each(function () {
$(this).text(i);
i++;
})
}
}
addCheck();
function slideCounter() {
link_counter.children().removeClass('current');
link_counter.children().eq(current_slide).addClass('current');
}
function addCheck() {
if (options.counter_slide) slideCounter();
if (options.slide_switch) onTimer();
}
function onTimer() {
_timer = setTimeout(function () {
slideNext();
}, options.slide_timer)
}
function offTransition() {
if (css_transitions) {
slides.css('transition-property', 'none')
.css(agent + 'TransitionProperty', 'none');
}
}
function TransitionEnd() {
if (!orient_change) {
size_change();
orient_change = true;
}
permit_next = true;
}
$(elem).bind('swipeleft', slideNext);
if (options.btn_next) {
$(options.btn_next).bind('tap', slideNext);
};
$(elem).bind('swiperight', slidePrev);
if (options.btn_prev) {
$(options.btn_prev).bind('tap', slidePrev);
};
function checkDevice() {
if (true) {
$(document).scrollTop($(document).scrollTop() + 1);
}
}
function preparation_next() {
var current_slide_;
offTransition();
if (current_slide > slide_last) current_slide_ = 0;
else current_slide_ = current_slide;
if (css_transform) {
slides.filter('.slide-item-' + current_slide_).css(agent + 'Transform', 'translate3d' + '(' + width_elem + 'px,0,0)');
return;
}
slides.filter('.slide-item-' + current_slide_).css('left', width_elem);
}
function preparation_prev() {
var current_slide_;
offTransition();
if (current_slide < 0) current_slide_ = slide_last;
else current_slide_ = current_slide;
if (css_transform) {
slides.filter('.slide-item-' + current_slide_).css(agent + 'Transform', 'translate3d' + '(' + (-width_elem) + 'px,0,0)');
return;
}
slides.filter('.slide-item-' + current_slide_).css('left', -width_elem);
}
function slideNext(event) {
if (event) event.stopPropagation();
if (!permit_next) return;
if (options.slide_switch) clearTimeout(_timer);
current_slide++;
preparation_next();
slideToggle('next');
}
function slidePrev(event) {
if (event) event.stopPropagation();
if (!permit_next) return;
if (options.slide_switch) clearTimeout(_timer);
current_slide--;
preparation_prev();
slideToggle('prev');
}
function slideToggle(direct) {
if (css_transitions) {
if (transit_timer) return;
transit_timer = setTimeout(function () {
slides.css('transition', 'all ' + options.duration + 'ms')
.css(agent + 'Transition', 'all ' + options.duration + 'ms');
setTimeout(function () {
if (direct == 'next') {
if (css_transform) {
slides.filter('.slide-item-' + (current_slide - 1)).css(agent + 'Transform', 'translate3d' + '(' + (-width_elem) + 'px,0,0)');
if (current_slide > slide_last) current_slide = 0;
slides.filter('.slide-item-' + current_slide).css(agent + 'Transform', 'translate3d(0,0,0)');
}
else {
slides.filter('.slide-item-' + (current_slide - 1)).css('left', -width_elem);
if (current_slide > slide_last) current_slide = 0;
slides.filter('.slide-item-' + current_slide).css('left', 0);
}
}
else if (direct == 'prev') {
if (css_transform) {
slides.filter('.slide-item-' + (current_slide + 1)).css(agent + 'Transform', 'translate3d' + '(' + width_elem + 'px,0,0)');
if (current_slide < 0) current_slide = slide_last;
slides.filter('.slide-item-' + current_slide).css(agent + 'Transform', 'translate3d(0,0,0)');
}
else {
slides.filter('.slide-item-' + (current_slide + 1)).css('left', width_elem);
if (current_slide < 0) current_slide = slide_last;
slides.filter('.slide-item-' + current_slide).css('left', 0);
}
}
addCheck();
transit_timer = false;
}, 1);
}, 20);
}
else {
if (direct == 'next') {
slides.filter('.slide-item-' + (current_slide - 1)).animate({ left: -width_elem }, options.duration);
if (current_slide > slide_last) current_slide = 0;
slides.filter('.slide-item-' + current_slide).animate({ left: 0 }, options.duration, TransitionEnd);
}
else if (direct == 'prev') {
slides.filter('.slide-item-' + (current_slide + 1)).animate({ left: width_elem }, options.duration);
if (current_slide < 0) current_slide = slide_last;
slides.filter('.slide-item-' + current_slide).animate({ left: 0 }, options.duration, TransitionEnd);
}
addCheck();
}
if (options.duration > 1) permit_next = false;
}
});
};
})(jQuery);

$.ajax({url:link}) and Jquery UI Droppable

I have a problem.
I drop element into #projectsActive. New element have been created there. Old element have been deleted with fadeOut
But ajax query sometimes isn't running.
What's the reason?
$("#projectsActive").droppable({
drop: function (event, elem)
{
var e = elem.draggable;
var linkToSend = "/Projects/Publish/" + $(e).attr("projectid");
$.ajax({ url: linkToSend });
var projectid = $(e).attr("projectid");
var innerText = "";
if ($(e).find("a").length > 0)
{
innerText = $(e).children("a").html();
}
else
{
innerText = $(e).html();
}
var newObject = '<li class="project dragg" projectid="' + projectid + '">' + innerText + '</li>';
$(e).fadeOut("fast", function ()
{
$("#projectsActive").append(newObject);
$(this).remove();
BindDrags();
});
}
});

Resources