jQuery Taggd插件(编辑模式)在输入字段中获取值

时间:2015-04-19 05:17:17

标签: javascript jquery plugins

我正在使用jQuery taggd插件,到目前为止一切顺利。 我修改了一点,我在编辑模式下使用它。因此,当用户在文本框中键入值时,它会检查它是URL还是字符串,如果它是一个URL,它运行ajax调用php文件,该文件从URL中删除一些数据。网址标题,说明和图片。我创建了3个隐藏的输入字段,一旦ajax调用完成就会填充。单击SAVE图标后,它会将数据保存到DOM。但是我希望一旦用户再次点击标签就再次显示它。目前它只显示标准输入字段的值。

这是taggd插件,有一些小的修改:



/*!
 * jQuery Taggd
 * A helpful plugin that helps you adding 'tags' on images.
 *
 * License: MIT
 */

(function($) {
	'use strict';
	
	var defaults = {
		edit: false,
		
		align: {
			x: 'center',
			y: 'center'
		},

		handlers: {},

		offset: {
			left: 0,
			top: 0
		},
		
		strings: {
			save: '✓',
			delete: '×'
		}
	};
	
	var methods = {
		show: function() {
			var $this = $(this),
				$label = $this.next();
			
			$this.addClass('active');
			$label.addClass('show').find('input').focus();
		},
		
		hide: function() {
			var $this = $(this);
			
			$this.removeClass('active');
			$this.next().removeClass('show');
		},
		
		toggle: function() {
			var $hover = $(this).next();
			
			if($hover.hasClass('show')) {
				methods.hide.call(this);
			} else {
				methods.show.call(this);
			}
		}
        
	};
	
	
	/****************************************************************
	 * TAGGD
	 ****************************************************************/
	
	var Taggd = function(element, options, data) {
		var _this = this;
		
		if(options.edit) {
			options.handlers = {
				click: function() {
                    
					_this.hide();
					methods.show.call(this);
				}
			};
		}
		
		this.element = $(element);
		this.options = $.extend(true, {}, defaults, options);
		this.data = data;
		this.initialized = false;
		
		if(!this.element.height() || !this.element.width()) {
			this.element.on('load', _this.initialize.bind(this));
		} else this.initialize();
	};
	
	
	/****************************************************************
	 * INITIALISATION
	 ****************************************************************/
	
	Taggd.prototype.initialize = function() {
		var _this = this;
		
		this.initialized = true;
		
		this.initWrapper();
		this.addDOM();
		
		if(this.options.edit) {
			this.element.on('click', function(e) {
                
				var poffset = $(this).parent().offset(),
					x = (e.pageX - poffset.left) / _this.element.width(),
					y = (e.pageY - poffset.top) / _this.element.height();

				_this.addData({
					x: x,
					y: y,
					text: '',
                    url: '',
                    url_title: '',
                    url_description: '',
                    url_image: ''
				});

				_this.show(_this.data.length - 1);
			});
		}
		
		$(window).resize(function() {
			_this.updateDOM();
		});
	};
	
	Taggd.prototype.initWrapper = function() {
		var wrapper = $('<div class="taggd-wrapper" />');
		this.element.wrap(wrapper);
		
		this.wrapper = this.element.parent('.taggd-wrapper');
	};
	
	Taggd.prototype.alterDOM = function() {
		var _this = this;
		
		this.wrapper.find('.taggd-item-hover').each(function() {
			var $e = $(this),
				
				$input = $('<input id="url" type="text" size="16" />')
					.val($e.text()),
                $url_title = $('<input type="text" id="url_title" class="url_title" />'),
				$button_ok = $('<button />')
					.html(_this.options.strings.save),
                
                $url_description = $('<input type="text" class="url_description" id="url_description" />'),
                $url_image = $('<input type="text" class="url_img" id="url_img" />'),
                $url_preview = $('<div id="content"></div>'),
				$button_delete = $('<button />')
					.html(_this.options.strings.delete);
			
            
			$button_delete.on('click', function() {
				var x = $e.attr('data-x'),
					y = $e.attr('data-y');
				
				_this.data = $.grep(_this.data, function(v) {
					return v.x != x || v.y != y;
				});
				
				_this.addDOM();
				_this.element.triggerHandler('change');
			});
            
            // Typing URL timer
            var typingTimer;
            var doneTypingInterval = 2000;
            
            $input.keyup(function() {
                clearTimeout(typingTimer);
                typingTimer = setTimeout(doneTyping, doneTypingInterval);
            });
            
            $input.keydown(function() {
                clearTimeout(typingTimer);
                $url_preview.empty();
            });
            
            // Process URL scrape request
            function doneTyping() {
                var getUrl = $input.val();
                
                if(isURL(getUrl)) {
                    console.log('Typed text is a URL');
                    $url_preview.append('<img src="images/loader.gif" style="width:24px; padding-top:10px; height:24px; margin:0 auto;">');
                    

                    // Get url data by ajax
                    $.post('ajax/Crawl.php', {
                        'url' : getUrl
                    },function(data) {
                        
                        $url_preview.empty();
                        
                        
                        var content = '<h3 class="url_title">' + data.title + '</h3><p class="url_description" style="font-size:11px;">' + data.description + '</p><img class="url_image" src="' + data.images + '" style="width:100%; height:auto;">';
                        $url_preview.append(content);
                        
                        $url_title.val(data.title);
                        $url_description.val(data.description);
                        $url_image.val(data.images);
                        console.log(content);

                        
                    }, 'json');

                } else {
                    console.log('Typed text is a string');
                }
            };

            
            function isURL(url) {
                
                var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
                '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
                '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
                '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
                '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
                '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
                
                if(!pattern.test(url)) {
                    return false;
                } else {
                    if(!/^(https?|ftp):\/\//i.test(url)) {

                        url = 'http://'+url;
                        $input.val(url); 
                }
                return true;
                }
   
             };

                       
            $button_ok.on('click', function() {
				var x = $e.attr('data-x'),
					y = $e.attr('data-y'),
                    
					item = $.grep(_this.data, function(v) {
						return v.x == x && v.y == y;
					}).pop();
				
				if(item) item.text = $input.val();
                if(isURL(item.text)) {
                    if(item) item.url = item.text;
                } else {
                    if(item) item.url = null;
                }
                
                if(item) item.url_title = $url_title.val();
                if(item) item.url_description = $url_description.val();
                if(item) item.url_image = $url_image.val();

				_this.addDOM();
				_this.element.triggerHandler('change');
				//_this.hide();
			});
			/*$input.on('change', function() {

				var x = $e.attr('data-x'),
					y = $e.attr('data-y'),
					item = $.grep(_this.data, function(v) {
						return v.x == x && v.y == y;
					}).pop();
				
				if(item) item.text = $input.val();
              

				_this.addDOM();
				_this.element.triggerHandler('change');
			});
			*/
			$e.empty().append($input, $button_ok, $button_delete, $url_preview, $url_title, $url_description, $url_image);
            
            
		});
		
		_this.updateDOM();
        
	};
	
	/****************************************************************
	 * DATA MANAGEMENT
	 ****************************************************************/
	
	Taggd.prototype.addData = function(data) {
		if($.isArray(data)) {
			this.data = $.merge(this.data, data);
		} else {
			this.data.push(data);
		}
		
		if(this.initialized) {
			this.addDOM();
			this.element.triggerHandler('change');
		}
	};
	
	Taggd.prototype.setData = function(data) {
		this.data = data;
		
		if(this.initialized) {
			this.addDOM();
		}
	};
	
	Taggd.prototype.clear = function() {
		if(!this.initialized) return;
		this.wrapper.find('.taggd-item, .taggd-item-hover').remove();
	};
	
	
	/****************************************************************
	 * EVENTS
	 ****************************************************************/
	
	Taggd.prototype.on = function(event, handler) {
		if(
			typeof event !== 'string' ||
			typeof handler !== 'function'
		) return;
		
		this.element.on(event, handler);
	};
	
	
	/****************************************************************
	 * TAGS MANAGEMENT
	 ****************************************************************/
	
	Taggd.prototype.iterateTags = function(a, yep) {
		var func;
		
		if($.isNumeric(a)) {
			func = function(i, e) { return a === i; };
		} else if(typeof a === 'string') {
			func = function(i, e) { return $(e).is(a); }
		} else if($.isArray(a)) {
			func = function(i, e) {
				var $e = $(e);
				var result = false;
				
				$.each(a, function(ai, ae) {
					if(
						i === ai ||
						e === ae ||
						$e.is(ae)
					) {
						result = true;
						return false;
					}
				});
				
				return result;
			}
		} else if(typeof a === 'object') {
			func = function(i, e) {
				var $e = $(e);
				return $e.is(a);
			};
		} else if($.isFunction(a)) {
			func = a;
		} else if(!a) {
			func = function() { return true; }
		} else return this;
		
		this.wrapper.find('.taggd-item').each(function(i, e) {
			if(typeof yep === 'function' && func.call(this, i, e)) {
				yep.call(this, i, e);
			}
		});
		
		return this;
	};
	
	Taggd.prototype.show = function(a) {
		return this.iterateTags(a, methods.show);
	};
	
	Taggd.prototype.hide = function(a) {
		return this.iterateTags(a, methods.hide);
	};
	
	Taggd.prototype.toggle = function(a) {
		return this.iterateTags(a, methods.toggle);
	};
	
	/****************************************************************
	 * CLEANING UP
	 ****************************************************************/
	
	Taggd.prototype.dispose = function() {
		this.clear();
		this.element.unwrap(this.wrapper);
	};
	
	
	/****************************************************************
	 * SEMI-PRIVATE
	 ****************************************************************/
	
	Taggd.prototype.addDOM = function() {
		var _this = this;
		
		this.clear();
		this.element.css({ height: 'auto', width: 'auto' });
		
		var height = this.element.height();
		var width = this.element.width();
		
		$.each(this.data, function(i, v) {
			var $item = $('<span />');
			var $hover;
			
			if(
				v.x > 1 && v.x % 1 === 0 &&
				v.y > 1 && v.y % 1 === 0
			) {
				v.x = v.x / width;
				v.y = v.y / height;
			}
			
			if(typeof v.attributes === 'object') {
				$item.attr(v.attributes);
			}
			
			$item.attr({
				'data-x': v.x,
				'data-y': v.y
			});
			
			$item.css('position', 'absolute');
			$item.addClass('taggd-item');
			
			_this.wrapper.append($item);
			
			if(typeof v.text === 'string' && (v.text.length > 0 || _this.options.edit)) {
				$hover = $('<span class="taggd-item-hover" style="position: absolute;" />').html(v.text);
				
				$hover.attr({
					'data-x': v.x,
					'data-y': v.y
				});
				
				_this.wrapper.append($hover);
			}
			
			if(typeof _this.options.handlers === 'object') {
				$.each(_this.options.handlers, function(event, func) {
					var handler;
					
					if(typeof func === 'string' && methods[func]) {
						handler = methods[func];
					} else if(typeof func === 'function') {
						handler = func;
					}
					
					$item.on(event, function(e) {
						if(!handler) return;
						handler.call($item, e, _this.data[i]);
					});
				});
			}
		});
		
		this.element.removeAttr('style');
		
		if(this.options.edit) {
			this.alterDOM();
            
		}
		
		this.updateDOM();
	};
	
	Taggd.prototype.updateDOM = function() {
		var _this = this;
		
		this.wrapper.removeAttr('style').css({
			height: this.element.height(),
			width: this.element.width()
		});
		
		this.wrapper.find('span').each(function(i, e) {
			var $el = $(e);
			
			var left = $el.attr('data-x') * _this.element.width();
			var top = $el.attr('data-y') * _this.element.height();
			
			if($el.hasClass('taggd-item')) {
				$el.css({
					left: left - $el.outerWidth(true) / 2,
					top: top - $el.outerHeight(true) / 2
				});
			} else if($el.hasClass('taggd-item-hover')) {
				if(_this.options.align.x === 'center') {
					left -= $el.outerWidth(true) / 2;
				} else if(_this.options.align.x === 'right') {
					left -= $el.outerWidth(true);
				}
				
				if(_this.options.align.y === 'center') {
					top -= $el.outerHeight(true) / 2;
				} else if(_this.options.align.y === 'bottom') {
					top -= $el.outerHeight(true);
				}
				
				$el.attr('data-align', $el.outerWidth(true));
				
				$el.css({
					left: left + _this.options.offset.left,
					top: top + _this.options.offset.top
				});
			}
		});
	};
	
	
	/****************************************************************
	 * JQUERY LINK
	 ****************************************************************/
	
	$.fn.taggd = function(options, data) {
		return new Taggd(this, options, data);
	};
})(jQuery);
&#13;
&#13;
&#13;

