Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a JSON object inside a DOM `data` attribute?

I tried to set some json data inside a dataset attribute.

The HTML looks likes this

<div data-switch="true" data-json="{'key1': 'value 1'}, {'key2': 'value 2'}">

The data inside the data-json I obtain it with JavaScript in this way:

var json = $("[data-json]").data("json").toString();
json = JSON.stringify(json);

Whatever I try, it doesn't convert it to an object. It just returns a string

With toString() and stringify()

$(function() {
	json = $("[data-json]").data("json").toString();
    json = JSON.stringify(json);
    json = JSON.parse(json);
    
    console.log(json);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-json="{'key1': 'value 1'}, {'key2', 'value 2'}">

</div>

When i remove the toString() and stringify() functions, it gives the following error: Uncaught SyntaxError: Unexpected token ' in JSON at position 1

Without toString() and stringify()

$(function() {
	json = $("[data-json]").data("json");
    json = JSON.parse(json);
    
    console.log(json);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-json="{'key1': 'value 1'}, {'key2', 'value 2'}">

</div>

Fiddle with original JavaScript and HTML

/**
 * Switch content inside Metro UI blocks
 *
 * @requires {data-switch} 		Set data-switch="true" inside the dom
 */
$(function() {
	
	/**
	 * Get all switch elements
	 */
	var switches = $("[data-switch]");
	/**
	 * Sample data for each switch element	 
	var switches_data = {
		0: {
			0: {
				image: 'https://cdn.elegantthemes.com/blog/wp-content/uploads/2016/02/rules-good-ui-design-web-project-thumbnail.png',
				content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
			},
			1: {
				image: 'http://www.fujitsu.com/fts/Images/28618-workplace-manager580x224_tcm21-1830661.jpg',
				content: 'Aliquam interdum sit amet nibh aliquet accumsan.'
			},
			2: {
				image: 'http://cdn.moneycrashers.com/wp-content/uploads/2013/03/manager2.jpg',
				content: 'Vestibulum sed metus eu justo sagittis congue.'
			}
		},
		1: {
			0: {
				image: 'https://cdn.elegantthemes.com/blog/wp-content/uploads/2016/02/rules-good-ui-design-web-project-thumbnail.png',
				content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
			},
			1: {
				image: 'http://www.fujitsu.com/fts/Images/28618-workplace-manager580x224_tcm21-1830661.jpg',
				content: 'Aliquam interdum sit amet nibh aliquet accumsan.'
			},
			2: {
				image: 'http://cdn.moneycrashers.com/wp-content/uploads/2013/03/manager2.jpg',
				content: 'Vestibulum sed metus eu justo sagittis congue.'
			}
		},
		2: {
			0: {
				image: 'https://cdn.elegantthemes.com/blog/wp-content/uploads/2016/02/rules-good-ui-design-web-project-thumbnail.png',
				content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
			},
			1: {
				image: 'http://www.fujitsu.com/fts/Images/28618-workplace-manager580x224_tcm21-1830661.jpg',
				content: 'Aliquam interdum sit amet nibh aliquet accumsan.'
			},
			2: {
				image: 'http://cdn.moneycrashers.com/wp-content/uploads/2013/03/manager2.jpg',
				content: 'Vestibulum sed metus eu justo sagittis congue.'
			}
		}
	};
	*/
	/**
	 * Check if elements exists
	 */
	if(switches.length > 0) {
		/**
		 * Loop through objects
		 *
		 * @var c 	Object Key
		 * @var e 	Object Value
		 */
		$.each(switches, function(c, e) {
			/** 
			 * Get switches data current object
			 */
			var switches_data = $(this).data("switches");
			console.log(switches_data);
			/**
			 * Get next div
			 */
			var next = $(this).children().first()[0];
			next = $(next);
			/**
			 * Set type animation
			 */
			var animation = "flipInX";
			/**
			 * Set index where to start from
			 */
			var index = 0;
			/**
			 * Generate interval seconds, a random number so they will never be the same
			 */
			var x = Math.floor((Math.random() * 6000) + 3000);
			/**
			 * Loop through switches
			 *
			 * @var i 	Object Key
			 * @var b	Object Value
			 */
			$.each(switches_data, function(i, b) {
				/**
			 	 * Create new element for each switches
			 	 */
				var el = $("<div />").attr({class: "metro-ui-column-content animated", id: "content-column-" + i});
				/**
				 * Append el to next element, previous defined
				 */
				el.appendTo(next);
				/**
				 * Set background image for el
				 */
				el.css({
					"background": "url("+ b.image +") no-repeat",
					"background-size": "cover"
				});
				/**
				 * Append html content
				 */
				el.html( "<div class=\"metro-ui-column-html\">" + b.content + "</div>");
			});
			
			/**
			 * Set static this
			 */
			var self = $(this);
			/**
			 * Find all animated object
			 */
			var animated = $(this).find(".animated");
			/**
			 * Generate random number between 2000 and 4000, it acts as seconds for interval
			 */
			var x = Math.floor((Math.random() * 8000) + 4000);
			/**
			 * Loop through animated objects
			 *
			 * @var i	Object Key
			 * @var e	Object Value
			 */
			$.each(animated, function(i, e) {
				/**
				 * Start with the first animated object in the current loop
				 */ 
				if(i === 0) {
					/**
					 * Start with an timeout with random generated content, so no content will ever be loaded at the same time
					 */
					setTimeout(function() {
						/**
					 	 * Gets visible by setting the z-index
					 	 */
						$(e).css("z-index", 2).addClass("flipInX");
					}, x);
				}				
			});
			/**
			 * Set new index higher than first object
			 */
			var index = 3 ;
			/**
			 * Set interval function to start looping the animation
			 */
			setInterval(function() {
				/**
				 * Get next object from current object
				 */
				var next = self.find(".flipInX").next();
				/**
				 * If there is no next object reset to first object
				 */
				if(next.length === 0) {
					/**
					 * Update next to first object cause next doenst exist
					 */
					var next = self.find(".animated").first();
				}
				/**
				 * Set new index and add animation class
				 */
				next.css("z-index", index++).addClass("flipInX").siblings().removeClass("flipInX");
			}, x);
		});
	}
	
});
@import url('https://fonts.googleapis.com/css?family=Roboto:400,700');
body {
  background-color: #f1f1f1;
  font-family: 'Roboto', sans-serif;
  font-size: 14px;
}
* {
  box-sizing: border-box;
}
/* Metro theme UI */
.metro-theme-ui {
  max-width: 450px;
  margin: 40px auto;
  height: 250px;
}
.metro-ui-row {
  position: relative;
  width: 100%;
  min-height: 1px;
  /* Fix breaking when height is 0 */
}
.metro-ui-row:after,
.metro-ui-row:before {
  display: table;
  content: " ";
  clear: both;
}
.metro-ui-column {
  position: relative;
  background: #12A7CC;
  padding: 50px;
  box-shadow: 1px 1px 2px #ccc;
  overflow: hidden;
}
.metro-ui-column.fadeIn {
  animation: fadeIn .33s ease;
}
.metro-ui-column.fadeOut {
  animation: fadeOut .33s ease;
}
.metro-ui-column .metro-ui-column-content {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
}
.metro-ui-column .metro-ui-column-html {
  background: rgba(0, 0, 0, 0.5);
  position: absolute;
  color: #fff;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  padding: 10px;
}
/* Calculate column width */
.metro-ui-col {
  padding: 2px;
  float: left;
}
.metro-ui-col-10 {
  width: calc(100%);
}
.metro-ui-col-9 {
  width: calc(11.11111111%);
}
.metro-ui-col-8 {
  width: calc(12.5%);
}
.metro-ui-col-7 {
  width: calc(14.28571429%);
}
.metro-ui-col-6 {
  width: calc(16.66666667%);
}
.metro-ui-col-5 {
  width: calc(20%);
}
.metro-ui-col-4 {
  width: calc(25%);
}
.metro-ui-col-3 {
  width: calc(33.33333333%);
}
.metro-ui-col-2 {
  width: calc(50%);
}
.metro-ui-col-1 {
  width: calc(100%);
}
/* Keyframes */
.animated {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
.animated.infinite {
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
}
.animated.hinge {
  -webkit-animation-duration: 2s;
  animation-duration: 2s;
}
.animated.flipOutX,
.animated.flipOutY,
.animated.bounceIn,
.animated.bounceOut {
  -webkit-animation-duration: .75s;
  animation-duration: .75s;
}
@keyframes flipInX {
  from {
    left: -100%;
  }
  to {
    left: 0;
  }
}
.metro-ui-column .metro-ui-column-content.flipInX {
  -webkit-animation-name: flipInX;
  animation-name: flipInX;
  -webkit-backface-visibility: visible !important;
  backface-visibility: visible !important;
}
@keyframes flipOutX {
  from {
    -webkit-transform: perspective(400px);
    transform: perspective(400px);
  }
  30% {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 0deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 0deg);
    opacity: 1;
  }
  to {
    -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
    opacity: 0;
  }
}
.flipOutX {
  -webkit-animation-name: flipOutX;
  animation-name: flipOutX;
  -webkit-backface-visibility: visible !important;
  backface-visibility: visible !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="metro-theme-ui">
	<div class="metro-ui-row">
		<div class="metro-ui-col metro-ui-col-10">
			<div class="metro-ui-column"></div>
		</div>
	</div>
	<div class="metro-ui-row">
		<div class="metro-ui-col metro-ui-col-3" data-switch="true" data-switches='{"image": "https://cdn.elegantthemes.com/blog/wp-content/uploads/2016/02/rules-good-ui-design-web-project-thumbnail.png", "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."}, { "image": "http://www.fujitsu.com/fts/Images/28618-workplace-manager580x224_tcm21-1830661.jpg", "content": "Aliquam interdum sit amet nibh aliquet accumsan."}, { "image": "http://cdn.moneycrashers.com/wp-content/uploads/2013/03/manager2.jpg", "content": "Vestibulum sed metus eu justo sagittis congue." }'">
			<div class="metro-ui-column"></div>
		</div>
		<div class="metro-ui-col metro-ui-col-3">
			<div class="metro-ui-column"></div>
		</div>
		<div class="metro-ui-col metro-ui-col-3">
			<div class="metro-ui-column"></div>
		</div>
	</div>
	<div class="metro-ui-row">
		<div class="metro-ui-col metro-ui-col-3">
			<div class="metro-ui-column"></div>
		</div>
		<div class="metro-ui-col metro-ui-col-3">
			<div class="metro-ui-column"></div>
		</div>
		<div class="metro-ui-col metro-ui-col-3">
			<div class="metro-ui-column"></div>
		</div>
	</div>
</div>
like image 650
Red Avatar asked Dec 07 '22 18:12

Red


2 Answers

You can actually just pass a valid json object it should just work.

json = $("[data-json]").data("json");

console.log(typeof(json))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-switch="true" data-json='[{"key1": "value 1"}, {"key2": "value 2"}]'>
like image 151
rishipuri Avatar answered Dec 10 '22 07:12

rishipuri


You use valid JSON (which requires that you use double quotes, not single quotes, around keys and other strings). Then either retrieve with attr and parse with JSON.parse, or if you want to use jQuery's data store, use data to load it into that store and access it; data will parse it automatically. Note that data is not just an accessor for data-8 attributes, it's both more and less than that, so be sure to read the API docs for it and use it if you want its features, and don't use it if you don't.

Example:

var d = $("div[data-json]");
// Using `attr` and `JSON.parse`:
console.log(JSON.parse(d.attr("data-json")));
// Using jQuery'd data store
console.log(d.data("json"));
<div data-json='{"answer":42,"question":"Life, the Universe, and Everything!"}'></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Note that the attribute uses single quotes, so we can conveniently use double quotes in the JSON. But that would fail if we used ' in the JSON anywhere (such as in a string: "where":"Joe's house").

The text of attributes is HTML, not raw text. So if you're generating this JSON dynamically, perhaps in a server-side template or something, be sure that when it's output, it's output as HTML text, not raw text, to ensure that any necessary encoding is done. When you do that, the quotes may well be turned into &quot; entities, in which case there's no problem using " around the attribute value:

var d = $("div[data-json]");
// Using `attr` and `JSON.parse`:
console.log(JSON.parse(d.attr("data-json")));
// Using jQuery'd data store
console.log(d.data("json"));
<div data-json="{&quot;answer&quot;:42,&quot;question&quot;:&quot;Life, the Universe, and Everything!&quot;}"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
like image 27
T.J. Crowder Avatar answered Dec 10 '22 06:12

T.J. Crowder