我认为这会做我想要的,因为它适用于标准文本输入框,使用.val($ e.text()),工作正常,但只要我对url_title框执行相同操作,例如.val($ e.url_title()),我得到以下错误。

&#13;
&#13;
				$input = $('<input id="url" type="text" size="16" />')
					.val($e.text()),
                $url_title = $('<input type="text" id="url_title" class="url_title" />'),
				$button_ok = $('<button />')
					.html(_this.options.strings.save),
                
                $url_description = $('<input type="text" class="url_description" id="url_description" />'),
                $url_image = $('<input type="text" class="url_img" id="url_img" />'),
                $url_preview = $('<div id="content"></div>'),
				$button_delete = $('<button />')
					.html(_this.options.strings.delete);
			
&#13;
&#13;
&#13;

但是,例如,我将$ url_title更改为

&#13;
&#13;
$url_title = $('<input type="text" id="url_title" class="url_title" />').val($e.url_title()),
&#13;
&#13;
&#13;

我在控制台中收到错误消息: 未捕获的TypeError:undefined不是函数

这是主页上的初始化代码:

&#13;
&#13;
$(document).ready(function() {
	var options = {
		edit: true,
		
		align: {
			y: 'top'
		},

		offset: {
			top: 15
		},

		handlers: {
      //mouseenter: 'show',
			click: 'toggle'
		}
	};
	
	/*var data = [
		{ x: 0.22870478413068845, y: 0.41821946169772256, text: 'Eye'             },
		{ x: 0.51, y: 0.5, text: 'Bird'             },
		{ x: 0.40, y: 0.3, text: 'Water, obviously' }
	];*/
	var data = [];
	
	var taggd = $('.taggd').taggd( options, data );
	
	taggd.on('change', function() {
		console.log(taggd.data);
	});
	});
&#13;
&#13;
&#13;

在控制台日志中,它记录了正确的值:

[Object]0: Objecttext: "http://stackoverflow.com"url: "http://stackoverflow.com"url_description: "Q&A for professional and enthusiast programmers"url_image: "http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon@2.png?v=ea71a5211a91&a"url_title: "Stack Overflow"x: 0.41141586360266863y: 0.19444444444444445

我希望有人可以发光,并指出我做错的正确方向。

为了简化它,我希望能够为我的标签提供标题输入和描述输入,我将如何实现这一目标?

谢谢。

1 个答案:

答案 0 :(得分:0)

我怀疑$e.url_title()导致错误,据我所知,url_title()不是一个可以在jQuery实例上调用的方法。

据推测,您打算改为访问变量。


我在脚本中找不到问题,除了未定义的函数调用,所以我基本上重写了整个事情,这似乎有效:http://jsbin.com/nexujuhefo/2/edit?js,console,output

我认为问题是Taggd奇怪的逻辑;)


字段现在记住数据:http://jsbin.com/hosipiyuqa/1/edit?js,console,output